\begindata{text,538369072} \textdsversion{12} \template{default} \define{global } \define{text menu:[Region~4,Text] attr:[FontFamily Andy Int 0]} \define{errordescrip } \define{error attr:[FontFamily AndyType Int 0]} \define{returnvalues } \define{footnote attr:[Flags OverBar Int Set] attr:[FontSize PreviousFontSize Point -2]} \text{\chapter{1 FLAMES: Filtering Language for the Andrew MEssage System} \section{1.1 About FLAMES} FLAMES is an extension language for the Andrew Message System. FLAMES can be used to write Lisp-like programs that automatically classify incoming mail. FLAMES can act on any message that arrives in a Mailbox. It acts on them as the mail is read -- as messages in the Mailbox are moved into appropriate folders. For example, you can write a FLAMES file that will sort mail from certain people into certain folders, or automatically post messages with special addresses to a bulletin board. You can also reject mail -- that is, bounce it back to the sender -- or you can automatically resend mail to additional destinations. The FLAMES language is built upon Eli, the Embedded Lisp Interpreter. Eli is a real Lisp interpreter, pared down, specifically designed for ``embedded'' use inside larger systems. Because of this two-level structure, there are two sets of primitives for programmers to learn. Eli itself provides most of the standard Lisp primitives, plus some string manipulation primitives. FLAMES provides primitives specific to the manipulation of incoming messages. \begindata{bp,539690440} \enddata{bp,539690440} \view{bpv,539690440,1583,0,0} \section{1.2 About This Document} This document contains user and programmer information about programming in FLAMES, as well as a reference list of FLAMES primitives and library functions. This document will \bold{not} teach you how to program in Lisp. If you are unfamiliar with Lisp, you should find a book designed to teach Lisp and learn from it. If you are using EZ to read this document, you can open an interactive Table of Contents window by choosing \bold{Table of Contents} from the \italic{Page} menu card. Clicking on a heading or index entry in the Table of Contents window scrolls this document to bring that heading or indexed item into view. Throughout this document, \italic{italics} indicate a parameter to a function, and \typewriter{typewriter} indicates a Lisp expression. Each primitive or library function is listed by name in alphabetical order within its section. The description of each function has several subsections, as follows: \text{______________________________________________________ \italic{1.4.0.1 FunctionName} ______________________________________________}}\text{________ \typewriter{(sample call of FunctionName from FLAMES)} \bold{Parameters} \leftindent{Description of this function's argument(s). \italic{Msg}, where it is one of a function's arguments, is left out of this section since it always means "the current message". (At this writing, FLAMES can only process one message at a time.)}\leftindent{ } \bold{Description} \leftindent{A brief description of the function, as well as various facts related to this function that are helpful to know. In general, the word "caller" refers to the MessageServer process being run by the user. } \bold{Return Value} \leftindent{Description of what this function returns. Includes conditions for return values where appropriate. If only one return value is listed, then either this function returns that value, or it encounters an error and doesn't return at all. } \bold{Defined In} \leftindent{If this function is defined in a FLAMES library file, this section will give the name of that file. If the function is defined in the MessageServer itself, this section will say "MessageServer (intrinsic)".} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-ORIGIN [FUNCTION-NAME (error description)]} A list of all the ways this function can halt due to an error condition. The \typewriter{typewriter} text is exactly what the MessageServer will say when it encounters one of the listed error conditions. If "None" is specified, then this function cannot fail, although a function it calls in turn may fail.} \bold{Known Bugs} \leftindent{What are the known bugs? What is the status of the known bugs?} \bold{See Also} \leftindent{A list of related FLAMES, ELI, or operating system functions, as well as documents that may be useful.}\leftindent{ } \bold{Example} \leftindent{A (usually) simple, practical example of this function, with commentary.} \begindata{bp,539690504} \enddata{bp,539690504} \view{bpv,539690504,1584,0,0} \section{1.3 Programming Information} \subsection{1.3.1 FLAMES filenames } By convention, FLAMES programs should have a ".flames" extension. In particular, the MessageServer looks for a FLAMES file called \leftindent{~/.AMS.flames} It is possible to make the MessageServer look at a different file by using the "check" command in CUI. See the section on Debugging, below. Since .flames files are written in Lisp, you might want to add the following lines to your .ezinit file (if you are using EZ): \example{ addfiletype .flames ltext } These will give you the ltext "Lisp mode" when editing files with a .flames extension. Note that if you add anything to your .ezinit file, you should be aware of the warnings in the \italic{initfiles} online help document. \subsection{1.3.2 How FLAMES Interacts with the MessageServer } FLAMES is built into the MessageServer; the default method for handling incoming mail is a short built-in FLAMES program that places your new mail into the folder "mail" or "misc". By providing a .AMS.flames file, you simply redefine the hook to this mail processing function. There is only one mail processing function; FLAMES assumes the first evaluated Lisp symbol in your .AMS.flames file is the name of this function. You can define many Lisp functions in your .AMS.flames file, but only the \bold{first} will be called by FLAMES. When processing of new messages in the Mailbox is initiated and your .AMS.flames file was previously read in, FLAMES first checks the modification date of your .AMS.flames file to see if it has been changed, and reads it in again if it has. This means you don't have restart the AMS program you are using for changes you've made to your .AMS.flames file to take effect. Next, the mail processing function you've defined is called on each of the messages in the Mailbox in turn. If your function returns NIL for a message, the MessageServer assumes that that message was not successfully placed in a folder, and will \bold{not} remove it from the Mailbox. If your function returns an expression other than NIL, the copy of the message in the Mailbox will be automatically deleted. It is up to you to ensure that if your FLAMES function returns T, it has placed the message somewhere! If, for some reason, your mail processing function has an error, the error will be noted by the MessageServer and processing will continue with the next message in the Mailbox. Once all the messages have been run through, you are notified how many succeeded and how many failed. All Lisp state information (symbol names & bindings, etc.) is retained between calls to your mail processing function. Even if you modify your FLAMES file and it is re-read, state information is not cleared. This can be useful; for example, you can count the number of messages that were successfully processed by incrementing a variable, and that variable will retain its value between calls the MessageServer makes to your mail processing function. \subsection{1.3.3 Loading Libraries} A library is a collection of useful routines which you can use which save you the trouble of having to write the routines yourself. There are libraries for both FLAMES and Eli; together they let you do just about anything you would want to do with a message. The Eli library contains Lisp routines for handling strings, and the FLAMES library contains Lisp routines for processing incoming mail. In order to use a FLAMES library, whether the standard library or the library of another user, you must "load" the library into the program. To do this, place a line like the following anywhere (except as the first Lisp expression) in your FLAMES file: \leftindent{\typewriter{(load "flib")}} "flib" is the name for the standard FLAMES library, but you can \typewriter{load} any FLAMES or Eli file, as you will see below. When the program is run, FLAMES searches for library files to load according to what is specified by the *.flamespath and *.elipath preferences in your preferences file. The default for the former is \typewriter{/usr/andrew/lib/flames} and the latter is \typewriter{/usr/andrew/lib/eli}. (Or, /usr/andrew is replaced by the value of ANDREWDIR.) You can replace or augment the defaults by changing your preferences. For example, you could put the following two lines in your preferences: \typewriter{\smaller{*.flamespath: /afs/andrew.cmu.edu/usr1/jbRo/flames:/usr/andrew/lib/flames *.elipath: /afs/andrew.cmu.edu/usr1/jbRo/eli:/usr/andrew/lib/eli}} With these preferences, the command \typewriter{(load "foo")} causes FLAMES to search for files to be loaded in the following places, in the following order, and load the first file it finds: \typewriter{/afs/andrew.cmu.edu/usr1/jbRo/flames/foo /afs/andrew.cmu.edu/usr1/jbRo/flames/foo.flames /usr/andrew/lib/flames/foo /usr/andrew/lib/flames/foo.flames /afs/andrew.cmu.edu/usr1/jbRo/eli/foo /afs/andrew.cmu.edu/usr1/jbRo/eli/foo.eli /usr/andrew/lib/eli/foo /usr/andrew/lib/eli/foo.eli} Because FLAMES only loads the first library file it finds, if you want to use more than one library you must include a separate \typewriter{load} statement for each library. \subsection{1.3.4 Coding requirements} The first thing in your ~/.AMS.flames file must be the "\typewriter{defun}" (function definition) of the actual function that will be called to process new mail from the Mailbox. All other code, including \typewriter{load} statements and auxiliary routines, should come after this primary defun. Note, however, that comments at the beginning of the FLAMES file are just fine. The reason for this restriction is that the MessageServer looks at the return value of the first expression in ~/.AMS.flames to determine the name of the function that will be called every time a new message is read in from your Mailbox. Since a "defun" statement returns the name of the function, it often is the best candidate for the first expression. However, in theory, the first expression in your FLAMES file could be something like \example{'my-mail-hook} in which case the MessageServer would take the return value of this expression (the symbol \typewriter{my-mail-hook}) as the name of the Mailbox processing function, and attempt to call this whenever new mail is read. Since a defun of my-mail-hook must appear somewhere in the file eventually, it usually makes sense to include it as the first expression in the file and avoid any possible errors or confusion. \bold{Note: } Literal Lisp strings in your FLAMES program longer than about 1200 characters may cause Eli to core dump. \subsection{1.3.5 Comments} Comments in Lisp are preceded by a semi-colon and continued to the end of the line. For example: \italic{\leftindent{; this is a comment.}} If you are using EZ with the ltext template, choosing \bold{Redo Lisp styles} from the \italic{Lisp} menu card after writing a comment will italicize the comments. \subsection{1.3.6 Data types} As in most Lisp systems, variables in Eli and FLAMES are dynamically typed. Eli provides the following data types: \leftindent{string integer list symbol} FLAMES adds one additional non-dynamic "magic" pseudo-type: \leftindent{message (only one instance: \typewriter{msg})} To get a handle on a message, a datum of this type is passed in as the only argument to the Mailbox-processing function by the MessageServer. The message pseudo-type used by FLAMES is actually an integer pointer. This horrendously mixes the C pointer type with the Eli integer type, making it amazingly easy to core dump any routine that expects a "message" type by passing it a random integer argument. The Eli type checking will catch the mistake if you pass the routine a string or list, but not if you pass it an integer that isn't really a message. Don't do it. }\ \begindata{bp,539690568} \enddata{bp,539690568} \view{bpv,539690568,1585,0,0} \section{1.4 FLAMES Functions }The following sections describe in detail all the FLAMES functions available. There are two sources for these functions: those functions built into the MessageServer, called ``primitives'', and those functions that are defined in the FLAMES library \typewriter{flib.flames}, called ``library functions''. Primitives can be used by your FLAMES program without any special preparation, while you must \typewriter{load} the \typewriter{flib.flames} library before you can use the functions defined therein. See section 1.3.3 \bold{Loading Libraries}, above, for instructions on loading a FLAMES library. \begindata{bp,539690888} \enddata{bp,539690888} \view{bpv,539690888,1586,0,0} \subsection{1.4.1 Putting a Message in a Folder }These functions, in general, place the current message into a folder or folders. \typewriter{add-to-folders} \leftindent{Attempts to perform an \typewriter{AppendMsgToDir} operation with \italic{msg} on each folder in \italic{folder-list}. } \typewriter{AppendMsgToDir} \indent{Adds message \italic{msg} to the specified \italic{folder-dir}. } \typewriter{FinalAppendMsgToDir} \leftindent{Attempts to rename \italic{msg} into \italic{folder-dir. } Copies \italic{msg} into \italic{folder-dir} instead if renaming fails. } \typewriter{post-by-keyword} \leftindent{Places msg into folders by keywords in its headers. If no keywords in keyword-map match, msg is placed into default-folder. } \typewriter{post-to-list} \leftindent{Places \italic{msg} into the folders specified in \italic{folder-list} after \italic{folder-list} has been validated and \italic{restrictions} have been satisfied. } \begindata{bp,539690376} \enddata{bp,539690376} \view{bpv,539690376,1587,0,10} ______________________________________________________ \paragraph{\index{1.4.1.1 add-to-folders}} ______________________________________________________ \typewriter{(add-to-folders \italic{msg folder-list})} \bold{Parameters} \leftindent{\italic{Folder-list} is a list of strings, each one containing the short name of a message folder.} \bold{Description} \leftindent{Attempts to perform an \typewriter{AppendMsgToDir} operation with \italic{msg} on each folder in \italic{folder-list}.} \leftindent{Returns \typewriter{T} if \italic{folder-list} is empty. If \typewriter{add-to-folders} returns NIL, it may have appended \italic{msg} to one or more folders before failing. See \bold{Notes} under the \typewriter{AppendMsgToDir} and \typewriter{FindFolder} primitives.} \bold{Return Value} \leftindent{\typewriter{T} if \typewriter{AppendMsgToDir} is successful for every folder in \italic{folder-list}. \typewriter{NIL} if one of the folders in \italic{folder-list} couldn't be found or is not writeable.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions }\leftindent{Same as\typewriter{ AppendMsgToDir }and \typewriter{FindFolder.}}\bold{ } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{AppendMsgToDir FindFolder}} \bold{Example} \leftindent{\typewriter{(add-to-folders msg '("~jbRo/.MESSAGES/mail.nuevo" "mail.yucca"))} will attempt to add \italic{msg} to jbRo's mail folders mail.nuevo and mail.yucca. } \begindata{bp,539690312} \enddata{bp,539690312} \view{bpv,539690312,1588,0,0} ______________________________________________________ \paragraph{\index{1.4.1.2 AppendMsgToDir}} ______________________________________________________ \typewriter{(AppendMsgToDir}\typewriter{\italic{ msg} \italic{folder-dir})} \bold{Parameters} \leftindent{\description{\italic{Folder-dir} is a string containing the fully specified name of a mail folder.} } \bold{Description} \indent{Adds message \italic{msg} to the specified \italic{folder-dir}.} \leftindent{You can use the \typewriter{FindFolder} primitive to convert short folder names like mail.bcc to full directory pathnames. Attempting to add a message to a folder that already contains that message with \typewriter{AppendMsgToDir} will not add the message, but will still return \typewriter{T}.} \bold{Return Value} \leftindent{T} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [APPENDMSGTODIR (finding dir for appending)]} Could not find the specified directory. No write access to directory. The specified directory is not a message folder. \typewriter{FLAMES-PRIMITIVE [APPENDMSGTODIR (couldn't append to dir)]} Could not write the message file into the directory.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{FinalAppendMsgToDir FindFolder } }\bold{Example} \leftindent{\typewriter{(AppendMsgToDir msg "/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail")} will copy the message \italic{msg} into the folder mail and return \typewriter{T}. } \begindata{bp,539690824} \enddata{bp,539690824} \view{bpv,539690824,1589,0,0} ______________________________________________________ \paragraph{\index{1.4.1.3 FinalAppendMsgToDir}} ______________________________________________________ \typewriter{(FinalAppendMsgToDir\italic{ msg folder-dir})} \bold{Parameters} \leftindent{\italic{Folder-dir} is a string containing the fully specified name of a mail folder.} \bold{Description} \leftindent{Attempts to rename \italic{msg} into \italic{folder-dir. } Copies \italic{msg} into \italic{folder-dir} instead if renaming fails. Useful only in certain situations; see below. You can use the \typewriter{FindFolder} primitive to convert short folder names like mail.bcc to full directory pathnames. Since \typewriter{FinalAppendMsgToDir} renames a file out of the Mailbox instead of copying it, this must be the last operation which attempts to place \italic{msg} into a folder. Further calls to \typewriter{AppendMsgToDir} or \typewriter{FinalAppendMsgToDir} will fail, since the message in question will no longer be in the Mailbox. It is never necessary to use \typewriter{FinalAppendMsgToDir}; \typewriter{AppendMsgToDir} will have the same result. However, \typewriter{FinalAppendMsgToDir} is marginally faster in some situations since the message does not have to be recopied. Any prior operation on \italic{msg} that changed the contents of the body or headers will cause \typewriter{FinalAppendMsgToDir} to automatically abandon renaming \italic{msg} out of the Mailbox and fall back to copying. } \bold{Return Value} \leftindent{T } \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [FINALAPPENDMSGTODIR (finding dir for appending)]} Could not find the specified directory. No write access to directory. The specified directory is not a message folder. \typewriter{FLAMES-PRIMITIVE [FINALAPPENDMSGTODIR (couldn't append to dir)]} Could not write the message file into the directory. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{FindFolder AppendMsgToDir}} \bold{Example} \leftindent{\typewriter{(FinalAppendMsgToDir msg "/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail") } attempts to rename the file containing \italic{msg} into the folder mail. If \italic{msg} cannot be renamed from the Mailbox to \italic{folder-dir} for any reason, \typewriter{FinalAppendMsgToDir} will copy \italic{msg} instead.} \begindata{bp,539690952} \enddata{bp,539690952} \view{bpv,539690952,1590,0,0} ______________________________________________________ \paragraph{\index{1.4.1.4 post-by-keyword}} ______________________________________________________ \typewriter{(post-by-keyword \italic{msg} \italic{default-folder} keyword-map) } \bold{Parameters} \leftindent{Default-folder is a string containing the name of a folder. Msg will be placed into this folder if it fails all of the tests in keyword-map.} \leftindent{Keyword-map is a list of headers-keywords-folders mappings, formatted as follows: '((("header1"..."headern") ("keyword1"..."keywordn") ("folder1"..."foldern")) . . . (("header1"..."headern") ("keyword1"..."keywordn") ("folder1"..."foldern"))) For each headers-keywords-folders clause, if at least one of the bodies of one of the headers header1...headern contains at least one of the keywords keyword1...keywordn, then msg will be placed in folders folder1...foldern.} \bold{Description} \leftindent{Places msg into folders by keywords in its headers. If no keywords in keyword-map match, msg is placed into default-folder. The headers-keywords-folders mappings are considered in sequence; if one matches, the rest of the mappings are not considered. The headers and keywords in the mappings are treated as regular expressions, not plain text. If a folder in a mapping does not exist and the mapping is satisfied, that folder will be created and a "new folder announcement" message will be placed into its parent. A description of "new folder announcement" messages can be found under Description for the CreateFolderFromMessage primitive. Information about using regular expressions can be found in the reg-exp Help document and /usr/andrew/doc/eli/Eli-RegExp.d.} \bold{Return Value} \leftindent{T if msg was placed in any folder. NIL if msg was not placed in any folders.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{re-strdecompose+ ELI primitive (in /usr/andrew/doc/eli/Eli-Primitives.d) \italic{reg-exp} Help document /usr/andrew/doc/eli/Eli-RegExp.d}\leftindent{ } \bold{Example} \leftindent{\typewriter{\smaller{(post-by-keyword msg "mail" '((("from" "received") ("zzF4" "eeKr") ("mail.friends")) (("subject") ("bug" "problem" "error") ("work.bugs")))) }}will place \italic{msg} into folder mail.friends if its From or Received headers contain the keyword "zzF4" or "eeKr". If not, \italic{msg} will be placed into folder work.bugs if the Subject header contains "bug", "problem", or "error". Otherwise, \italic{msg} will be placed into folder mail.} \begindata{bp,539691016} \enddata{bp,539691016} \view{bpv,539691016,1591,0,0} ______________________________________________________ \paragraph{\index{1.4.1.5 post-to-list}} ______________________________________________________ \typewriter{(post-to-list \italic{msg folder-list default-folder reject-to reject-cc reject-str allow-creation restrictions})} \bold{Parameters} \leftindent{\italic{Folder-list} is NIL or a list of strings, each one containing the name of a message folder. \italic{Default-folder} is NIL or a string containing the name of a message folder to be used if folder-list is NIL. \italic{Reject-to}, \italic{reject-cc} are strings containing addresses to which a rejected \italic{msg} will be sent. \italic{Reject-str} is a string that will be prepended to the body of a rejected \italic{msg}. \italic{Allow-creation} is \typewriter{T} or \typewriter{NIL.} Signals whether or not to create new folders when necessary. \italic{Restrictions} is a list of lists, each sublist a "restriction". \italic{Restrictions} has the format: \typewriter{'}\typewriter{\smaller{(((\italic{"folder-name-re\subscript{1}"}) (\italic{"user\subscript{1}" "user\subscript{2}"..."user\subscript{n}"}) \italic{"rejection text.\subscript{1}"}) ((\italic{"folder-name-re\subscript{2}"}) (\italic{"user\subscript{1}" "user\subscript{2}"..."user\subscript{n}"}) \italic{"rejection text.\subscript{2}"}) . . . ((\italic{"folder-name-re\subscript{n}"}) (\italic{"user\subscript{1}" "user\subscript{2}"..."user\subscript{n}"}) \italic{"rejection text.\subscript{n}"})) }}where a \italic{folder-name-re} is a string containing a regular expression ("re") that will be matched against the folder names in \italic{folder-list}, and \italic{user} is a string containing a re that will be matched against the authorized sender of msg. If a \italic{folder-name-re} matches the name of a folder in \italic{folder-list}, and the authorized sender of \italic{msg} does not match any corresponding \italic{user}, \italic{msg} is rejected to \italic{reject-to} and \italic{reject-cc} prepended by \italic{rejection text}.} \bold{Description} \leftindent{Places \italic{msg} into the folders specified in \italic{folder-list} after \italic{folder-list} has been validated and \italic{restrictions} have been satisfied. If \italic{folder-list} is \typewriter{NIL}, \italic{msg} is placed into \italic{default-folder.} If one of the restrictions in \italic{restrictions} is not satisfied, \italic{msg} is rejected back to the authorized sender using the rejection message in that restriction. If one or more of the folders in \italic{folder-list} could not be validated, \italic{msg} is rejected to the addresses in \italic{reject-to} and \italic{reject-cc}. \italic{Reject-str} is prepended to the body of the rejected \italic{msg}. If one or more of the folders in \italic{folder-list} do not exist, but can be created, and \italic{allow-creation} is \typewriter{NIL}, \italic{msg} is rejected to the addresses specified in \italic{reject-to} and \italic{reject-cc}. \italic{Reject-str}, " (creation not permitted) ", and the list of creatable folders are prepended to the body of the rejected \italic{msg}. If one or more of the folders in \italic{folder-list} do not exist, but can be created, and \italic{allow-creation} is \typewriter{T}, those folders will be created with \italic{msg} as their "folder creation announcement" message and \italic{msg} will be added to them.} \leftindent{Information about using regular expressions can be found in the \italic{regular-expressions} Help document and /usr/andrew/doc/eli/Eli-RegExp.d. This routine is an excellent one to study to learn FLAMES.} \bold{Return Value} \leftindent{\typewriter{T} if \italic{msg} was successfully added to all the folders in \italic{folder-list,} or, a rejection message was sent. \typewriter{NIL} if \italic{folder-list} and \italic{default-folder} are \typewriter{NIL}, or, one or more folders in \italic{folder-list} could not be validated and \italic{reject-str} is \typewriter{NIL}.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{None } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{re-strdecompose+} ELI primitive (in \italic{AndrewDir}/doc/eli/procs.doc) \italic{AndrewDir}/doc/eli/regexp.doc } \bold{Example} \leftindent{\typewriter{\smaller{(post-to-list msg (list "~jbRo/.MESSAGES/mail.inbox" "~zzF4/.MESSAGES/xferred.jello" (extract-liberally "jbRo\\\\+" (GetHeaderContents msg "to"))) "mail.lost" (ReplyAddr msg "sender") "zzF4+rejections.jello@andrew.cmu.edu" "This message was rejected due to a bad foldername." NIL '((("mail.gone-away") NIL "Mail.gone-away is now read-only.") (("mail.gone") ("jbRo" "zzF4" "eeKr") "You're not gone enough."))) }}This \typewriter{post-to-list} call will attempt to file \italic{msg} into jbRo's mail.inbox, zzF4's xferred.jello, and other folders the sender specified in her "To:" header. Since the \italic{allow-creation} parameter is \typewriter{NIL}, if the sender specified a nonexistent folder it will not be created. If the sender addressed the message to jbRo+mail.gone-away, then \italic{msg} will be rejected back to her with the text "Mail.gone-away is now read-only" prepended. If the sender addressed\italic{ msg} to jbRo+mail.gone, and is not one of jbRo, zzF4, or eeKr, \italic{msg} will be rejected back to her with the text "You're not gone enough" prepended to the body. Note that since mail.gone-away appears in \italic{restrictions} before mail.gone, its restriction will be considered first. If mail.gone appeared first, it would match mail.gone-away as well, and mail.gone-away's restriction would never be considered. } \begindata{bp,539691080} \enddata{bp,539691080} \view{bpv,539691080,1592,0,0} \subsection{1.4.2 Examining Parts of a Message }These functions allow you to examine specific portions of the current message. \typewriter{BodyLength} \leftindent{Returns the number of characters in the message body. } \typewriter{extract-liberally} \leftindent{Searches through \italic{stringlist} for pattern \italic{reg-expr}, extracting "suffixes" from \italic{stringlist}. Extracted suffixes are, typically, things like "borscht" in "jbRo+borscht@andrew.cmu.edu". } \typewriter{GetAuthSender} \leftindent{Gets the authenticated author of \italic{msg}, that is, the user that wrote \italic{msg} into the Mailbox. } \typewriter{GetAuthSenderCell} \leftindent{Gets the name of the AFS cell from which \italic{msg} originated. } \typewriter{GetCaption} \leftindent{Returns the current caption of \italic{msg}. } \typewriter{GetHeaderContents} \leftindent{Returns a list containing the body of the header(s) \italic{header-name} in msg. } \typewriter{GetHeaderList} \leftindent{Gets a list of all the headers in \italic{msg}. } \typewriter{GetPartialBody} \leftindent{Gets part of the body of the message. }\typewriter{multi-getheadercontents} \leftindent{Extracts the bodies of all instances of the headers specified in header-list from msg by repeatedly calling \typewriter{GetHeaderContents}. }\ \begindata{bp,539691144} \enddata{bp,539691144} \view{bpv,539691144,1593,441,0} ______________________________________________________ \paragraph{\index{1.4.2.1 BodyLength}} ______________________________________________________ \typewriter{(BodyLength \italic{msg})} \leftindent{ }\bold{Parameters} \leftindent{\italic{msg}} \bold{Description} \leftindent{Returns the number of characters in the message body. \typewriter{BodyLength} could be used in conjunction with \typewriter{GetPartialBody} to get at manageable chunks of a long message. Multimedia messages can contain objects like rasters and FAD animations that look small on the screen but contain a great deal of data. } \bold{Return Value}\leftindent{ Integer} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{GetPartialBody FileLength }} \bold{Example} \leftindent{\typewriter{(BodyLength msg)} called on a message whose body contains some text and a raster could return the integer \typewriter{\typewriter{34029}.}} \begindata{bp,539691208} \enddata{bp,539691208} \view{bpv,539691208,1594,0,0} ______________________________________________________ \paragraph{\index{1.4.2.2 extract-liberally}} ______________________________________________________ \typewriter{(extract-liberally reg-expr stringlist)} \bold{Parameters} \leftindent{\italic{Reg-expr} is a string containing a regular expression. \italic{Stringlist} is a list of strings, usually containing mail addresses, to be searched for the \italic{reg-expr} string.} \bold{Description} \leftindent{Searches through \italic{stringlist} for pattern \italic{reg-expr}, extracting "suffixes" from \italic{stringlist}. Extracted suffixes are, typically, things like "borscht" in "jbRo+borscht@andrew.cmu.edu". \typewriter{extract-liberally} considers the following characters to be terminators of suffixes: \typewriter{] @,:)\}>%;"! } (note that the space character is a terminator). This function internally uses the ELI primitive \typewriter{re-strdecompose+}, a very useful routine. } \bold{Return Value} \leftindent{A list of strings, each one containing a suffix extracted from \italic{stringlist}. \typewriter{NIL} if no suffixes could be extracted.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{re-strdecompose+} ELI primitive} \bold{Example} \leftindent{\typewriter{(extract-liberally "[A-Za-z][wW][0-9][A-Za-z0-9]\\\\+" (multi-getheadercontents msg '("received" "from"))) }will extract the suffixes from the list of strings returned by \typewriter{multi-getheadercontents}. Here, \typewriter{multi-getheadercontents} will return the bodies of all the Received: and From: headers in \italic{msg}. \typewriter{extract-liberally} will look through the bodies for patterns that match the specified regular expression. In this case, the regular expression matches sets of four certain characters, followed by a plus, that have a "w" or "W" as their second character (that is, CMU-style usernames of people whose last name begins with a "W"). If \typewriter{extract-liberally} finds a match, it will extract a suffix beginning at the character following the match and terminating at the character before one of a set of certain characters (see \bold{Descriptio\leftindent{n}}\leftindent{ above).}} \begindata{bp,539691272} \enddata{bp,539691272} \view{bpv,539691272,1595,0,0} ______________________________________________________ \paragraph{\index{1.4.2.3 GetAuthSender}} ______________________________________________________ \typewriter{(GetAuthSender\italic{ msg})} \bold{Parameters} \leftindent{\italic{msg}} \bold{Description} \leftindent{Gets the authenticated author of \italic{msg}, that is, the user that wrote \italic{msg} into the Mailbox. There is no AMS authentication for sites not running AFS. The AMS delivery mechanism "sends" a message to an AFS user by writing it into that user's "~/Mailbox" directory. \typewriter{GetAuthSender} looks at the writer of the file and usually returns that user's name as the "authorized" sender. An exception is a temporary failure of the delivery mechanism, where a message cannot be immediately written into the recipient's Mailbox by the senders's MessageServer. The message is placed instead into a global queue for later delivery by a postman daemon. Therefore, the file is written into the Mailbox by the user "postman", so \typewriter{GetAuthSender} will return the name of the user specified in the \typewriter{X-Andrew-Authenticated-as:} header instead of the writer of the file. There are other permutations of conditions which will flex the authentication mechanism; experiment with messages you send to yourself (\typewriter{unlog} is useful here) to determine how they may affect your FLAMES file.\typewriter{ } \typewriter{GetHeaderContents} could be used to find the "real" sender of a message which originated outside the AFS (and therefore has no authentication header) and was placed into the Mailbox by "postman" (the Mail daemon). \typewriter{ReplyAddr} can be used to get a reply address for a message. } \bold{Return Value} \leftindent{A string containing one of the following: \description{\description{Username of the authenticated author of the message. "\typewriter{"} if \italic{msg} is not authenticated. "\typewriter{"} if the username cannot be determined due to a temporary failure of the authentication mechanism; usually because of a network or AFS outage. However, this return value does indicate that the message was written into the Mailbox by an AFS user. "\typewriter{"} if the author has a valid AFS user id, but not a name. This can happen for a recently removed username, where the author wrote the message just before her name was removed from the White Pages. See the \italic{white-pages} Help doc for more information about the White Pages database.}} } \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs}\leftindent{ This routine will fail to give correct authentication information if it is used on a message that has previously been unformatted with a call to \typewriter{UnformatMessage}. See \bold{Known Bugs} for the \typewriter{UnformatMessage} primitive.} \bold{See Also} \leftindent{\typewriter{GetHeaderList GetHeaderContents multi-getheadercontents ReplyAddr unlog(1V)} man page}\typewriter{ } \bold{Example} \leftindent{\typewriter{(GetAuthSender msg) }would return the string "\typewriter{jbRo}" if AFS user jbRo wrote the message into the Mailbox and was authenticated when he did so.} \begindata{bp,539691336} \enddata{bp,539691336} \view{bpv,539691336,1596,0,0} ______________________________________________________ \paragraph{\index{1.4.2.4 GetAuthSenderCell}} ______________________________________________________ \typewriter{(GetAuthSenderCell\italic{ msg})} \bold{Parameters} \leftindent{\italic{msg}} \bold{Description} \leftindent{Gets the name of the AFS cell from which \italic{msg} originated. See \bold{Description} for the \typewriter{GetAuthSender} primitive. } \bold{Return Value} \leftindent{\description{A string containing the name of the AFS cell from which msg was sent, provided that the source and destination cells are both running the Andrew Message Delivery System (AMDS).} \description{\typewriter{NIL} if msg did not originate from a cell running AMDS, or it appears to be forged.} } \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\error{\typewriter{FLAMES-PRIMITIVE [GETAUTHSENDERCELL (allocating result)]} }Out-of-memory} \bold{Known Bugs} \leftindent{This routine will fail to give correct authentication information if it is used on a message that has previously been unformatted with a call to \typewriter{UnformatMessage}. See \bold{Known Bugs} for the \typewriter{UnformatMessage} primitive. } \bold{See Also} \leftindent{\typewriter{GetHeaderList GetAuthSender GetHeaderContents multi-getheadercontents ReplyAddr unlog(1V)} man page}\typewriter{ } \bold{Example} \leftindent{\typewriter{(GetAuthSenderCell msg) }would return the string "katana.org" if msg was sent by a user in AFS cell katana.org.} \begindata{bp,539691400} \enddata{bp,539691400} \view{bpv,539691400,1597,0,0} ______________________________________________________ \paragraph{\index{1.4.2.5 GetCaption}} ______________________________________________________ \typewriter{(GetCaption \italic{msg})} \bold{Parameters} \leftindent{\italic{msg} } \bold{Description} \leftindent{Returns the current caption of \italic{msg}.} \leftindent{\typewriter{GetCaption} will return the default caption if the caption has not been modified with \typewriter{SetCaption. }The caption is not permanent (i.e., it can be changed again) until an \typewriter{AppendMsgToDir} or equivalent call is made. Once \italic{msg} has been put in a folder, that copy is inviolate. Captions are not stored with the message file itself. They are kept in the \typewriter{.MS_MsgDir} file that describes the folder in which the message resides. If the \typewriter{.MS_MsgDir} file becomes damaged in some way and must be reconstructed, non-standard captions may be lost.} \bold{Return Value} \leftindent{String containing the current caption of \italic{msg}.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{SetCaption AppendMsgToDir}} \bold{Example} \leftindent{\typewriter{(GetCaption msg)} could return the string \typewriter{\smaller{"28-Nov-88 Re: diskless NeXT? (was Re:..-Jello Biafra@cs.cmu.edu (2149)"} }if the \italic{msg} was dated 28-Nov-88, had the subject \typewriter{"Re: diskless NeXT? (was Re: Oppys)",} was sent by user \typewriter{"Jello Biafra"} in mail domain \typewriter{cs.cmu.edu}, and had a length of \typewriter{2149} characters.} \begindata{bp,539691464} \enddata{bp,539691464} \view{bpv,539691464,1598,0,0} ______________________________________________________ \paragraph{\index{1.4.2.6 GetHeaderContents}} ______________________________________________________ \typewriter{(GetHeaderContents \italic{msg header-name})} \bold{Parameters} \leftindent{\italic{Header-name} is a string containing a complete, valid header name such as "\typewriter{received}". \italic{Header-name }must not include a colon.} \bold{Description} \leftindent{Returns a list containing the body of the header(s) \italic{header-name} in msg.} \leftindent{This function returns a list, not a string. The body of a header is the part following the name and intervening whitespace; for example, everything after "Date\typewriter{: }" , but doesn't include the terminating newline. The header region runs from the beginning of the message to the first blank line. \typewriter{GetHeaderList} can be used to extract all the headers and their bodies. \typewriter{multi-getheadercontents} can be used to extract the bodies of a list of header names at once.} \leftindent{\typewriter{GetCaption} can be used to extract the caption of a message.} \bold{Return Value} \leftindent{A list of strings, each string containing the body of one instance of the header \italic{header-name}. \typewriter{NIL} if the specified header cannot be found in \italic{msg}.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{GetHeaderList multi-getheadercontents GetCaption}} \bold{Example} \leftindent{\typewriter{(GetHeaderContents msg "to") }could return the list \typewriter{("jbRo+@andrew.cmu.edu, zzF4@zaphod.FrexiNet")}. Note this list has only one element, since there was only one occurrence of a \typewriter{To:} header in \italic{msg}. If there had been three \typewriter{To:} headers, \typewriter{GetHeaderContents} would have returned a list containing three strings.} \begindata{bp,539691528} \enddata{bp,539691528} \view{bpv,539691528,1599,0,0} ______________________________________________________ \paragraph{\index{1.4.2.7 GetHeaderList}} ______________________________________________________ \typewriter{(GetHeaderList \italic{msg})} \bold{Parameters} \leftindent{\italic{msg}} \bold{Description} \leftindent{Gets a list of all the headers in \italic{msg}.} \leftindent{This function returns a list, not strings. The body of a header is the part following the name and intervening whitespace; for example, everything after "\typewriter{Received: }". The body does not include the terminating newline character. The header region runs from the beginning of the message to the first blank line. \typewriter{GetHeaderContents} can be used to extract the bodies of only those headers with a specific name. \typewriter{multi-getheadercontents} can be used to extract the bodies of a list of header names at once. \typewriter{GetCaption} can be used to extract the caption of a message.} \bold{Return Value} \leftindent{A list of two-element sublists. Each sublist contains two strings: the name of a header, and the body of that header. The order of headers in the returned list is the same as their order in \italic{msg}.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [GETHEADERLIST (allocating array)]} Out-of-memory. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{GetHeaderContents multi-getheadercontents GetCaption }} \bold{Example} \leftindent{If \italic{msg} contains only three headers,\typewriter{(GetHeaderList msg)} could return the list \typewriter{\smaller{(("from" "jbRo+") ("to" "zzF4@halibut.unowho.edu") ("subject" "Fishin'"))}.} } \begindata{bp,539691592} \enddata{bp,539691592} \view{bpv,539691592,1600,0,0} ______________________________________________________ \paragraph{\index{1.4.2.8 GetPartialBody}} ______________________________________________________ \typewriter{(GetPartialBody \italic{msg start length})} \bold{Parameters} \leftindent{\italic{Start} is an integer containing the offset of the desired chunk of the message, in characters, from the beginning of the body of the message. \italic{Length} is an integer containing the length of the desired chunk of the message, in characters.} \bold{Description} \leftindent{Gets part of the body of the message.} \leftindent{\italic{Start} is the offset from the beginning of the body, not the beginning of the entire message. Multimedia messages can contain objects, like rasters and FAD animations, that have a clearly defined beginnings and ends. The data in these objects are meaningless if not kept whole, including the beginning/end demarcations. When dealing with messages of an unknown, but possibly large, size, it is a good idea to deal with relatively small fixed-size chunks of the message in a loop construct. It is best not to put the entire body of a two megabyte message into a single string. The \typewriter{BodyLength} function can be used to find the length in characters of the body of a message.} \bold{Return Value} \description{\leftindent{A string containing the requested chunk of the message.}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [GETPARTIALBODY (allocating body buffer)]} Out-of-memory. \typewriter{FLAMES-PRIMITIVE [GETPARTIALBODY (bad file portion specified)]} \italic{Start} is negative, \italic{length} is zero or negative, or \italic{start}+\italic{length} is greater than the size of the body. \typewriter{FLAMES-PRIMITIVE [GETPARTIALBODY (finding requested file portion)] FLAMES-PRIMITIVE [GETPARTIALBODY (reading requested file portion)]} Couldn't extract requested chunk of \italic{msg}. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{BodyLength}} \bold{Example} \leftindent{\typewriter{(GetPartialBody msg 0 140)} would return a string containing approximately the first two lines (140 characters) of the body of \italic{msg}.} \begindata{bp,539691656} \enddata{bp,539691656} \view{bpv,539691656,1601,0,0} ______________________________________________________ \paragraph{\index{1.4.2.9 multi-getheadercontents}} ______________________________________________________ \typewriter{(multi-getheadercontents \italic{msg }\italic{header-list})} \bold{Parameters} \leftindent{\italic{Header-list}} is a list of strings, each one containing the name of a header. \bold{Description} \leftindent{Extracts the bodies of all instances of the headers specified in header-list from msg by repeatedly calling \typewriter{GetHeaderContents}.} \leftindent{See Description for the \typewriter{GetHeaderContents }primitive.} \bold{Return Value} \leftindent{A list of strings, each one containing the body of one instance of a header specified in header-list. The specified header names must be lowercase and not include a colon, such as "received". NIL if no headers in msg match those in header-list.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{GetHeaderContents GetHeaderList}} \bold{Example} \leftindent{\typewriter{(multi-getheadercontents msg '("to" "from" "resent-to"))} will extract the bodies of the To:, From:, and Resent-To: headers, and return them as a list.} \begindata{bp,539691720} \enddata{bp,539691720} \view{bpv,539691720,1602,0,0} \subsection{1.4.3 Changing Parts of a Message }These functions allow you to change specific parts of the current message. \typewriter{AddHeader} \indent{Adds the header \italic{header} to \italic{msg}. } \typewriter{DeleteHeader} \leftindent{Strips the first header named \italic{header-name} from \italic{msg}. } \typewriter{SetCaption} \leftindent{Gives \italic{msg} the caption \italic{new-caption}, replacing the old caption if one exists. } \typewriter{UnformatMessage} \leftindent{Strips out all multimedia formatting from \italic{msg}, including headers describing such formatting. } \text{\ \begindata{bp,539691784} \enddata{bp,539691784} \view{bpv,539691784,1603,533,0}} ______________________________________________________ \paragraph{\index{1.4.3.1 AddHeader}} ______________________________________________________ \typewriter{(AddHeader\italic{ msg} \italic{header})} \bold{Parameters} \leftindent{\description{\italic{Header} is a string containing a properly-formatted message header.} } \bold{Description} \indent{Adds the header \italic{header} to \italic{msg}.} \leftindent{The provided \italic{header} should conform to the format for mail headers, as follows: the string should begin a sequence of characters not containing any whitespace. This is followed by a colon, a whitespace, then any text. The total header length should not, but may, exceed 80 characters. The header should not contain any newline characters. The provided \italic{header} is not checked for proper header syntax before being added to \italic{msg}. The provided \italic{header} is prepended to the list of headers in \italic{msg}. Headers other than the usual \typewriter{From:}, \typewriter{To:}, \typewriter{Subject:}, etc., should begin with \typewriter{X-} to distinguish them from standard mail headers. In general, it is not a good idea to add headers that describe the state of \italic{msg}, such as \typewriter{Date:}, \typewriter{From:}, \typewriter{Message-ID:}, etc., unless you know what you're doing. \typewriter{AddHeader} will permanently modify \italic{msg}, but its action can be undone by an appropriate call to \typewriter{DeleteHeader}. } \bold{Return Value} \leftindent{\typewriter{T}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [ADDHEADER (internal error)]} Out-of-memory. Couldn't re-parse \italic{msg}; added \italic{header} may have bad syntax or bad information.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{DeleteHeader GetHeaderList GetHeaderContents} } \bold{Example} \leftindent{\typewriter{(AddHeader msg "X-My-Quote-Of-The-Day: Luck is a Skill") } will add the header "X-My-Quote-Of-The-Day: Luck is a Skill" to the list of headers in \italic{msg}.} \begindata{bp,539691848} \enddata{bp,539691848} \view{bpv,539691848,1604,0,0} ______________________________________________________ \paragraph{\index{1.4.3.2 DeleteHeader}} ______________________________________________________ \typewriter{(DeleteHeader \italic{msg header-name})} \bold{Parameters} \leftindent{\italic{Header-name} is a string containing a complete, valid header name such as "\typewriter{received}". The specified header must exist in \italic{msg} , be lowercase, and not include a colon.} \bold{Description} \leftindent{Strips the first header named \italic{header-name} from \italic{msg}. The header to be removed must occur at least once in the header region of \italic{msg}. The header region runs from the beginning of the message to the first blank line. \typewriter{DeleteHeader} will permanently modify \italic{msg}, but its action can be undone by an appropriate call to \typewriter{AddHeader}. \typewriter{GetHeaderList} can provide an assoc list of all the headers in \italic{msg}. }\bold{Return Value} \leftindent{T} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [DELETEHEADER (internal error)]} No such \italic{header} in \italic{msg}. Out-of-memory. } \bold{Known Bugs} \leftindent{None } \bold{See Also} \leftindent{\typewriter{GetHeaderList AddHeader} } \bold{Example} \description{\leftindent{\typewriter{(DeleteHeader msg "subject") }removes the first \typewriter{Subject:} header from \italic{msg}.}} \begindata{bp,539691912} \enddata{bp,539691912} \view{bpv,539691912,1605,0,0} ______________________________________________________ \paragraph{\index{1.4.3.3 SetCaption}} ______________________________________________________ \typewriter{(SetCaption \italic{msg new-caption})} \bold{Parameters} \leftindent{\italic{New-caption} is a string that contains the new caption. Only the first 89 characters of \italic{new-caption} are used.} \bold{Description} \leftindent{Gives \italic{msg} the caption \italic{new-caption}, replacing the old caption if one exists. \typewriter{SetCaption} will not affect the captions of copies of \italic{msg} that have already been placed in folders by \typewriter{AppendMsgToDir. SetCaption} can be used to give the same message different captions in different folders.\typewriter{ }The \italic{new-caption} string is truncated to 89 characters. \typewriter{GetCaption} can be used to get the current caption. Captions are not stored within the message file itself. They are kept in the .\typewriter{MS_MsgDir} file that describes the folder in which the message resides. If the .\typewriter{MS_MsgDir} file becomes damaged in some way and must be reconstructed, non-standard captions may be lost. (Folder reconstruction is described in the \italic{cui-wizard} help document.) } \bold{Return Value} \leftindent{\typewriter{T}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None }\bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{GetCaption }} \bold{Example} \leftindent{\typewriter{(SetCaption msg "Here's a Message with spunk!")} will change the current caption of \italic{msg} to "\typewriter{Here's a Message with spunk!}".} \begindata{bp,539691976} \enddata{bp,539691976} \view{bpv,539691976,1606,0,0} ______________________________________________________ \paragraph{\index{1.4.3.4 UnformatMessage}} ______________________________________________________ \typewriter{(UnformatMessage \italic{msg})} \bold{Parameters} \leftindent{\italic{msg} } \bold{Description} \leftindent{Strips out all multimedia formatting from \italic{msg}, including headers describing such formatting. Headers that describe formatting include: \indent{ \typewriter{X-Scribe-Format}, \typewriter{X-If-Type-Unsupported,} and \typewriter{Content-Type}.} \typewriter{UnformatMessage} is a destructive operation; the formatting information removed from \italic{msg} cannot easily be recovered. } \bold{Return Value} \leftindent{\typewriter{T}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [UNFORMATMESSAGE (internal error)]} Error creating, writing, or closing temp file. Error reading message file. Problem "un-Scribing" (removing formatting from) file. }\bold{Known Bugs} \leftindent{This primitive destroys all authentication information related to \italic{msg} as well as formatting. As a result, the \typewriter{GetAuthSender} and \typewriter{GetAuthSenderCell} primitives will not give accurate authentication information for a message that has been unformatted. To work around this bug, be sure to extract all the authentication information you'll need from \italic{msg} \underline{before} you unformat it.} \bold{See Also} \leftindent{None} \bold{Example} \leftindent{\typewriter{(UnformatMessage msg)} called on a message containing boldface and italic text will remove the embedded formatting producing the typestyles and remove all headers describing the formatting.} \begindata{bp,539692040} \enddata{bp,539692040} \view{bpv,539692040,1607,0,0} \subsection{1.4.4 Examining Message Folders } \typewriter{ensure-folders-exist} \leftindent{Checks for the existence and writeability of the folders in \italic{folder-list}. If a folder in the list doesn't exist, an attempt is made to create it, optionally using \italic{msg} as the folder-creation announcement. } \typewriter{FindFolder} \leftindent{Attempts to find a fully-specified mail directory with the desired name and access. } \typewriter{validate-folder-list} \leftindent{"Validates" the folders in folder-list by checking each one (via \typewriter{FindFolder}) for writeability, or failing that, createability.} \begindata{bp,539692104} \enddata{bp,539692104} \view{bpv,539692104,1608,0,0} ______________________________________________________ \paragraph{\index{1.4.4.1 ensure-folders-exist}} ______________________________________________________ \typewriter{(ensure-folders-exist \italic{msg folder-list}) (ensure-folders-exist \italic{folder-list})} \bold{Parameters} \leftindent{\italic{Folder-list} is a list of strings, each one containing the short name of a mail folder. \italic{Msg} is optional, depending on the desired behavior.} \bold{Description} \leftindent{Checks for the existence and writeability of the folders in \italic{folder-list}. If a folder in the list doesn't exist, an attempt is made to create it, optionally using \italic{msg} as the folder-creation announcement. If \typewriter{ensure-folders-exist} returns \typewriter{NIL}, one or more of the specified folders may have been created before one failed. See \bold{Description} for the \typewriter{CreateFolderFromMessage} primitive for details on the format of a folder-creation announcement message.} \bold{Return Value} \leftindent{\typewriter{T} if all the folders exist and/or were successfully created. \typewriter{NIL} if one of the specified folders did not exist and could not be created.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{Same as \typewriter{CreateFolder} or \typewriter{CreateFolderFromMessage}, whichever is appropriate. Includes errors for \typewriter{FindFolder}. } \leftindent{\typewriter{FLAMES-LIB-FUNC [ENSURE-FOLDERS-EXIST (wrong # of args)]} Wrong number of arguments supplied.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{CreateFolder CreateFolderFromMessage}}\typewriter{\leftindent{ FindFolder}} \bold{Example} \leftindent{\typewriter{(ensure-folders-exist msg'("~jbRo/.MESSAGES/mail.nuevo" "~jbRo/.MESSAGES/mail.yucca"))} will attempt to create jbRo's mail folders mail.nuevo and mail.yucca if they do not already exist. If a folder is created, a new folder announcement message will be placed in that folder's parent since a \italic{msg} was supplied.} \begindata{bp,539692168} \enddata{bp,539692168} \view{bpv,539692168,1609,0,0} ______________________________________________________ \paragraph{\index{1.4.4.2 FindFolder}} ______________________________________________________ \typewriter{(FindFolder \italic{short-name access-desired})} \bold{Parameters} \leftindent{\italic{Short-name} is a string containing a folder name in short form, such as mail.bcc, or a mostly-specified pathname such as "/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail.bcc". \italic{Access-desired} is a string containing one of the following: \description{\description{\typewriter{r} looks for an existing, readable folder with the specified name. \typewriter{w} looks for an existing, writeable folder with the specified name. \typewriter{c} looks for the specified folder's parent, which must have its rights set to allow creation of a new folder within it. The folder specified by \italic{short-name} need not exist.}} } \bold{Description} \leftindent{Attempts to find a fully-specified mail directory with the desired name and access.} \leftindent{\typewriter{FindFolder} is useful for creating the fully-specified folder names required by certain other FLAMES functions. \italic{Short-name} can also be passed as a fully-specified pathname. Tilde user-directory completion is performed by this function. \italic{Access-desired} must consist of a lowercase character. \typewriter{FindFolder} checks along the defined \typewriter{mspath} (as read from the caller's ~/preferences file, or the default otherwise) to disambiguate folder names.} \bold{Return Value} \leftindent{String containing disambiguated full pathname of desired folder if it was found and caller has the specified access. \typewriter{NIL} if desired folder was not found or caller does not have desired access.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [FINDFOLDER (allocating folder-name buffer)]} Out-of-memory. \typewriter{FLAMES-PRIMITIVE [FINDFOLDER (bad file mode given)]} Specified access-desired was not one of lowercase \typewriter{c}, \typewriter{w}, or \typewriter{r}. \typewriter{FLAMES-PRIMITIVE [FINDFOLDER (can't check creatability of folder)]} A message-tree root was specified as the short-name with c specified as the access-desired , and the caller does not have access to create the tree root. \typewriter{FLAMES-PRIMITIVE [FINDFOLDER (can't disambiguate folder name)]} No access to check existence of a component of the desired path. Could not resolve a tilde (~) in the path; user specified may not exist. \typewriter{FLAMES-PRIMITIVE [FINDFOLDER (accessing dir)]} Problem checking caller's access for the requested folder. See \typewriter{access.2} in the man pages for possible error conditions.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{CreateFolder} } \bold{Example} \leftindent{\typewriter{(FindFolder "mail.keepers" "c")} could return the string\typewriter{ "/afs/andrew.cmu.edu/usr3/jbRo/mail/keepers"} if the folder mail exists and the caller has rights to add new folders to it.} \begindata{bp,539692232} \enddata{bp,539692232} \view{bpv,539692232,1610,0,0} ______________________________________________________ \paragraph{\index{1.4.4.3 validate-folder-list}} ______________________________________________________ \typewriter{(validate-folder-list \italic{folder-list})} \bold{Parameters} \description{\leftindent{\italic{Folder-list} is a list of strings, each one containing the short name of a folder.}} \bold{Description} \leftindent{"Validates" the folders in folder-list by checking each one (via \typewriter{FindFolder}) for writeability, or failing that, createability. Returns a list of three lists; see \bold{Return Value} below.}\indent{ \typewriter{validate-folder-list} does not attempt to create or modify any folders. See \bold{Description} for the \typewriter{FindFolder} primitive. } \bold{Return Value} \leftindent{A list of three lists of strings. The first list contains the full pathnames of message folders from \italic{folder-list} that are writeable. The second list contains the short names of folders that do not exist and cannot be created by the caller. The third list contains the full pathnames of folders that do not exist but can be created by the caller.} \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{Includes errors for \typewriter{FindFolder}. \typewriter{FLAMES-LIB-FUNC [VALIDATE-FOLDER-LIST (wrong # of args)]} Wrong number of arguments.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{FindFolder ensure-folders-exist create-folders }} \bold{Example} \leftindent{\typewriter{(validate-folder-list '("mail.is" "mail.was" "~zzF4/.MESSAGES/mail.will.be")) }could return the list: \typewriter{(("/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail/is") ("~zzF4/.MESSAGES/mail.will.be") ("/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail/was")) }if the caller has access to write to its existing folder mail.is, has access to create the non-existent folder mail.was, and does not have access to write to or create zzF4's mail.will.be folder.} \begindata{bp,539692296} \enddata{bp,539692296} \view{bpv,539692296,1611,0,0} \subsection{1.4.5 Creating Folders} \typewriter{CreateFolder} \leftindent{Creates a new message folder. } \typewriter{CreateFolderFromMessage} \leftindent{Creates a new message folder and adds \italic{msg} to it. A standard "new folder announcement" message is placed in the new folder's parent. } \typewriter{create-folders} \leftindent{Attempts to create the mail folders specified in \italic{folder-list} by repeatedly calling \typewriter{CreateFolderFromMessage} if a \italic{msg} is specified, or \typewriter{CreateFolder} if no \italic{msg} is specified. } \begindata{bp,539692360} \enddata{bp,539692360} \view{bpv,539692360,1612,0,0} ______________________________________________________ \paragraph{\index{1.4.5.1 CreateFolder}} ______________________________________________________ (\typewriter{CreateFolder} \italic{folder-dir}) \bold{Parameters} \leftindent{\italic{Folder-dir} is a string containing the fully specified name of a mail folder. The folder's parent must exist and be a message folder or message-tree root.} \bold{Description} \leftindent{Creates a new message folder. You can use the \typewriter{FindFolder} primitive to convert short folder names like mail.bcc to full directory pathnames. \typewriter{CreateFolder} will "overwrite" an existing folder if one is specified. Overwriting an existing message folder in this manner has no ill effects; no messages will be lost.} \bold{Return Value} \leftindent{\typewriter{T}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [CREATEFOLDER (internal error)]} \italic{Folder-dir} was passed as a short name, instead of a full pathname. Syntax or other error in pathname. Couldn't lock currently existing directory if overwriting; some other operation on it is in progress. Pathname is too long. No access for creating requested directory. Parent of specified folder is not a message directory.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{FindFolder CreateFolderFromMessage }} \bold{Example} \leftindent{\typewriter{(CreateFolder "/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail/nuevo") }will create the folder mail.nuevo and return \typewriter{T}.} \begindata{bp,539692424} \enddata{bp,539692424} \view{bpv,539692424,1613,0,0} ______________________________________________________ \paragraph{\index{1.4.5.2 CreateFolderFromMessage}} ______________________________________________________ \typewriter{(CreateFolderFromMessage }\typewriter{\italic{folder-dir msg}}\typewriter{)} \bold{Parameters} \leftindent{\italic{Folder-dir} is a string containing the fully specified name of the mail folder that is to be created.} \bold{Description} \leftindent{Creates a new message folder and adds \italic{msg} to it. A standard "new folder announcement" message is placed in the new folder's parent. A new folder announcement is not added for the creation of a top-level folder, since such folders do not have parents. You can use the \typewriter{FindFolder} primitive to convert short folder names like mail.bcc to full directory pathnames. In creating the "new folder announcement" message, the headers "\typewriter{X-Andrew-DirectoryCreation: }\italic{folder-dir}" , "\typewriter{Subject:} \italic{folder-name}", and a few lines of text stating that a new folder has been created are inserted into the message. The headers of \italic{msg} itself are not modified by this primitive. \typewriter{CreateFolderFromMessage} will overwrite an existing folder if a duplicate name is specified. Overwriting an existing message folder in this manner causes no ill effects; no messages will be lost. However, a "new folder announcement" message will be put into the parent directory even if a similar message exists.} \bold{Return Value} \leftindent{T } \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [CREATEFOLDERFROMMESSAGE (creating new dir)]} \italic{Folder-dir} was passed as a short name, instead of a full pathname. Syntax error in pathname. Couldn't lock currently existing directory if overwriting; some other operation on it is in progress. Pathname is too long (>1024 characters). Insufficient access to create a folder. Parent of specified folder is not a message directory. \typewriter{FLAMES-PRIMITIVE [CREATEFOLDERFROMMESSAGE (adding announcement to parent)]} Probably out-of-memory.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{FindFolder CreateFolder }} \bold{Example} \leftindent{\typewriter{(CreateFolderFromMessage "/afs/andrew.cmu.edu/usr3/jbRo/.MESSAGES/mail/nuevo" msg) }will create the folder mail.nuevo, put \italic{msg} into it, and put a "new folder announcement" based on \italic{msg} into the folder mail.} \begindata{bp,539692488} \enddata{bp,539692488} \view{bpv,539692488,1614,0,0} ______________________________________________________ \paragraph{\index{1.4.5.3 create-folders}} ______________________________________________________ \typewriter{(create-folders \italic{msg folder-list}) (create-folders \italic{folder-list})} \bold{Parameters} \leftindent{\italic{Folder-list} is a list of strings, each one containing the short name of a mail folder. \italic{Msg} is optional, depending on the desired behavior.} \bold{Description }\leftindent{Attempts to create the mail folders specified in \italic{folder-list} by repeatedly calling \typewriter{CreateFolderFromMessage} if a \italic{msg} is specified, or \typewriter{CreateFolder} if no \italic{msg} is specified.}\bold{ Returns }\leftindent{T if folder-list is empty.}\bold{ }\leftindent{ If msg is supplied, create-folders will use the CreateFolderFromMessage primitive, otherwise it will use the CreateFolder primitive. If create-folders returns NIL, one or more of the specified folders may have been created before one failed. See Description for the CreateFolderFromMessage and CreateFolder primitives. T if CreateFolderFromMessage (or CreateFolder, if appropriate) is successful for every folder in folder-list. NIL if one of the specified folders cannot be created. } \bold{Defined In} \typewriter{\leftindent{flib.flames}} \bold{Error Conditions} \leftindent{Same as CreateFolderFromMessage or CreateFolder, whichever is appropriate. Also see FindFolder's errors. \typewriter{FLAMES-LIB-FUNC [CREATE-FOLDERS (wrong # of args)]} Wrong number of arguments supplied.}\bold{ Known Bugs }\leftindent{None}\bold{ See Also }\leftindent{\typewriter{CreateFolderFromMessage CreateFolder FindFolder}}\bold{ Example }\leftindent{\typewriter{(create-folders '("mail.nuevo""~zzF4/.MESSAGES/mail.yucca")) }will attempt to create the message folders mail.nuevo (in the caller's tree) and mail.yucca (in zzF4's tree) using the CreateFolder primitive.} \begindata{bp,539692552} \enddata{bp,539692552} \view{bpv,539692552,1615,0,0} \subsection{1.4.6 Obtaining Mail Addresses} Functions that handle mail address validation and generation. \typewriter{ReplyAddr} \leftindent{Gets the reply address for \italic{msg}. } \typewriter{ValidateAddr} \leftindent{Accepts a string and tests it for validity as a mail address. If possible, \typewriter{ValidateAddr} will convert a poorly-formed or non-canonical address to one that conforms to RFC 822, Section 6: Address Specifications.} \begindata{bp,539692616} \enddata{bp,539692616} \view{bpv,539692616,1616,0,0} ______________________________________________________ \paragraph{\index{1.4.6.1 ReplyAddr}} ______________________________________________________ \typewriter{(ReplyAddr\italic{ msg reply-type})} \bold{Parameters} \leftindent{\italic{Reply-type} is a string which specifies what kind of reply address is desired: }\description{\leftindent{\indent{\typewriter{s} asks for the reply-to-sender address. \typewriter{r} asks for the reply-to-readers address. This will, for example, return the address of the newsgroup to which \italic{msg} was posted. \typewriter{a} asks for the reply-to-all address(es). This address will, in general, apply to both senders and readers, not including the address of the caller.}} } \bold{Description} \leftindent{Gets the reply address for \italic{msg}. \italic{Reply-type} can be uppercase or lowercase. \typewriter{ReplyAddr} will make an effort to remove the caller's address and duplicate addresses from the returned address string, if they are present. \typewriter{GetHeaderContents} can be used to directly extract the body of the \typewriter{From:} or \typewriter{Return-Path:} header. } \bold{Return Value} \leftindent{A string containing the desired address. \typewriter{NIL} if the desired address does not exist or cannot be determined.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [REPLYADDR (constructing reply-to-all addresses)]} Out-of-memory. \typewriter{FLAMES-PRIMITIVE [REPLYADDR (bad mode specified)]} Requested \italic{reply-type} was not one of \typewriter{s}, \typewriter{r}, or \typewriter{a}. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{GetHeaderContents}} \bold{Example} \leftindent{\typewriter{(ReplyAddr msg "s")} could return the string "\typewriter{jbRo+@andrew.cmu.edu}" if user jbRo sent the message.} \begindata{bp,539692680} \enddata{bp,539692680} \view{bpv,539692680,1617,0,0} ______________________________________________________ \paragraph{\index{1.4.6.2 ValidateAddr}} ______________________________________________________ \typewriter{(ValidateAddr doubtful-address)} \bold{Parameters} \leftindent{\italic{doubtful-address} is a string containing a mail address that is to be ``validated''.} \bold{Description} \leftindent{This routine accepts a string and tests it for validity as a mail address. If possible, \typewriter{ValidateAddr} will convert a poorly-formed or non-canonical address to one that conforms to RFC 822, Section 6: Address Specifications. The supplied address (or comma-separated addresses) in \italic{doubtful-address is} checked and adjusted in the following ways: \description{Syntax is checked. The mail domain (i.e., everything after ``@'') is checked for existence and made complete. If the mail domain is ``local'', that is, the same as the sender's mail domain, or the mail domain is also the name of an AFS cell that is running the \italic{White Pages} (q.v.), or the mail domain is not specified, then the addressee's userid is checked for existence. The addressee's full name, if it can be determined, is appended to the supplied address. Various special addressing schemes are checked for validity, including ``+dist+'' and ``+dir-insert+'' forms.} } \bold{Return Value} \leftindent{\typewriter{(success-code address-or-error-string)} A list of two elements: the first element is an integer \italic{success-code}; the second \italic{address-or-error-string} element is either a validated address string (if \italic{success-code} is zero) or an English explanation of why the \italic{doubtful-address} could not be validated. The possible values of the integer \italic{success-code} (the first element of the returned list) are: \description{\typewriter{0} (no error) All parts of the supplied \italic{doubtful-address} were successfully validated. \italic{address-or-error-string} will contain the validated address. \typewriter{1} (uncertain error) \typewriter{ValidateAddr} is uncertain about whether certain special parts of the supplied \italic{doubtful-address} are valid. Examine the returned error in \italic{address-or-error-string} for details. \typewriter{2} (temporary error) Out-of-memory. The White Pages database for a remote AFS mail domain specified in \italic{doubtful-address }is temporarily unavailable or unusable; a file server may be down. Other temporary failures; examine returned error in \italic{address-or-error-string} for details. \typewriter{3} (fatal error) Bad address syntax in supplied \italic{doubtful-address}. No such mail domain, no such user, ambiguous user name, the local White Pages is unavailable or unusable, can't find the file containing a distribution list for a distibution-list address, can't find the directory for a dir-insert address, no AFS group supplied for an AFS-group address. Other severe errors; examine the returned error in \italic{address-or-error-string} for details.} } \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions}\leftindent{ \typewriter{FLAMES-PRIMITIVE [VALIDATEADDR (Couldn't get user's pw entry)] }Couldn't find the name of the caller in the local passwd file. Other error conditions for \typewriter{ValidateAddr} are specified in \bold{Return Value}, above. }\bold{Known Bugs} \leftindent{None} \bold{See Also}\leftindent{ RFC 822 ("Request-for-Comments #822") Section 6, Address Specification. \italic{white-pages} help document} \bold{Example} \leftindent{\typewriter{(validateaddr "J.Biafra, zzF4@katana.org, lauren@andrew") }might return the list (0 "\\"Jello Biafra\\" , zzF4@CSA.KATANA.ORG, \\"Hollan Lauren\\" ") (Note that the backslashes ``\\'' above are used to escape the double-quotes ``"'' embedded in the returned Lisp string. They will not appear in the actual address.)}\leftindent{\typewriter{ }if J.Biafra and lauren can be uniquely found in the local White Pages as Jello Biafra and Hollan Lauren, respectively, and the host katana.org has the host-translation CSA.KATANA.ORG. No attempt is made to check for existence of user zzF4 at katana.org, since katana.org is not an AFS cell with a White Pages database. This example could have failed (returned a non-zero \italic{success-code})if either J.Biafra or lauren couldn't be found or were ambigous names, or the host katana.org didn't exist or couldn't be found in the host tables.} \begindata{bp,539692744} \enddata{bp,539692744} \view{bpv,539692744,1618,0,0} \subsection{1.4.7 Rejecting or Resending a Message} Functions that reject or resend the current message. \typewriter{RejectMessage} \leftindent{"Rejects" a message. The message, prefaced by \italic{text} and a rejection notice, is forwarded to the address(es) specified in \italic{reject-to} and \italic{reject-cc. }} \typewriter{ResendMessage} \leftindent{Resends \italic{msg} to the address specified after adding appropriate ReSent headers. } \typewriter{TracelessResendMessage} \leftindent{Resends \italic{msg} to the address specified by \italic{to}. Doesn't add any headers and attempts to minimize changes to existing headers.} \begindata{bp,539692808} \enddata{bp,539692808} \view{bpv,539692808,1619,0,0} ______________________________________________________ \paragraph{\index{1.4.7.1 RejectMessage}} ______________________________________________________ \typewriter{(RejectMessage \italic{msg reject-to reject-cc text})} \bold{Parameters} \leftindent{\italic{Reject-to }and\italic{ reject-cc} are strings containing mail addresses to which \italic{msg} should be forwarded or CCed. They can be empty or \typewriter{NIL}; see \bold{Notes} below. \italic{Text} is a string that will be prepended to the body of \italic{msg} before it is sent.} \bold{Description} \leftindent{"Rejects" a message. The message, prefaced by \italic{text} and a rejection notice, is forwarded to the address(es) specified in \italic{reject-to} and \italic{reject-cc.}} \leftindent{\typewriter{RejectMessage} does not change the contents of the headers or body of \italic{msg}, but the headers of the "rejected" copy will be changed. The forwarded message will contain the following text as its first two lines: \typewriter{\indent{"The following message was delivered properly, but was automatically rejected by the recipient's message server for the following reason:".}} These lines are followed by the contents of \italic{text}, then the line \typewriter{\indent{"-- The rejected message is shown below --". }}Finally, the original body of \italic{msg} is appended. If\italic{ reject-cc} is an empty string,\italic{ msg} gets CCed to the user Bboard.Maintainer. If \italic{reject-cc} is NIL, no CC is sent. If\italic{ reject-to} is NIL or an empty string, the rejected message is sent to the address specified in the \typewriter{Return-Path: }header of \italic{msg}. \typewriter{(ReplyAddr msg "s")} can be used to find the reply-to-sender address for \italic{ msg}. It is not recommended to have a slash ("/") as the first character of \italic{reject-to} unless you are purposely rejecting a message to a directory instead of a user. }\bold{Return Value} \leftindent{T} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [REJECTMESSAGE (internal error)]} Out-of-memory. Couldn't extract body of \italic{msg}. Couldn't create, write to, or close temp file. Couldn't send the forwarded message. } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{ResendMessage DropoffFile DropoffMessage TracelessResendMessage ReplyAddr}} \bold{Example} \leftindent{\typewriter{(RejectMessage msg "jbRo" "zzF4" "Message was too hard to read.")} will prepend the text \typewriter{"Message was too hard to read."} (along with a built-in rejection message, see below) to the body of \italic{msg}, then forward \italic{msg} to user jbRo and carbon-copy \italic{msg} to user zzF4.} \begindata{bp,539692872} \enddata{bp,539692872} \view{bpv,539692872,1620,0,0} ______________________________________________________ \paragraph{\index{1.4.7.2 ResendMessage}} ______________________________________________________ \typewriter{(ResendMessage \italic{msg to})} \bold{Parameters} \leftindent{\italic{To} is a string containing the address to which \italic{msg} will be sent.} \bold{Description} \leftindent{Resends \italic{msg} to the address specified after adding appropriate ReSent headers. Has other side effects; see below. \typewriter{ResendMessage} strips all previous \typewriter{Received:} and some \typewriter{X-Andrew-Authenticated-as:} headers from \italic{msg} before resending it. It adds the headers \typewriter{ReSent-From:}, \typewriter{ReSent-To:}, and \typewriter{ReSent-Date:}. Modifications that \typewriter{ResendMessage} makes to \italic{msg}'s headers are permanent. \typewriter{TracelessResendMessage} can be used to resend \italic{msg} with minimal header changes. }\bold{Return Value} \leftindent{T} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [RESENDMESSAGE (internal error)]} Couldn't create, write to, or close temp file. Out-of-memory. Couldn't send the message. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{TracelessResendMessage DropoffFile DropoffMessage RejectMessage }} \bold{Example} \leftindent{\typewriter{(ResendMessage msg "jbRo+@andrew.cmu.edu")} would send \italic{msg} to user jbRo after adding \typewriter{ReSent-From:}, \typewriter{ReSent-To:},and \typewriter{ReSent-Date:} headers.} \begindata{bp,539692936} \enddata{bp,539692936} \view{bpv,539692936,1621,0,0} ______________________________________________________ \paragraph{\index{1.4.7.3 TracelessResendMessage}} ______________________________________________________ \typewriter{(TracelessResendMessage\italic{ msg to})} \bold{Parameters} \leftindent{\italic{To} is a string containing the address to which \italic{msg} will be sent.} \bold{Description} \leftindent{Resends \italic{msg} to the address specified by \italic{to}. Doesn't add any headers and attempts to minimize changes to existing headers. Authentication headers can only be left unchanged by the postman user, or for messages that the caller sends to itself. ResendMessage will resend a message, adding the usual \typewriter{ReSent} headers. } \bold{Return Value} \leftindent{T} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [TRACELESSRESENDMESSAGE (internal error)]} Couldn't create, write to, or close temp file. Out-of-memory. Couldn't send the message. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{ResendMessage RejectMessage DropoffFile DropoffMessage }} \bold{Example} \leftindent{\typewriter{(TracelessResendMessage msg "jbRo")} will resend \italic{msg} to user jbRo without adding any \typewriter{ReSent} headers. \typewriter{Return-path} headers will be unchanged, but authentication headers will be updated to indicate that this message was resent by the caller, not sent by the user specified in the \typewriter{From:} header.} \begindata{bp,539693000} \enddata{bp,539693000} \view{bpv,539693000,1622,0,0} \subsection{1.4.8 Originating a Message } Functions that can create and send a new message. \typewriter{DropoffFile} \leftindent{"Drops off" a file for delivery to the addresses in \italic{to-list}. The delivery is not actually performed by this routine, the file \italic{filename} is simply given to the site's delivery mechanism. } \typewriter{DropoffMessage} \leftindent{"Drops off" a \italic{message-string} (string) for delivery to the addresses in \italic{to-list}. The delivery is not actually performed by this routine, the message is simply given to the site's delivery mechanism.} \begindata{bp,540340232} \enddata{bp,540340232} \view{bpv,540340232,1623,0,0} ______________________________________________________ \paragraph{\index{1.4.8.1 DropoffFile}} ______________________________________________________ \typewriter{(DropoffFile \italic{to-list filename})} \bold{Parameters} \leftindent{\italic{to-list} is a list of strings. Each string contains a recipient's address. Supplied addresses are \underline{not} checked for validity. \italic{filename} is a string containing the full pathname of a file to be delivered to the addresses in \italic{to-list}.} \bold{Description} \leftindent{"Drops off" a file for delivery to the addresses in \italic{to-list}. The delivery is not actually performed by this routine, the file \italic{filename} is simply given to the site's delivery mechanism. \typewriter{DropoffFile} sends the file you supply, \underline{verbatim}. If you are sending a short message, you may want to use \typewriter{DropoffMessage} instead, which takes a string containing the entire text of the message instead of a filename. It is recommended that you supply at least the \typewriter{To:}, \typewriter{From:}, and \typewriter{Subject:} headers in the file \italic{filename.} In sending the message, the following headers might be prepended to the file \italic{filename} by the dropoff process: \typewriter{Return-path:}, \typewriter{X-Andrew-Authenticated-as:}, and \typewriter{Received:}. The headers of a message are separated from the message body by a blank line You can use the \typewriter{(GetParameter "date")} primitive to assist in constructing a \typewriter{Date:} header for your message. Use the \typewriter{ValidateAddr} primitive to check an address for validity.} \bold{Return Value} \leftindent{A list of two elements. The first element is an integer from 1 to 8, inclusive, that your FLAMES program can check to determine the success of the dropoff. The meaning of each integer is described below. The second element is a string containing an English text description of the relative success of the dropoff. \bold{Integer Return Codes} (the first element of the returned list) \error{\typewriter{1}} Dropped off OK. \error{\typewriter{2}} Dropped off OK, but there was a minor problem. A \typewriter{~/.Outgoing} directory may have had to have been created. \error{\typewriter{3}} The message file couldn't be placed in a global queue, so it was placed in \typewriter{~/.Outgoing} for processing by the local (workstation) queue. \error{\typewriter{4}} The message file couldn't be queued. A server may be down, or the user's home directory doesn't reside on AFS and no \typewriter{~/.Outgoing} directory exists. \error{\typewriter{5}} The dropoff procedure was given bad information. Since the \typewriter{DropoffFile} primitive checks the parameters you supply, you should never get this return code. \error{\typewriter{6}} Temporary failure of the dropoff mechanism. You can try again later; a server may be down. \error{\typewriter{7}} The file specified by \italic{filename} does not exist or cannot be read. \error{\typewriter{8}} Catch-all return code for generic errors.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [DROPOFFFILE ("to" list is empty)] }No addresses specified in \italic{to-list}. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Couldn't allocate memory for copy of recipients)] }Out-of-memory. \typewriter{FLAMES-PRIMITIVE [DROPOFFFILE (Destination address is not a string)] }One of the elements of \italic{to-list} is not a string. \typewriter{FLAMES-PRIMITIVE [DROPOFFFILE (Couldn't allocate memory for copy of address)] }Out-of-memory} \bold{Known Bugs} \leftindent{None} \bold{See Also} \typewriter{\leftindent{RejectMessage ResendMessage DropoffMessage TracelessResendMessage GetParameter}} \bold{Example} \leftindent{\typewriter{(DropoffFile ("jbRo+@psy.cmu.edu" "zzF4") "/afs/andrew/usr/rgLd/mailtemp") }would attempt to send the file /afs/andrew/usr/rgLd/mailtemp to the above addresses, and might return a list whose first element is the integer \typewriter{7} if the file does not exist.} \begindata{bp,540340296} \enddata{bp,540340296} \view{bpv,540340296,1624,0,0} ______________________________________________________ \paragraph{\index{1.4.8.2 DropoffMessage}} ______________________________________________________ \typewriter{(DropoffMessage \italic{to-list message-string})} \bold{Parameters} \leftindent{\italic{to-list} is a list of strings. Each string contains a recipient's address. Supplied addresses are \underline{not} checked for validity. \italic{message-string} is a string containing the entire text of the message you wish to send, including headers and the message body. \typewriter{DropoffMessage} ignores the contents of this string, but the recipient's mailer software may become confused if you supply headers that are contradictory or meaningless.} \bold{Description} \leftindent{"Drops off" a \italic{message-string} (string) for delivery to the addresses in \italic{to-list}. The delivery is not actually performed by this routine, the message is simply given to the site's delivery mechanism. \typewriter{DropoffMessage} sends the \italic{message-string} you supply, verbatim. If you are sending a large message, you may want to write it into a file with \typewriter{WriteFile} and use the \typewriter{DropoffFile} primitive instead, since the entire message must be held in memory as a string by \typewriter{DropoffMessage}. It is recommended that you supply at least the \typewriter{To:}, \typewriter{From:}, and \typewriter{Subject:} headers in \italic{message-string}. In sending the message, the following headers might be automatically prepended to \italic{message-string} by the dropoff process: \typewriter{Return-path:}, \typewriter{X-Andrew-Authenticated-as:}, and \typewriter{Received:}. The headers of a message are separated from the message body by a blank line. You can use the \typewriter{(GetParameter "date")} primitive to assist in constructing a \typewriter{Date:} header for your message. Use the \typewriter{ValidateAddr} primitive to check an address for validity.} \bold{Return Value} \leftindent{A list of two elements. The first element is an integer from 1 to 8, inclusive, that your FLAMES program can check to determine the success of the dropoff. The meaning of each integer is described below. The second element is a string containing an English text description of the relative success of the dropoff. \bold{Integer Return Codes} (the first element of the returned list) \error{1} Dropped off OK. \error{2} Dropped off OK, but there was a minor problem. A \typewriter{~/.Outgoing} directory may have had to have been created. \error{3} The message couldn't be placed in a global queue, so it was placed in \typewriter{~/.Outgoing} for processing by the local (workstation) queue. \error{4} The message couldn't be queued. A server may be down, or the user's home directory doesn't reside on AFS and no \typewriter{~/.Outgoing} directory exists. \error{5} The dropoff procedure was given bad information. Since the \typewriter{DropoffMessage} primitive checks the parameters you supply, you should never get this return code. \error{6} Temporary failure of the dropoff mechanism. You can try again later; a server may be down. \error{7} The temporary file written by \typewriter{DropoffMessage} to hold the message could not be read by the dropoff mechanism. \error{8} Catch-all return code for generic errors.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE ("to" list is empty)]} No addresses specified in \italic{to-list}. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Couldn't allocate memory for copy of recipients)]} Out-of-memory. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Destination address is not a string)]} One of the elements of \italic{to-list} is not a string. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Couldn't allocate memory for copy of address)]} Out-of-memory \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Couldn't get a temporary filename)]} Internal error. Couldn't generate a name for the temporary file the message is written into. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (Couldn't open a temporary file)]} Internal error. Couldn't open the temporary file the message is written into. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (writing data)]} Couldn't write the message into a temp file. Filesystem may be full. \typewriter{FLAMES-PRIMITIVE [DROPOFFMESSAGE (closing file)]} Internal error. Couldn't close the temp file the message is written into.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{RejectMessage ResendMessage DropoffFile TracelessResendMessage GetParameter}} \bold{Example} \leftindent{\typewriter{(DropoffMessage ("jbRo+@psy.cmu.edu" "zzF4") "From: Hank To: jello, zzF4 Subject: test This is a test of a dropoff message FLAMES primitive.") }attempts to send the above message to the above addresses, and might return a list whose first element is the integer \typewriter{1} if the dropoff process was successful. Note that the \typewriter{To:} header does not match the addresses in \italic{to-list }here; \typewriter{DropoffMessage} does not need nor use any of the information in \italic{message-string} (but some other delivery agent may).} \begindata{bp,540340360} \enddata{bp,540340360} \view{bpv,540340360,1625,0,0} \subsection{1.4.9 Multipurpose Functions} Functions that have more than one action. Usually used to file incoming messages into the appropriate folder. \typewriter{process-mapped-mailbox} \leftindent{Places \italic{msg} into a tree of folders based upon suffixes following the specified \italic{prefix} in the headers specified in \italic{header-list}. Will create folders as necessary. } \typewriter{standard-mapping} \leftindent{Places \italic{msg} into a tree of folders based upon suffixes following the username in certain headers. Will create folders as necessary. } \begindata{bp,540340424} \enddata{bp,540340424} \view{bpv,540340424,1626,0,0} ______________________________________________________ \paragraph{\index{1.4.9.1 process-mapped-mailbox}} ______________________________________________________ \typewriter{(process-mapped-mailbox \italic{msg treeroot prefix header-list default-folder reject-to reject-cc reject-str})} \bold{Parameters} \leftindent{\italic{Treeroot} is a string containing the name of an existing folder. This folder is the parent of the folders that \italic{msg} will be placed into by suffixes. \italic{Prefix} is a string containing a regular expression that will be used to find suffixes \italic{Header-list} is a list of strings, each one containing the name of a header to be searched for \italic{prefix}. Supplied header names must be lowercase and not include a colon, such as "received".\italic{ } \italic{Default-folder} is a string containing the name of a folder. \italic{Msg} will be placed into this folder if no suffixes can be found. \italic{Reject-to} and \italic{reject-cc} are strings containing addresses that will receive rejections. \italic{Reject-str} is a string containing text that will be prepended to the rejected message.} \bold{Description} \leftindent{Places \italic{msg} into a tree of folders based upon suffixes following the specified \italic{prefix} in the headers specified in \italic{header-list}. Will create folders as necessary. If you don't want incoming messages to automatically create folders, you can copy and modify this function or use \typewriter{post-to-list} instead. See \typewriter{extract-liberally} for a more exact description of suffixes. A description of "new folder announcement" messages can be found under \bold{ Description} for the \typewriter{CreateFolderFromMessage} primitive. } \bold{Return Value} \leftindent{\typewriter{T} if \italic{msg} was placed in any folder or a rejection was sent. \typewriter{NIL} if \italic{msg} was not placed in any folders and a rejection was not sent.} \bold{Defined In} \typewriter{\indent{flib.flames}} \bold{Error Conditions} \leftindent{None } \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{extract-liberally post-to-list standard-mapping}} \bold{Example} \leftindent{\typewriter{\smaller{(process-mapped-mailbox msg "mail" "jbRo[+#]" '("to" "received" "resent-to") "mail" (ReplyAddr msg "s") "jbRo+rejections@andrew.cmu.edu" "There was a problem delivering this message.") }}will do exactly what the \typewriter{standard-mapping} \bold{Example} does, except instead of searching a pre-defined set of headers for a pre-defined prefix, \typewriter{process-mapped-mailbox} will search the specified list, in this case To, Received, and ReSent-To for the specified prefix: "jbRo" followed by a "+" or a "#".} \begindata{bp,540340488} \enddata{bp,540340488} \view{bpv,540340488,1627,0,0} ______________________________________________________ \paragraph{\index{1.4.9.2 standard-mapping}} ______________________________________________________ \typewriter{(standard-mapping \italic{msg treeroot default-folder reject-to reject-cc reject-str})} \bold{Parameters} \leftindent{\italic{Treeroot} is a string containing the name of an existing folder. This folder is the parent of the folders that \italic{msg} will be placed into by suffixes.\italic{ } \italic{Default-folder} is a string containing the name of a folder. \italic{Msg} will be placed into this folder if no suffixes can be found. \italic{Reject-to} and \italic{reject-cc} are strings containing addresses that will receive rejections. \italic{Reject-str} is a string containing text that will be prepended to the rejected message.} \bold{Description} \leftindent{Places \italic{msg} into a tree of folders based upon suffixes following the username in certain headers. Will create folders as necessary. If you don't want incoming messages to automatically create folders, you can copy and modify this function or use \typewriter{post-to-list} instead. See \typewriter{extract-liberally} for a more exact description of suffixes. \typewriter{standard-mapping} looks in the To, CC, Resent-To, Resent-CC, and Received headers for suffixes. A description of "new folder announcement" messages can be found under \bold{Description} for the \typewriter{CreateFolderFromMessage} primitive. } \bold{Return Value} \leftindent{\typewriter{T} if \italic{msg} was placed in any folder or a rejection was sent. \typewriter{NIL} if \italic{msg} was not placed in any folders and a rejection was not sent.} \bold{Defined In} \typewriter{\indent{flib.flames}} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{extract-liberally post-to-list process-mapped-mailbox }} \bold{Example} \leftindent{\typewriter{\smaller{(standard-mapping msg "mail" "mail" (ReplyAddr msg "s") "jbRo+rejections@andrew.cmu.edu" "There was a problem delivering this message.") }}will look for suffixes in \italic{msg} and place \italic{msg} into a folder under mail accordingly. For example, if \italic{msg} is sent to "jbRo+urgent", it will be placed into the folder mail.urgent. If mail.urgent doesn't exist, it will be created, and a "new folder announcement" message will be placed into mail. If no suffixes are found in \italic{msg}, for example, \italic{msg} was sent to "jbRo+", then it will be placed into the default folder; mail. In general, \italic{msg} will never be rejected unless \italic{treeroot} is owned by a user other than the caller or does not exist.} \begindata{bp,540340552} \enddata{bp,540340552} \view{bpv,540340552,1628,0,0} \subsection{1.4.10 File Operations} These functions perform various operations on files. \typewriter{FileLength} \leftindent{Returns the length, in bytes, of the specified file. } \typewriter{ReadFile} \leftindent{Reads part of the specified file.} \typewriter{WriteFile} \leftindent{Writes \italic{string} into file \italic{filename} at positive offset \italic{start} from the beginning of the file. If file \italic{filename} does not exist, it will be created, if possible. } \begindata{bp,540340616} \enddata{bp,540340616} \view{bpv,540340616,1629,0,0} ______________________________________________________ \paragraph{\index{1.4.10.1 FileLength}} ______________________________________________________ \typewriter{(FileLength \italic{filename})} \bold{Parameters} \description{\leftindent{\italic{Filename} is a string containing the fully specified name of a file.}} \bold{Description} \leftindent{Returns the length, in bytes, of the specified file.} \leftindent{The specified file must exist, and you must have list access to its directory entry. \typewriter{FileLength} finds the length of a file by \typewriter{stat}-ing its directory entry, not directly reading the file. Shell commands can be directly executed with the \typewriter{System} ELI primitive.} \bold{Return Value }\leftindent{Integer} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [FILELENGTH (can't stat file)]} File does not exist. Cannot read directory entry for file, caller may have insufficient access.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{None\typewriter{ }} \bold{Example} \leftindent{\typewriter{(FileLength "/afs/andrew.cmu.edu/usr3/jbRo/.login")} could return the integer \typewriter{246}.} \begindata{bp,540340680} \enddata{bp,540340680} \view{bpv,540340680,1630,0,0} ______________________________________________________ \paragraph{\index{1.4.10.2 ReadFile}} ______________________________________________________ \typewriter{(ReadFile \italic{file-name start length})} \bold{Parameters} \leftindent{\description{\italic{File-name} is a string containing the fully-specified name of a file. Tilde ("~") user directory completion is \underline{not} performed.\italic{ Start} is an integer containing the offset of the desired chunk of the file, in bytes, from the beginning of the file. \italic{Length} is an integer containing the length of the desired chunk of the file, in bytes.}} \bold{Description} \leftindent{Reads part of the specified file. On most systems, a byte is equivalent to a character. The "\typewriter{~}" (tilde) user directory path specifier will not work properly in a call to \typewriter{ReadFile}. The \typewriter{FileLength} primitive can be used to get the size of a file. }\bold{Return Value} \leftindent{A string containing the requested chunk of the file \italic{file-name}.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [READFILE (opening file)]} Requested \italic{file-name} does not exist or caller has no read access. \typewriter{FLAMES-PRIMITIVE [READFILE (finding requested file portion)]} \italic{Start} or \italic{length} was negative, or \italic{start}+\italic{length} was larger than the size of the specified file. \typewriter{FLAMES-PRIMITIVE [READFILE (allocating result buffer)]} Out-of-memory. \typewriter{FLAMES-PRIMITIVE [READFILE (reading requested file portion)]} Couldn't read file.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{The \typewriter{open(2)} man page for other error conditions. \typewriter{WriteFile FileLength}} \bold{Example} \leftindent{\typewriter{(ReadFile "/afs/andrew.cmu.edu/usr3/jbRo/.plan" 0 400)} would return a string containing the first 400 bytes of user jbRo's plan file.} \begindata{bp,540340744} \enddata{bp,540340744} \view{bpv,540340744,1631,0,0} ______________________________________________________ \paragraph{\index{1.4.10.3 WriteFile}} ______________________________________________________ \typewriter{(WriteFile \italic{filename string start})} \bold{Parameters} \leftindent{\italic{Filename} is a string containing the full pathname for a writeable file. The file need not exist, but must be creatable. \italic{String} is a string to be written into file \italic{filename}. \italic{Start} is a positive integer containing the offset from the beginning of \italic{filename} to begin writing \italic{string}.} \bold{Description} \leftindent{Writes \italic{string} into file \italic{filename} at positive offset \italic{start} from the beginning of the file. If file \italic{filename} does not exist, it will be created, if possible. If \italic{start} is larger than the current length of file \italic{filename}, the file written to will become unnecessarily large since there will be a gap (which reads as zeros) between the old end-of-file and the offset \italic{start}. The \typewriter{FileLength} primitive can be used to get the length of a file. } \bold{Return Value} \description{\italic{\leftindent{String}}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [WRITEFILE (opening file)]} Couldn't open or create requested file; \italic{filename} may be bad or no write access. \typewriter{FLAMES-PRIMITIVE [WRITEFILE (finding requested file portion)]} Bad \italic{start}. \typewriter{FLAMES-PRIMITIVE [WRITEFILE (writing data)]} Couldn't write \italic{string} to \italic{filename}. \typewriter{FLAMES-PRIMITIVE [WRITEFILE (closing file)]} Couldn't close \italic{filename}. }\bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{ReadFile FileLength open(2)} and \typewriter{lseek(2)} man pages for specific error conditions.} \bold{Example} \leftindent{\typewriter{(WriteFile "/afs/andrew.cmu.edu/usr3/jbRo/hunka" "burnin' love" 10)} will write the string "burnin' love" starting at the tenth character of file \typewriter{hunka}, provided the caller of \typewriter{WriteFile} has write access to \typewriter{hunka}.} \begindata{bp,540340808} \enddata{bp,540340808} \view{bpv,540340808,1632,0,0} \subsection{1.4.11 Andrew File System Functions } \typewriter{GetGroupMembers} \leftindent{Finds the usernames of members of an AFS group.} \typewriter{UserRightsToDir} \leftindent{Checks to see if a certain user has the specified rights to a directory in AFS.} \typewriter{UserAnyRightsToDir} \leftindent{Checks to see if a certain user has one or more of the specified rights to a directory in AFS. }\ \begindata{bp,540340872} \enddata{bp,540340872} \view{bpv,540340872,1633,0,0} ______________________________________________________ \paragraph{\index{1.4.11.1 GetGroupMembers}} ______________________________________________________ \typewriter{(GetGroupMembers afs-group afs-cell)} \bold{Parameters} \leftindent{\italic{afs-group }and\italic{ afs-cell} are both strings. \italic{afs-group} contains the name of an AFS protection group belonging to the optionally-specified \italic{afs-cell}. \italic{afs-cell}, if not supplied, defaults to the local cell.} \bold{Description} \leftindent{Finds the usernames of the members of the specified \italic{afs-group} in the specified \italic{afs-cell}. } \bold{Return Value}\bold{ }\leftindent{A list of two or more elements. The first element is an integer \italic{success-code}. All other elements are strings. If the routine is successful, \italic{success-code} will be zero and the second and succeeding elements of the returned list will each contain the username of one member of the \italic{afs-group}. If the routine is unsuccessful, \italic{success-code} will be non-zero and the second element of the returned list will contain an English error message (string) explaining why the call failed.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [GETGROUPMEMBERS (checking arglist size)] }Wrong number of arguments. \typewriter{FLAMES-PRIMITIVE [GETGROUPMEMBERS (evaluating or type checking arguments)]} Wrong types of arguments (one or both of the arguments was not a string). Other error conditions: see the error string in the second element of the returned list.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\italic{afs-group} help document.} \bold{Example} \leftindent{\typewriter{(getgroupmembers "jbRo:friends") }might return the list\typewriter{ (0 "zzF4" "eekR" "nova") }if the group jbRo:friends in the local AFS cell contains the users zzF4, eekR, and nova. }\leftindent{\typewriter{(getgroupmembers "jbRo:friends" "katana.org")} might return the list \typewriter{(0 "zzF4" "eekR" "nova") }if the group jbRo:friends in the AFS cell katana.org contains the users zzF4, eekR, and nova.} \begindata{bp,540340936} \enddata{bp,540340936} \view{bpv,540340936,1634,0,0} ______________________________________________________ \paragraph{\index{1.4.11.2 UserRightsToDir}} ______________________________________________________ \typewriter{(UserRightsToDir directory username usercell)} \bold{Parameters} \leftindent{All three arguments are strings. \description{\italic{directory} is the pathname of the directory of interest. \italic{directory} must reside in AFS. \italic{username} is the name of the user whose rights on \italic{directory} are to be obtained. \italic{usercell} is the name of the AFS cell to which the user \italic{username} belongs.}} \bold{Description} \leftindent{Finds the rights that user \italic{username} in AFS cell \italic{usercell} has on \italic{directory}. The rights are returned as an integer summation of the binary directory rights bits, e.g., read=1, lookup=8, read and lookup=1+8=9. See the \typewriter{chmod(1v)} man page for a list of the values of the various rights bits (called \italic{mode bits} in that document). The returned integer rights can be translated to standard rights letters with the \typewriter{afs-rights-to-string} library routine in \typewriter{afs.flames}. } \bold{Return Value}\bold{ }\leftindent{If the routine is successful, an integer is returned. This integer represents the rights that \italic{username} holds on \italic{directory}. If the routine is unsuccessful, a list of two elements will be returned: an integer error code, and an English string describing the error.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [USERRIGHTSTODIR (checking arglist size)] }Wrong number of arguments. \typewriter{FLAMES-PRIMITIVE [USERRIGHTSTODIR (evaluating or type checking arguments)]} Wrong types of arguments (one or both of the arguments was not a string). Other error conditions: see the error string in the second element of the returned list.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\italic{protection} help document \typewriter{chmod(1v)} man page \typewriter{afs-rights-to-string} library routine \typewriter{UserAnyRightToDir} primitive} \bold{Example} \leftindent{\typewriter{(userrightstodir "/afs/andrew/usr3/zzF4/src" "jbRo" "katana.com") }returns an integer representing the rights that user jbRo of AFS cell katana.org holds on the AFS directory /afs/andrew/usr3/zzF4/src. If this call to \typewriter{UserRightsToDir} returned \typewriter{9} and is wrapped in a call to the library routine \typewriter{afs-rights-to-string}: \typewriter{(afs-rights-to-string (UserRightsToDir "/afs/andrew/usr3/zzF4/src" "jbRo" "katana.com"))} then \typewriter{afs-rights-to-string} would return "\typewriter{rl}", meaning user jbRo from AFS cell katana.com has "read" and "lookup" rights on the directory /afs/andrew/usr3/zzF4/src. } \begindata{bp,540341000} \enddata{bp,540341000} \view{bpv,540341000,1635,0,0} ______________________________________________________ \paragraph{\index{1.4.11.3 UserAnyRightToDir}} ______________________________________________________ \typewriter{(UserAnyRightToDir directory rights username usercell)} \bold{Parameters}\leftindent{ \description{\italic{directory} is a string containing the pathname of the directory of interest. \italic{directory} must reside in AFS. \italic{rights} is an integer. This integer represents the summation of the binary directory rights bits of interest. \italic{username} is the name of the user whose rights on \italic{directory} are to be tested. \italic{usercell} is the name of the AFS cell to which the user \italic{username} belongs.}} \bold{Description} \leftindent{Tests whether user \italic{username} from AFS cell \italic{usercell} has at least one of the specified rights, represented in the integer \italic{rights,} on the AFS directory \italic{directory}. A \italic{rights} integer can be obtained from standard rights letters ("rwildka") with the library routine \typewriter{string-to-afs-rights}. } \bold{Return Value}\bold{ }\leftindent{\typewriter{T} if the specified \italic{username} from AFS cell \italic{usercell} holds one or more of the rights specified in \italic{rights} on \italic{directory}. \typewriter{NIL} if he specified \italic{username} from AFS cell \italic{usercell} holds none of the rights specified in \italic{rights} on \italic{directory}.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [USERRIGHTSTODIR (checking arglist size)] }Wrong number of arguments. \typewriter{FLAMES-PRIMITIVE [USERRIGHTSTODIR (evaluating or type checking arguments)]} Wrong types of arguments (one or both of the arguments was not a string). Other error conditions: see the error string in the second element of the returned list.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\italic{protection} help document \typewriter{chmod} man page \typewriter{string-to-afs-rights} library routine \typewriter{UserRightsToDir} primitive} \bold{Example} \leftindent{\typewriter{(useranyrighttodir "/afs/andrew/usr3/zzF4/src" 11 "jbRo" "katana.com") }might return \typewriter{T} if user jbRo from AFS cell katana.com has read,lookup, and write (1+8+2=11) access to the directory /afs/andrew/usr3/zzF4/src. } \begindata{bp,540341064} \enddata{bp,540341064} \view{bpv,540341064,1636,0,0} \subsection{1.4.12 Utility Functions} These routines perform various utility functions. \typewriter{GenID} \leftindent{Returns a world-unique string appropriate for use as a message-id or message-file filename.} \typewriter{GetEnv} \leftindent{Returns the value of the specified process environment variable.} \typewriter{GetParameter} \leftindent{Gets one of various configuration parameters from the message system. } \begindata{bp,540341128} \enddata{bp,540341128} \view{bpv,540341128,1637,0,0} ______________________________________________________ \paragraph{\index{1.4.12.1 GenID}} ______________________________________________________ \typewriter{(GenID \italic{is-filename})} \bold{Parameters} \leftindent{\italic{is-filename}, if non-\typewriter{NIL}, will cause \typewriter{GenID} to return a string no longer than the longest filename your system can handle. If \italic{is-filename} is NIL, \typewriter{GenID} will return an 18-character string.} \bold{Description} \leftindent{Returns a world-unique string appropriate for use as a message-id or message-file filename. The returned string is essentially a base-64 representation of the current time, Internet address of the machine, process-id, modulo 256 integer, and some random bits. Some of this information may not be included for strings less than 18 characters long. The information encoded in the returned string can be decoded with the \italic{AndrewDir}\typewriter{/etc/decode_id }program. } \bold{Return Value}\bold{ }\leftindent{A string containing a world-unique pattern of characters from the set [A-Z, a-z, 0-9 , : = ].} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{\typewriter{FLAMES-PRIMITIVE [GENID (checking arglist size)]} \typewriter{GenID} called with wrong number of arguments.} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{None} \bold{Example} \leftindent{\typewriter{(GenID NIL)} could return the string "\typewriter{sYno5Ye00UkM891U48}".} \begindata{bp,540341192} \enddata{bp,540341192} \view{bpv,540341192,1638,0,0} ______________________________________________________ \paragraph{\index{1.4.12.2 GetEnv}} ______________________________________________________ \typewriter{(GetEnv \italic{environment-var-name})} \bold{Parameters} \leftindent{\italic{Environment-var-name} is a string containing the name of a process environment variable, such as "\typewriter{HOME}", "\typewriter{TERM}", "\typewriter{PATH}", etc.} \bold{Description }\leftindent{Returns the value of the specified process environment variable. }\leftindent{\italic{Environment-var-name} must have the same case as the desired environment variable, usually all caps. Environment variables' values cannot be set with FLAMES. }\bold{Return Value} \leftindent{String containing the value of \italic{environment-var-name} if the specified variable has a value. \typewriter{NIL} if the specified variable has no value or does not exist.} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions }\leftindent{None} \bold{Known Bugs} \leftindent{Note that the \typewriter{System} ELI primitive cannot reliably be used to find values of enviroment variables, since a new shell (with its own variables) is started up to execute the command passed to \typewriter{System}. Use \typewriter{GetEnv} instead.} \bold{See Also} \typewriter{\leftindent{GetParameter }} \bold{Example} \leftindent{\typewriter{(GetEnv "HOME")} could return \typewriter{"/afs/andrew.cmu.edu/usr3/jbRo"}; the home directory of user jbRo.} \begindata{bp,540341256} \enddata{bp,540341256} \view{bpv,540341256,1639,0,0} ______________________________________________________ \paragraph{\index{1.4.12.3 GetParameter}} ______________________________________________________ \typewriter{(GetParameter \italic{keyword})} \bold{Parameters} \leftindent{\italic{Keyword} is a string containing one of the following: \description{\description{\typewriter{AndrewDir} asks for the path to the root of the logged-in user's site's Andrew software.\typewriter{ date} asks for the current date and time.\typewriter{ home }asks for the logged-in user's home directory. m\typewriter{aildomain }asks for the host/domain name to which mail to the logged-in user should be addressed. \typewriter{time} asks for the current time in seconds since midnight, January 1, 1970 GMT. \typewriter{uid }asks for the logged-in user's userid. \typewriter{uidsuffix }asks whether a "+" should be appended to the logged-in user's userid for proper mail delivery on this system.}}} \bold{Description} \leftindent{Gets one of various configuration parameters from the message system.} \leftindent{\italic{Keyword} can be UPPER-, MiXeD-, or lower-case. The \typewriter{AndrewDir} request is useful in running Andrew utilities (such as \italic{AndrewDir}\typewriter{/etc/decode_id}) from your FLAMES file when the Andrew software is not on your path. If you are using a \typewriter{uidsuffix} request, note that the plus character that may result must be escaped with a backslash (\typewriter{"\\+"}) when passed to a regular expression parsing function (such as \typewriter{extract-liberally}) if it is to be taken literally. The date and time returned by a \typewriter{date} request are in a format suitable for inclusion in the Date: header of a message. \typewriter{GetEnv} can also be used to find the home and username of the caller from the caller's environment variables, but \typewriter{GetParameter} is more reliable for this use.} \bold{Return Value} \leftindent{A string containing the value of the requested keyword. \description{\leftindent{\returnvalues{\typewriter{AndrewDir} returns a pathname, such as "\typewriter{/usr/andrew"}, to the root of the site's Andrew software.\typewriter{ date} returns the date and time in the form \typewriter{"Fri, 14 Jul 89 13:26:56 -0400 (EDT)"}.\typewriter{ home} returns the caller's home directory. \typewriter{maildomain} returns the caller's mail domain in the form "\typewriter{andrew.cmu.edu}". \typewriter{time} returns the current time in the form "\typewriter{617558457}" (see above). \typewriter{uid} returns the caller's login name.} \typewriter{uidsuffix} returns "\typewriter{+}" if one should be appended to a user id for proper addressing, or "" if not. \typewriter{NIL} if the specified \italic{keyword} is not one of the above.}}} \bold{Defined In} \leftindent{MessageServer (intrinsic)} \bold{Error Conditions} \leftindent{None} \bold{Known Bugs} \leftindent{None} \bold{See Also} \leftindent{\typewriter{GetEnv }} \bold{Example} \leftindent{\typewriter{(GetParameter "uidsuffix")} would return \typewriter{"+"} if the caller's mail delivery system expects addresses to be in the form \typewriter{"jbRo+@andrew.cmu.edu"} instead of \typewriter{"jbRo@andrew.cmu.edu".}} \begindata{bp,540341320} \enddata{bp,540341320} \view{bpv,540341320,1640,0,0} \section{1.5 Quick Reference List} This is a quick reference list of the Library routines and Primitives described in this file. \typewriter{add-to-folders} -- multiple \typewriter{AppendMsgToDir} \typewriter{addheader} -- add a header to msg \typewriter{AppendMsgToDir} -- place msg into a folder \typewriter{BodyLength} -- find the length of the body of msg \typewriter{create-folders} -- multiple CreateFolder/CreateFolders \typewriter{CreateFolder} -- create a folder \typewriter{CreateFolderfrommessage} -- create a folder plus creation message \typewriter{DeleteHeader} -- delete a header from msg \typewriter{DropoffFile} -- initiates delivery of a message (file) \typewriter{DropoffMessage} -- initiates delivery of a message (string) \typewriter{ensure-folders-exist} -- check writeability/ensure existence of folders \typewriter{extract-liberally} -- get suffixes from strings \typewriter{FileLength} -- find the length of any file \typewriter{FinalAppendMsgToDir} -- place msg into a folder via renaming \typewriter{FindFolder} -- disambiguate a folder name \typewriter{GenID} -- generate a world-unique string \typewriter{GetAuthSender} -- get the authorized sender of msg \typewriter{GetCaption} -- get the caption of msg \typewriter{GetEnv} -- get the value of an environment variable \typewriter{GetGroupMembers} -- get the members of an AFS protection group \typewriter{GetHeaderContents} -- get the body/bodies of a header \typewriter{GetHeaderList} -- get the names and bodies of all headers \typewriter{GetParameter} -- get the value of a MessageServer/system parameter \typewriter{GetPartialBody} -- get part of the body of msg \typewriter{multi-getheadercontents} -- multiple \typewriter{getheadercontents} \typewriter{post-by-keyword} -- place msg into folders by keywords \typewriter{post-to-list} -- place msg into folders with restrictions \typewriter{process-mapped-mailbox} -- place msg into folder by prefix/suffix. \typewriter{ReadFile} -- read part of a file \typewriter{RejectMessage} -- reject msg \typewriter{ReplyAddr} -- get a type of reply address \typewriter{ResendMessage} -- resend msg \typewriter{SetCaption} -- set the caption of msg \typewriter{standard-mapping} -- place msg into folder by predefined prefix/suffixes \typewriter{TracelessResendMessage} -- resend msg with minimal modifications \typewriter{UnformatMessage} -- remove multimedia formatting from msg \typewriter{UserAnyRightToDir} -- check if user has any of listed rights to a dir in AFS. \typewriter{UserRightsToDir} -- find rights of a user to a dir in AFS. \typewriter{ValidateAddr }-- chack a mail address for correctness. \typewriter{validate-folder-list} -- check writeability/createability of folders \typewriter{WriteFile} -- write to a file \begindata{bp,537558784} \enddata{bp,537558784} \view{bpv,537558784,1642,0,0} Copyright 1992 Carnegie Mellon University and IBM. All rights reserved. \smaller{\smaller{$Disclaimer: Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice, this permission notice, and the following disclaimer appear in supporting documentation, and that the names of IBM, Carnegie Mellon University, and other copyright holders, not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. $ }}\enddata{text,538369072}