DOCUMENTATION OF MM-D FUNCTIONS AND INTERFACES
                             MARK CRISPIN
----------------------------------------------------------------------
     The files listed below must be rewritten for each port of MM-D to
a new operating system.

[Main program]

#include "imap2.h"
#include "smtp.h"
#include "misc.h"
#include "tcpsio.h"

mm_searched (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function is called from map_search to notify the main program
that this message number matches the search.  Note that the stream is
locked and that therefore you cannot call any map_xxx functions!

mm_exists (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function is called from several functions to notify the main
program that this message number exists (i.e. there are this many
messages in the mailbox).  Note that the stream is locked and that
therefore you cannot call any map_xxx functions!

mm_expunged (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function is called from map_expunge to notify the main program
that this message number has been expunged from the mail file and that
all subsequent messages are now referenced by a message number one
less than before.  Note that the stream is locked and that therefore
you cannot call any map_xxx functions!

usrlog (string)
    char *string;
 This function is called from several functions to output a string for
the user to see.  No newline is included in the string, so this
function has to output its own.

dbglog (string)
    char *string;
 This function is called from several functions to output a string to a
debugging telemetry stream.  No newline is included in the string, so
this function has to output its own.

getpassword (host,username,password)
    char *host;
    char *username;
    char *password;
 This function is called to get a user name and password for the given
host.  The function stores the user name and password in the strings
pointed to by the appropriate arguments.

[OSDEP.C]:	operating system-dependent functions

rfc822_date (date)
     char date[];
 This function is called to get the current date and time in an RFC 822
format string into the the string pointed to by the argument.

[TCPSIO.C]:	TCP/IP string-oriented I/O functions

#include "tcpsio.h"
#include "misc.h"

TCPSTREAM *tcp_open (host,port)
    char *host;
    int port;
 This function is called to open a TCP connection to the given host
name on the given port number.  It returns a TCPSTREAM, which is an
internal data structure for this file and is implementation-dependent.
NIL is returned if this function fails for any reason.

char *tcp_getline (stream)
    TCPSTREAM *stream;
 This function returns a malloc() string containing a null-terminated
text line from the TCP stream.  The CR/LF which terminated the line is
not included.  The caller should free() the string when it is finished
with it.  NIL is returned if this function fails for any reason.

tcp_getbuffer (stream,size,buffer)
    TCPSTREAM *stream;
    int size;
    char *buffer;
 This function reads the requested number of bytes into the indicated
buffer.  This function returns T if successful and NIL if it fails for
any reason.

tcp_soutr (stream,string)
    TCPSTREAM *stream;
    char *string;
 This function writes the indicated (null-terminated) string to the
TCP stream.  This function returns T if successful and NIL if it fails
for any reason.

tcp_close (stream)
    TCPSTREAM *stream;
 The function closes the TCP stream and frees all resources associated
with it that it may have created.

char *tcp_host (stream)
    TCPSTREAM *stream;
 This function returns the stream's foreign host name string.

char *tcp_localhost (stream)
    TCPSTREAM *stream;
 This function returns the stream's local host name string.

----------------------------------------------------------------------
     The files listed below are the standard MM-D mailsystem library
modules, and are operating system and machine independent.  Only those
functions suitable for external callers are documented here; other
functions are for internal use only and are used by external callers
at their own risk!

[IMAP2.C]:	Mail Access Protocol functions

[Note!!  There is an important difference between a "sequence" and a
 "msgno".  A sequence is a string representing one or more messages in
 IMAP2 sequence format ("n", "n:m", or combination of these delimited
 by commas), whereas a msgno is an int representing a single message.]

IMAPSTREAM *map_open (net_mailbox,oldstream,debug)
    char *net_mailbox;
    IMAPSTREAM *oldstream;
    short debug;
 This function opens a MAP connection to the net_mailbox (in
{host}mailbox format, e.g. "{KSL.Stanford.EDU}INBOX") and if
successful returns a stream suitable for use by the other MAP
functions.  If oldstream is non-NIL, a check is made to see if the TCP
host is the same as the host for this mailbox.  If it is not,
oldstream is closed; otherwise, an attempt is made to reuse oldstream
as the stream for this mailbox.  If debug is non-NIL, map_debug() is
called on a newly-created stream immediately after the TCP connection
is opened so that the greeting, login, and mailbox selection protocol
goes into the debugging telemetry.  NIL is returned if this function
fails for any reason.

map_close (stream)
    IMAPSTREAM *stream;
 This function closes the MAP stream and frees all resources
associated with it that it may have created.

map_fetchfast (stream,sequence)
    IMAPSTREAM *stream;
    char *sequence;
 This function causes a fetch of all the IMAP2 "fast" information
(internal date, RFC 822 size, and flags) for the given sequence.
Since all this information is also fetched by map_fetchenvelope(),
this function is generally not used.

map_fetchflags (stream,sequence)
    IMAPSTREAM *stream;
    char *sequence;
 This function causes a fetch of the flags for the given sequence.
This main reason for using this function is to update the flags in the
local cache in case some other process changed the flags (multiple
simultaneous write access is allowed to the flags in IMAP2) as part of
a "check entire mailbox" (as opposed to "check for new messages")
operation.

ENVELOPE *map_fetchenvelope (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function causes a fetch of all the IMAP2 information (envelope,
internal date, RFC 822 size, and flags) for the given msgno and up to
MAPLOOKAHEAD (a parameter in IMAP2.H) subsequent messages which are
not yet in the cache.  No fetch is done if the envelope for the given
msgno is already in the cache.  The ENVELOPE for this msgno is
returned.
 This is the primary function for fetching non-text information about
messages, and should be called before any attempt to reference cache
information about this message via map_elt().

char *map_fetchmessage (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function causes a fetch of the specified message as an RFC 822
format text string and returns that text string.
 An application which uses both this and map_fetchtext() would use
this function for a "display message literally" function.

char *map_fetchheader (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function causes a fetch of the RFC 822 format header of the
specified message as a text string and returns that text string.

char *map_fetchtext (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function causes a fetch of the body of the specified message as
a text string and returns that text string.
 An application which uses both this and map_fetchmessage() would use
this function for a "display message" function, with the envelope
interpreted and displayed to the user in some manner to provide the
information which would otherwise be in the header.

char *map_fetchfromstring (stream,msgno,length)
    IMAPSTREAM *stream;
    int msgno;
    int length;
 This function returns a "from" string of the specified length for the
specified message, suitable for display to the user in a menu line.
 If the personal name of the first address in the envelope's from item
is non-NIL, it is used; otherwise a string is created by appending the
mailbox of the first address, an "@", and the host of the first
address.  The string is trimmed or padded with trailing spaces as
necessary to make its length match what the caller requested.
 The length argument is provided to make it convenient for the
application to decide upon the length it wants.  It should be
considered a constant, since once generated the string is kept in the
cache and is returned on subsequent calls instead of recomputed.

char *map_fetchsubjectstring (stream,msgno,length)
    IMAPSTREAM *stream;
    int msgno;
    int length;
 This function returns a "subject" string of the specified length for
the specified message, suitable for display to the user in a menu
line.
 The envelope's subject item is copied and trimmed as necessary to
make its length be no more what the caller requested.  Unlike
map_fetchfromstring(), this function can return a string of shorter
length than what the caller requested.
 The warning about the length argument in map_fetchfromstring() also
applies to this function.

MESSAGECACHE *map_elt (stream,msgno)
    IMAPSTREAM *stream;
    int msgno;
 This function returns the cache entry for the specified message, and
is preferred over using stream->messagearray[msgno-1].
 Although this function will create a cache entry if it does not
already exist, that functionality is for internal use only.  This
function should never be called without having first called
map_fetchenvelope() on the message first.

map_setflag (stream,sequence,flag)
    IMAPSTREAM *stream;
    char *sequence;
    char *flag;
 This function causes a store to add the specified flag to the flags
set for the messages in the specified sequence.  If there is any
problem in setting flags, a message will be passed to the application
via the usrlog() facility.

map_clearflag (stream,sequence,flag)
    IMAPSTREAM *stream;
    char *sequence;
    char *flag;
 This function causes a store to delete the specified flag from the
flags set for the messages in the specified sequence.  If there is any
problem in clearing flags, a message will be passed to the application
via the usrlog() facility.

map_search (stream,criteria)
    IMAPSTREAM *stream;
    char *criteria;
 This function causes a mailbox search using the specified criteria
(in IMAP2 format).  The application's mm_searched() function is called
for each message that matches the search criteria.  If there is any
problem in searching, a message will be passed to the application via
the usrlog() facility.

map_checkmailbox (stream)
    IMAPSTREAM *stream;
 This function causes an explicit check of the mailbox for new
messages including a remote reparse of all flags in the mailbox.  The
application's mm_exists() function is called with the number of
messages in the mailbox.  The status of the check is passed to the
application via the usrlog() facility.
 Note that map_fetchflags() needs to be called to update the flags in
the local cache.

map_expungemailbox (stream)
    IMAPSTREAM *stream;
 This function causes an expunge of the mailbox.  The application's
mm_expunged() function is called for each message that has been
expunged.  The application's mm_exists() function is called at the
start and end of the expunge to ensure synchronization.  The status of
the expunge is passed to the application via the usrlog() facility.
 Note that the decrementing of msgno's for subsequent messages happens
immediately; for example, if three consequtive messages starting at
msgno 5 are expunged, mm_expunged() will be called with a msgno of 5
three times.

map_copymessage (stream,sequence,mailbox)
    IMAPSTREAM *stream;
    char *sequence;
    char *mailbox;
 This function causes the messages in the specified sequence to be
copied to the specified mailbox.  The system \Seen flag is set for
these messages if the copy is successful.
 If there is any problem in copying, a message will be passed to the
application via the usrlog() facility.
 Note that the mailbox must be on the same host as the stream and is a
mailbox only, not a net_mailbox ({host}mailbox format).

map_movemessage (stream,sequence,mailbox)
    IMAPSTREAM *stream;
    char *sequence;
    char *mailbox;
 This function causes the messages in the specified sequence to be
copied to the specified mailbox.  The system \Seen and \Deleted flags
are set for these messages if the copy is successful.
 If there is any problem in copying, a message will be passed to the
application via the usrlog() facility.
 Note that the mailbox must be on the same host as the stream and is a
mailbox only, not a net_mailbox ({host}mailbox format).

map_checklock (stream)
    IMAPSTREAM *stream;
 This function returns T if the stream is locked (an IMAP2 protocol
operation is in progress) else NIL.  Any multi-tasking application
should call this function prior to calling any of the other functions
in this module.  Any attempt to do a MAP operation while one is
already in progress on the same stream will cause the application to
fail in unpredictable ways, mostly likely due to the _exit() calls in
the internal imap_lock() routine when it discovers the stream is
already locked.
 Note that this check is insufficient in a preemptive-scheduling
multi-tasking application due to the possibility of a timing race.
Such applications must be written so that only one process accesses
the stream, or to have a higher level lock.
 Since MAP operations will not finish until they are completed, a
single-tasking application does not have to worry about this problem,
except in its mm_searched(), mm_exists(), and mm_expunged() functions
when the stream is *always* locked.

map_debug (stream)
    IMAPSTREAM *stream;
 This function enables IMAP2 protocol telemetry logging for this
stream.  All IMAP2 protocol operations are passed to the application
via the dbglog() facility.

map_nodebug (stream)
    IMAPSTREAM *stream;
 This function disables IMAP2 protocol telemetry logging for this
stream.

[MISC.C]:	Miscellaneous utility functions

char *ucase (string)
    char *string;
 This function converts each lowercase character of the specified
string to uppercase and returns the string.
 Note: this function modifies the source string.

char *lcase (string)
    char *string;
 This function converts each uppercase character of the specified
string to lowercase and returns the string.
 Note: this function modifies the source string.

char *hostfield (string)
    char *string;
 This function parses the specified string as if it were a net_mailbox
({host}mailbox format) and if successful returns a malloc() string
containing the host part of that string.  The caller should free() the
returned string when it is finished with it.  NIL is returned if this
function fails for any reason.

char *mailboxfield (string)
    char *string;
 This function parses the specified string as if it were a net_mailbox
({host}mailbox format) and if successful returns a malloc() string
containing the mailbox part of that string.  If the net_mailbox has a
valid host but no mailbox (e.g. "{SUMEX-AIM.Stanford.EDU}") then a
malloc() copy of the default mailbox, "INBOX", is returned.  The
caller should free() the returned string when it is finished with it.
NIL is returned if this function fails for any reason.

find_rightmost_bit (valptr)
    long *valptr;
 This function returns -1 if the 32-bit value pointed to by valptr is
non-zero, otherwise it returns the bit number (0 = LSB, 31 = MSB) of
the right-most bit in that value.  This is used to convert from the
bits in the cache's userFlags item to an index into the stream's
userFlags array of flag texts.

min (i,j)
    int i,j;
 This function returns the minimum of the two integers.

[SMTP.C]:	Mail Transfer Protocol functions

SMTPSTREAM *mtp_open (hostlist,debug)
    char **hostlist;
    int debug;
 This function opens an MTP connection to a one of the hosts in the
host list and if successful returns a stream suitable for use by the
other MTP functions.  The hosts are tried in order until a connection
is successfully opened.  If debug is non-NIL, mtp_debug() is called on
the stream immediately after the TCP connection is opened so that the
greeting and hello protocol goes into the debugging telemetry.  NIL is
returned if this function fails to open a connection to any of the
hosts in the list.

mtp_close (stream)
    SMTPSTREAM *stream;
 This function closes the MTP stream and frees all resources
associated with it that it may have created.

mtp_mail (stream,type,msg)
    SMTPSTREAM *stream;
    char *type;
    MESSAGE *msg;
 This function negotiates an MTP transaction of the specified type
(one of "MAIL", "SEND", "SAML", or "SOML") to deliver the specified
message.  This function returns T if success or NIL if there is any
failure.  The text reason for the failure is in the stream's reply
item; if it is associated with a recipient it is also in that address'
error item.

MTPADR *mtp_parse_address (string,defaulthost)
    char *string;
    char *defaulthost;
 This function parses a string that contains an RFC 822 format address
list and returns an address list suitable for the to, cc, or bcc items
of a message.  The address list should be freed via mtp_free_address()
when the application is finished with it.  If there are any parsing
errors a message is passed to the application via the usrlog()
facility.

mtp_debug (stream)
    SMTPSTREAM *stream;
 This function enables SMTP protocol telemetry logging for this
stream.  All SMTP protocol operations are passed to the application
via the dbglog() facility.

mtp_nodebug (stream)
    SMTPSTREAM *stream;
 This function disables SMTP protocol telemetry logging for this
stream.

rfc822_header (header,message)
    char *header;
    MESSAGE *message;
 This function writes an RFC 822 format header into header based on
the information in message.

rfc822_write_address (destination,address)
    char *destination;
    MTPADR *address;
 This function writes an RFC 822 format address list into destination
based on the information in address and is therefore the inverse of
mtp_parse_address().

mtp_free_message (message)
    MESSAGE *message;
 This function does a free() of message and all the malloc() strings
inside of it.

mtp_free_address (address)
    MTPADR *address;
 This function does a free() of the specified address list and all the
malloc() strings inside of it.  This is called from mtp_free_message,
so it isn't necessary to call this for an address list that is in a
message.