]> granicus.if.org Git - uw-imap/commitdiff
add files for 2006-08-30T23:26:14Z
authorUnknown <>
Wed, 30 Aug 2006 23:26:14 +0000 (23:26 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Fri, 7 Sep 2018 00:02:28 +0000 (00:02 +0000)
docs/internal.txt [new file with mode: 0644]

diff --git a/docs/internal.txt b/docs/internal.txt
new file mode 100644 (file)
index 0000000..203688e
--- /dev/null
@@ -0,0 +1,2988 @@
+/* ========================================================================
+ * Copyright 1988-2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 
+ * ========================================================================
+ */
+
+         Documentation of c-client Functions and Interfaces
+
+REVISED: 19 August 1996
+
+                                 Credits
+
+     The original version of this document was written by Mark Crispin at
+the University of Washington, and described the version of c-client that
+supported the IMAP2 (RFC 1176) and IMAP2bis (unpublished) protocols.
+
+     This version is a substantial rewrite of that document, and was
+written by Mark Crispin with funding from Sun Microsystems, Incorporated.
+Sun's generous support of this work is gratefully acknowledged.
+
+
+                                Road Map
+
+     This document is organized into the following sections.  Except as
+noted, an implementor of an application that uses c-client needs to be
+familiar with all of these sections.  Someone who plans to write a new
+mailbox driver for c-client (or otherwise modify it) needs to be familiar
+with all sections, no exception.
+
+History
+       History of how c-client came about.
+
+Overview
+       Read this before designing an application that uses c-client.
+
+c-client Structures
+       Documentation of several important c-client structs which are
+       used in, and returned by, c-client calls.
+
+String Structures
+       Documentation of the concept of a "string structure", which
+       provides random access to strings without requiring that the
+       string be in memory.
+
+c-client Support Functions
+       Documentation of support functions for c-client; these deal
+       with c-client functionality.
+
+       Only mail_parameters() is of interest to most application
+       developers.  Advanced application developers, particularly
+       for limited memory systems, may also need to know about the
+       readfn_t, mailgets_t, mailcache_t, and tcptimeout_t function
+       pointer types, and possibly also the mail_valid_net_parse()
+       function.
+
+Mailbox Access Functions
+       Documentation of functions which deal with mailboxes;
+       listing, subscribing, creating, deleting, renaming, status
+       inquiries, opening, and closing mailboxes.
+
+Handle Functions
+       Documentation of mail stream handles, which provide protection
+       for an advanced application which may have multiple pointers to
+       a single mail stream.  If a stream has a handle on it, closing
+       the stream does not release its memory, so pointers to it in
+       the application remain valid.  Freeing the last handle will free
+       the entire stream.
+
+       This is only of interest for advanced application developers.
+
+Message Data Fetching Functions
+       Documentation on message data fetching in an open mailbox,
+       including parsed representations of RFC-822 and MIME headers
+       and message text.  Also how to fetch message attributes (flags,
+       internal date, sizes).
+
+Message Status Manipulation Functions
+       Documentation on altering message flags in an open mailbox.
+
+Mailbox Searching
+       Documentation on searching an open mailbox for messages which
+       match certain criteria (e.g. "messages sent July 4 from Jones
+       with text `Paris'").
+
+Miscellaneous Mailbox and Message Functions
+       Documentation on other operations that would be used by an
+       application but that don't fit into any of the above categories.
+
+Date/Time Handling Functions
+       Documentation on functions that deal with date/time strings.
+
+       This is only of interest for advanced application developers
+       and for implementors of new c-client drivers.
+
+Utility Functions
+       Documentation on internal utility functions.
+
+       This is primarily of interest for implementors of new c-client
+       drivers, but advanced application developers may also use some
+       of these functions.
+
+Data Structure Instantiation/Destruction functions
+       Documentation on creating and destroy c-client structures.
+
+       This is primarily of interest for implementors of new c-client
+       drivers.  However, application developers will need some of
+       these functions to create and destroy structures which are used
+       as arguments to various application functions.
+
+Authentication Functions
+       Documentation on support for network protocol authentication
+       functions.
+
+       This is only of interest for implementors of new c-client
+       drivers which deal with authentication mechanisms.
+
+Network Access Functions
+       Documentation on creating and destroy c-client structures.
+
+       This is primarily of interest for implementors of new c-client
+       drivers which deal with a network.  However, advanced
+       application developers may need to use this information if they
+       wish to insert their own layer into a network session.
+
+Subscription Management Functions
+       Documentation on managing the local (client-based) subscription
+       database file.
+
+       This is primarily of interest to advanced application developers.
+
+Miscellaneous Utility Functions
+       Documentation on various useful utility functions, such as "make
+       a copy of this string."
+
+SMTP Functions
+       Documentation on posting email messages via SMTP protocol.
+
+NNTP Functions
+       Documentation on posting netnews messages via NNTP protocol.
+
+RFC 822 Support Functions
+       Documentation on public RFC-822/MIME functions.
+
+       This is primarily of interest for implementors of new c-client
+       drivers and advanced application developers.
+
+Operating System-Dependent Public Interface
+       Documentation on OS-dependent functions.  With the exception of
+       fs_get(), fs_give(), and fs_resize(), which should be called
+       instead of malloc(), free(), and realloc(), these functions are
+       primarily of interest for implementors of new c-client drivers.
+
+Main Program Callbacks
+       Documentation of functions which the main program must provide
+       as callbacks from c-client.
+
+Driver Interface
+       Documentation of the driver dispatch vector and the functions
+       which a driver must supply.
+
+       This is primarily of interest for implementors of new c-client
+       drivers.
+
+Driver Support Functions
+       Documentation of support functions which are called by drivers.
+
+       This is primarily of interest for implementors of new c-client
+       drivers.
+\f                                History
+
+     The c-client API was originally written by Mark Crispin at Stanford
+University as a set of routines to support IMAP and SMTP from a main
+program which would handle the user interface.  In its original form, it
+was written as the low-level routines that were to be used as part of a
+Macintosh client.
+
+     The first IMAP client, MM-D (for "MM on Xerox D machines" -- MM was a
+popular DEC-20 mail program) was written in Interlisp for Xerox Lisp
+machines.  At that time, there was no name for the embryonic Mac client,
+but since it was the first one to be written in C instead of Lisp, it was
+given a development name of "C client".  This name became "c-client"
+because that is the name of the subdirectory on UNIX where the source files
+were stored.
+
+     To exercise the routines, a minimal main program which uses c-client,
+mtest, was written.  mtest has subsequently been extended so that it runs
+on every platform that c-client is ported.
+
+     The real Mac client, was eventually written by Frank Gilmurrary and
+Bill Yeager at Stanford using the autumn 1988 version of c-client and named
+"MacMS".  In the winter of 1988-89, Mark Crispin, who had changed jobs to
+the University of Washington, developed MS as an MM-like text-based program
+for UNIX and MailManager as a GUI-based program for NeXT machines.
+
+     The realization sunk in that this API needed its own name.  As early
+as spring 1989, there were at least four programs (mtest, MS, MailManager,
+and MacMS) that used it.  The name c-client thus became permanent.
+
+     In its history, c-client has undergone two major redesigns, both by
+Mark Crispin who is now on the staff at the University of Washington.
+
+     The first major redesign added the following:
+       1) ANSI C calling conventions throughout to assist in function
+          argument type checking.
+       2) Vectoring mail access calls through "driver" methods; thus
+          providing transparent access to multiple types of mail
+          stores with the same call.
+       3) MIME support.
+
+     The second major redesign was part of the IMAP4 project.  Many
+c-client functions were extended with additional arguments and options.
+The driver interface was also made simpler, with more work done by
+driver-independent code.
+\f
+                              Overview
+
+     The most important file for the author of an application using the
+c-client is mail.h.  mail.h defines several important structures of
+data which are passed between the main program and the c-client.
+Although some functions (e.g. mail_fetchtext_body()) return the data
+fetched, for certain other data items (e.g. flags) you need to get the
+data as a structure reference.  mail.h also defines a large number of
+useful constants and structures.
+
+     When a function in mail.h exists to reference data, it MUST be
+used instead of referencing the structures directly.  This is because
+in some cases the data is not actually fetched until a reference (via
+the function call) is made.  For example, although the MESSAGECACHE
+element for a message can be obtained by indexing the proper cache
+element in the stream, there is no guarantee that the item in fact
+exists unless mail_fetchstructure_full() is called for that message.
+Less costly functions. also exist to create and load a MESSAGECACHE
+element.
+
+     The main program will probably also need to include smtp.h,
+misc.h, and osdep.h, but this usage should be solely to receive
+function prototypes.  Any other definitions in those files should be
+considered private to that module.
+
+     Two important predefined symbols are NIL and T.  NIL is any sort
+of "false"; T is any sort of "true".  NIL is also used to null-specify
+certain optional arguments.
+
+                       * * * IMPORTANT * * *
+
+     Any multi-threaded application should test stream->lock prior to
+calling any c-client stream functions.  Any attempt to call a
+mail_xxx() function while one is already in progress on the same
+stream will cause the application to fail in unpredictable ways.
+
+     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 MAIL operations will not finish until they are completed, a
+single-tasking application does not have to worry about this problem,
+except in the callback invoked from MAIL (e.g. mm_exists(), etc.) in which
+case the stream is *always* locked.
+\f
+                         c-client Structures
+
+     c-client has a large number of structures which are used for
+multiple functions.  The most important of these are described here.
+
+     The MAILSTREAM structure is used to reference open mailboxes.
+Applications may reference the following:
+
+char *mailbox;                 mailbox name
+unsigned short use;            stream use count, this is incremented
+unsigned short sequence;       stream sequence, this is incremented
+                                each time a stream is reused (i.e.
+                                mail_open() is called to open a
+                                different mailbox on this stream)
+unsigned int rdonly : 1;       stream is open read-only
+unsigned int anonymous : 1;    stream is open with anonymous access
+unsigned int halfopen : 1;     stream is half-open; it can be
+                                reopened or used for functions that
+                                don't need a open mailbox such as
+                                mail_create() but no message data
+                                can be fetched
+unsigned int perm_seen : 1;    Seen flag can be set permanently
+unsigned int perm_deleted : 1; Deleted flag can be set permanently
+unsigned int perm_flagged : 1; Flagged flag can be set permanently
+unsigned int perm_answered :1; Answered flag can be set permanently
+unsigned int perm_draft : 1;   Draft flag can be set permanently
+unsigned int kwd_create : 1;   new user flags can be created by
+                                referencing then in mail_setflag() or
+                                mail_clearflag().  Note: this can
+                                change during a session (e.g. if
+                                there is a limit on the number of
+                                keywords), so check after creating a
+                                new flag to see if any more can be
+                                created before letting the user try
+                                to do so
+unsigned long perm_user_flags; corresponding user flags can be set
+                                permanently.  This is a bit mask
+                                which matches the entries in
+                                stream->user_flags[]
+unsigned long gensym;          generated unique value.  Always
+                                referenced with stream->gensys++
+unsigned long nmsgs;           number of messages in current mailbox
+unsigned long recent;          number of recent messages in current
+                                mailbox
+unsigned long uid_validity;    UID validity value; this is used to
+                                verify that recorded UIDs match the
+                                UIDs that the stream has.  If the
+                                mailbox does not have matching UIDs
+                                (e.g. the UIDs were lost or not
+                                recorded) then the UID validity value
+                                will be different
+unsigned long uid_last;                highest currently assigned UID in the
+                                current mailbox; a new UID will be
+                                assigned with ++stream->uid_last
+char *user_flags[NUSERFLAGS];  pointers to user flag names in bit
+                                order from stream->perm_user_flags or
+                                elt->user_flags
+
+     The following MAILSTREAM values are only used internally:
+
+DRIVER *dtb;                   dispatch table for this driver
+void *local;                   pointer to driver local data
+unsigned int lock : 1;         stream lock flag (an operation is in
+                                progress; used as a bug trap to
+                                detect recursion back to c-client
+                                from callback routines).
+unsigned int debug : 1;                debugging information should be logged
+                                via mm_dlog().
+unsigned int silent : 1;       don't do main program callbacks on
+                                this stream (used when a stream is
+                                opened internally)
+unsigned int scache : 1;       short caching; don't cache information
+                                in memory
+
+     The following MAILSTREAM values are only used by the cache
+manager routine (see the documentation about mailcache_t above):
+
+unsigned long cachesize;       size of c-client message cache
+union {
+  void **c;                    to get at the cache in general
+  MESSAGECACHE **s;            message cache array
+  LONGCACHE **l;               long cache array
+} cache;
+
+     The following MAILSTREAM values are for the convenience of
+drivers that use short caching and want to be able to garbage collect
+any values that they returned:
+
+unsigned long msgno;           message number of `current' message
+ENVELOPE *env;                 pointer to `current' message envelope
+BODY *body;                    pointer to `current' message body
+char *text;                    pointer to `current' text
+
+
+     The MESSAGECACHE structure (commonly called an "elt" as a
+nickname for "cache ELemenT") contains information about messages.
+Applications may use the following:
+
+unsigned long msgno;           message number.  If the elt is locked
+                                (by elt->lockcount++), then the elt
+                                pointer can be stored (e.g. with the
+                                data for a window which draws this
+                                message) and elt->msgno will change
+                                automatically whenever expunges are
+                                done so the window will always view
+                                the correct message.  If elt->msgno
+                                becomes 0, then the message has been
+                                expunged, but the elt won't be freed
+                                until the elt lock count is
+                                decremented (by mail_free_elt()).
+unsigned long uid;             message unique ID
+unsigned int hours: 5;         internal date hours (0-23)
+unsigned int minutes: 6;       internal date minutes (0-59)
+unsigned int seconds: 6;       internal date seconds (0-59)
+unsigned int zoccident : 1;    non-zero if internal date time zone is
+                                west of UTC
+unsigned int zhours : 4;       internal date time zone hours from UTC
+                                (0-12)
+unsigned int zminutes: 6;      internal date time zone minutes (0-59)
+unsigned int seen : 1;         message Seen flag
+unsigned int deleted : 1;      message Deleted flag
+unsigned int flagged : 1;      message Flagged flag
+unsigned int answered : 1;     message Answered glag
+unsigned int draft : 1;                message Draft flag
+unsigned int valid : 1;                flags are valid in this elt; an elt
+                                that was newly created but never
+                                loaded with flags won't have this set.
+unsigned int recent : 1;       message recent flag
+unsigned int searched : 1;     message matches search criteria in
+                                most recent mail_search_full() call
+unsigned int spare : 1;                reserved for application use
+unsigned int spare2 : 1;       reserved for application use
+unsigned int spare3 : 1;       reserved for application use
+unsigned int lockcount : 8;    non-zero if multiple references to
+                                this elt.  Refer to the msgno member
+                                for more information.
+unsigned int day : 5;          internal date day of month (1-31)
+unsigned int month : 4;                internal date month of year (1-12)
+unsigned int year : 7;         internal date year since BASEYEAR
+                                (currently 1970; was 1969 in older
+                                versions so use BASEYEAR instead of
+                                having the base year wired in)
+unsigned long user_flags;      message user flags; this is a bit mask
+                                which matches the entries in
+                                stream->user_flags[]
+unsigned long rfc822_size;     size of message in octets
+
+     The following MESSAGECACHE values are only used internally by
+drivers:
+
+unsigned int sequence : 1;     message is in sequence from either
+                                mail_sequence() or mail_uid_sequence()
+unsigned long data1;           first data item
+unsigned long data2;           second data item
+unsigned long data3;           third data item
+unsigned long data4;           fourth data item
+
+
+     The ADDRESS structure is a parsed form of a linked list of RFC 822
+addresses.  It contains the following information:
+
+char *personal;                        personal name phrase
+char *adl;                     at-domain-list (also called "source
+                                route")
+char *mailbox;                 mailbox name
+char *host;                    domain name of mailbox's host
+char *error;                   error in address from smtp_mail(); if
+                                an error is returned from smtp_mail()
+                                for one of the recipient addresses
+                                the SMTP server's error text for that
+                                recipient can be found here.  If it
+                                is null then there was no error (or
+                                an error was found with a prior
+                                recipient
+ADDRESS *next;                 pointer to next address in list
+
+
+     The ENVELOPE structure is a parsed form of the RFC 822 header.
+Its member names correspond to the RFC 822 field names.  It contains
+the following information:
+
+char *remail;                  remail header if any
+ADDRESS *return_path;          error return address
+char *date;                    message composition date string
+ADDRESS *from;                 from address list
+ADDRESS *sender;               sender address list
+ADDRESS *reply_to;             reply address list
+char *subject;                 message subject string
+ADDRESS *to;                   primary recipient list
+ADDRESS *cc;                   secondary recipient list
+ADDRESS *bcc;                  blind secondary recipient list
+char *in_reply_to;             replied message ID
+char *message_id;              message ID
+char *newsgroups;              USENET newsgroups
+char *followup_to;             USENET reply newsgroups
+char *references;              USENET references
+
+
+     The BODY structure is a parsed form of a linked list of the MIME
+structure of a message.  It contains the following information.
+
+unsigned short type;           body primary type code.  This is an
+                                index into the body_types vector of
+                                body type names.  The following body
+                                types are pre-defined:
+       TYPETEXT                unformatted text
+       TYPEMULTIPART           multiple part
+       TYPEMESSAGE             encapsulated message
+       TYPEAPPLICATION         application data
+       TYPEAUDIO               audio
+       TYPEIMAGE               static image (GIF, JPEG, etc.)
+       TYPEVIDEO               video
+       TYPEOTHER               unknown
+                               Additional types up to TYPEMAX are
+                                dynamically defined if they are
+                                encountered by c-client.
+unsigned short encoding;       body transfer encoding.  This is an
+                                index into the body_encodings vector
+                                of body encoding names.  The
+                                following body encodings are
+                                pre-defined:
+       ENC7BIT                 7 bit SMTP semantic data
+       ENC8BIT                 8 bit SMTP semantic data
+       ENCBINARY               8 bit binary data
+       ENCBASE64               base-64 encoded data
+       ENCQUOTEDPRINTABLE      human-readable 8-as-7 bit data
+       ENCOTHER                unknown
+                               Additional encodings up to ENCMAX are
+                                dynamically defined if they are
+                                encountered by c-client.
+char *subtype;                 body subtype string
+PARAMETER *parameter;          parameter list
+char *id;                      body content identifier
+char *description;             body content description
+unsigned char *contents.text;  when composing a message that is NOT
+                                of TYPEMULTIPART, non-binary text of
+                                the content is stored here.  Note that
+                                this happens even when the text is
+                                of TYPEMESSAGE.  Text of encoding
+                                ENC8BIT may be converted to
+                                ENCQUOTEDPRINTABLE when it is sent.
+                                This should not be referenced for any
+                                other reason; in particular, this is
+                                NOT the way for an application to
+                                access content data (use
+                                mail_fetchbody_full() instead).
+BINARY *contents.binary;       when composing a message that is NOT
+                                of TYPEMULTIPART, binary content (of
+                                encoding ENCBINARY) is stored here.
+                                It will be converted to ENCBASE64 when
+                                it is sent.
+                                This should not be referenced for any
+                                other reason; in particular, this is
+                                NOT the way for an application to
+                                access content data (use
+                                mail_fetchbody_full() instead).
+PART *contents.part;           for body parts of TYPEMULTIPART, this
+                                contains the list of body parts in
+                                this multipart
+MESSAGE contents.msg;          for body parts of TYPEMESSAGE with
+                                subtype "RFC822", this contains the
+                                encapsulated message
+unsigned long size.lines;      size in lines
+unsigned long size.bytes;      size in octets.  This MUST be set when
+                               composing a message if the encoding is
+                               ENC8BIT or ENCBINARY.
+char *md5;                     body content MD5 checksum
+
+     The following BODY information is used only by c-client
+internally.  The use of this data is driver-specific and it can not be
+relied-upon by applications.
+
+unsigned char *contents.text;  drivers can store a pointer to the
+                                body contents as text here.            
+unsigned long size.ibytes;     internal size of the body content (prior
+                                to newline conversion, etc.) in octets
+
+
+     The MESSAGE structure is a parsed form of a MESSAGE/RFC822 MIME
+body part.  It contains the following information:
+
+ENVELOPE *env;                 encapsulated message RFC 822 header
+BODY *body;                    encapsulated message MIME structure
+
+     The following MESSAGE information is used only by c-client
+internally.  The use of this data is driver-specific and it can not be
+relied-upon by applications.
+
+char *hdr;                     encapsulated message header
+unsigned long hdrsize;         message header size
+char *text;                    message in RFC 822 form
+unsigned long offset;          offset of text from header
+
+
+     The PARAMETER structure is a parsed form of a linked list of
+attribute/value pairs.  It contains the following information:
+
+char *attribute;               attribute name
+char *value;                   value
+PARAMETER *next;               next parameter in list
+
+
+     The PART structure is a parsed form of a linked list of MIME body
+parts.  It contains the following information:
+
+BODY body;                     body information for this part
+PART *next;                    next body part
+
+     The following PART information is used only by c-client
+internally.  The use of this data is driver-specific and it can not be
+relied-upon by applications.
+
+unsigned long offset;          offset from body origin
+
+
+    The NETMBX structure is a parsed form of a network mailbox name:
+
+char host[NETMAXHOST];         remote host name
+char user[NETMAXUSER];         remote user name if specified
+char mailbox[NETMAXMBX];       remote mailbox name
+char service[NETMAXSRV];       remote service name (IMAP4, NNTP, etc.)
+unsigned long port;            TCP/IP port number if specified
+unsigned int anoflag : 1;      anonymous access requested
+unsigned int dbgflag : 1;      protocol debugging telemetry, via
+                                mm_dlog(), requested
+
+
+     The STRINGLIST structure is a list of strings (which may have
+embedded NULs) and their lengths:
+
+char *text;                    string text
+unsigned long size;            string length
+STRINGLIST *next;              next string in list
+\f
+                         String Structures
+
+     A string structure is analogous to a char*, and is used in some
+functions as an input argument.  It represents a string of data in a
+way that does not necessarily require the entire string to be in
+memory at once.  This is essential for small machines with
+highly-restricted memory limits (e.g. DOS).
+
+                      String Structure Access
+
+     To use a string structure, the caller needs to know a string
+driver and needs to know the driver-dependent data used by that string
+structure.  A simple string driver is mail_string, a string driver
+that takes an in-memory char* string as the driver-dependent data.
+The DOS port uses string drivers that take a struct holding a file
+descriptor and a file offset.  Often the user of a string driver is
+the same module that defined it, so usually the programmer knows about
+its conventions.
+
+     The following calls are used to access a string structure:
+
+void INIT (STRING *s,STRINGDRIVER *d,void *data,unsigned long size);
+       s       pointer to the string structure to be initialized
+       d       pointer to the string driver
+       data    pointer to driver-dependent data, from which the
+                driver can determine string data
+       size    size of the string
+ This call initializes the string stucture.
+
+
+unsigned long SIZE (STRING *s);
+       s       pointer to the string structure
+ This call returns the number of characters remaining in the string
+after the current string character pointer.
+
+
+char CHR (STRING *s);
+       s       pointer to the string structure
+ This call returns the character at the current string character
+pointer.
+
+
+char SNX (STRING *s);
+       s       pointer to the string structure
+ This call returns the character at the current string character
+pointer, and increments the string character pointer.
+
+
+unsigned long GETPOS (STRING *s);
+       s       pointer to the string structure
+ This returns the value of the current string character pointer.
+
+
+void SETPOS (STRING *s,unsigned long i);
+       s       pointer to the string structure
+       i       new string pointer value
+ This method sets the string character pointer to the given value.
+
+
+                     String Structure Internals
+
+     A string structure holds the following data:
+
+void *data;            used by the string driver as it likes
+unsigned long data1;   used by the string driver as it likes
+unsigned long size;    static, holds the total length of the string
+                        from the INIT call
+char *chunk;           current chunk of in-memory data; this is used
+                        for buffering to avoid unnecessary calls to
+                        the string driver's next method.
+unsigned long chunksize; size of an in-memory data chunk
+unsigned long offset;  position of first character of the chunk in
+                        the overall string
+char *curpos;          current position; this is what CHR() will
+                        access
+unsigned long cursize; number of characters remaining in the current
+                        string
+STRINGDRIVER *dtb;     the string driver for this string structure
+
+
+     A string structure is manipulated by a string driver, which has
+the following access methods:
+
+void (*init) (STRING *s,void *data,unsigned long size);
+       s       pointer to the string structure to be initialized
+       data    pointer to driver-dependent data, from which the
+                driver can determine string data
+       size    size of the string
+ This method initializes the string stucture.  It can use the data,
+data1, and chunksize values as it likes.  The remaining values must be
+set up as follows:
+       size            static, copied from the size argument
+       chunk           pointer to a buffer loaded with initial data
+       chunksize       size of the buffer
+       offset          0
+       curpos          copied from chunk
+       cursize         copied from chunksize
+       dtb             STRINGDRIVER identity pointer
+
+
+char (*next) (STRING *s);
+       s       pointer to the string structure
+ This method returns the character at the current string character
+pointer, and increments the string character pointer.  This method
+is likely to call the setpos method if the desired character is not in
+the current chunk.
+
+
+void (*setpos) (STRING *s,unsigned long i);
+       s       pointer to the string structure
+       i       new string pointer value
+ This method sets the string character pointer to the given value.  If
+the pointer is not in the current chunk, then a new chunk is loaded
+and the associated values (chunk, offset, curpos, cursize) are
+adjusted accordingly.
+\f
+                     c-client Support Functions
+
+
+void mail_string_init (STRING *s,void *data,unsigned long size);
+char mail_string_next (STRING *s);
+void mail_string_setpos (STRING *s,unsigned long i);
+
+     These three functions are the init, next, and setpos string
+structure access methods for the build-in mail_string string driver.
+mail_string is a basic string driver for a char* string.  See the
+documentation below on "String Structures" for more information.
+
+
+void mail_link (DRIVER *driver);
+       driver  pointer to the driver to be added
+
+     This function adds the specified driver to the list of mailbox
+drivers.  Initially there are no drivers lunk, so all programs which
+intend to use c-client need to have at least one call to this function.
+
+     A function which uses IMAP4 would have a statement such as:
+       mail_link (&imapdriver);        /* link in IMAP driver */
+early in the program's initialization.  Normally, this is done by the
+statement
+       #include "linkage.c"
+which will include the "system standard driver linkage" defined when
+c-client was built.  By using linkage.c instead of explicit mail_link()
+calls, you are guaranteed that you will have a consistant linkage among
+all software built on this system.
+
+
+void auth_link (AUTHENTICATOR *auth);
+       auth    pointer to the authenticator to be added
+
+     This function adds the specified authenticator to the list of
+authenticators.  Initially there are no authenticators lunk.  Normally,
+this is done by linkage.c so you don't need to call this routine
+explicitly.
+
+
+void *mail_parameters (MAILSTREAM *stream,long function,void *value);
+       stream  stream to poll or NIL
+       function function code
+       value   new value for function codes that change a parameter
+
+     This function fetches or changes the settings of various c-client
+operational parameters depending upon the function.  If the stream is
+specified, only the action for the underlying driver for that stream is
+taken; however, the scope of the operational parameters is global so
+there is generally no reason for the stream argument ever to be
+non-NIL.
+
+     The function codes ENABLE_DRIVER and DISABLE_DRIVER take a driver
+pointer as a value.  These functions enable and disable mailbox
+processing by that driver.  By default, all drivers are enabled.
+
+     The remaining function codes are in a pair named GET_xxx to
+fetch an operational parameter and SET_xxx to set the parameter:
+
+ GET_DRIVERS / SET_DRIVERS
+        The list of currently lunk drivers.
+
+ GET_GETS / SET_GETS
+        If non-NIL, points to a function for reading message text.
+       Defaults to NIL.
+        This function is called with three arguments; a function
+       pointer to a "reading function", a stream for the reading
+       function, and a size in octets.  The reading function is
+       in turn called with the stream, a size in octets, and a
+       pointer to a readin buffer.
+        This function returns with a char* string, which will be
+       returned by the mail_fetchheader(), mail_fetchtext(), or
+       mail_fetchbody() function which triggered the message text
+       reading.
+        The purpose is to permit reading of large strings, without
+       requiring an in-memory buffer for the entire string.  The idea
+       is that this function can store the data in some form other
+       than a char* (e.g. a temporary file) and the main program will
+       recognize that it should get the text from there instead of
+       from the results from mail_fetch....().
+        This is only supported on DOS and Win16; on other platforms it
+       is inconsistent whether or not it works.
+
+ GET_CACHE / SET_CACHE
+        Points to the c-client cache manager function.  Defaults to
+       mm_cache().
+
+ GET_SMTPVERBOSE / SET_SMTPVERBOSE
+        If non-NIL, points to a function that accepts a char* string.
+       This function is called any time the SMTP routines receive a
+       response code less than 100.  The argument is the text of the
+       response code
+
+ GET_RFC822OUTPUT / SET_RFC822OUTPUT
+        If non-NIL, points to an alternate rfc822_output() function.
+       rfc822_output() will call this function and return instead of
+       doing its normal action.  See the description of
+       rfc822_output() for more information.   
+
+ GET_USERNAME / SET_USERNAME
+        The logged-in user name.
+
+ GET_HOMEDIR / SET_HOMEDIR
+        The home directory path name.
+
+ GET_LOCALHOST / SET_LOCALHOST
+        The local host name.
+
+ GET_SYSINBOX / SET_SYSINBOX
+        The "system INBOX" (where mail is delivered) path name.
+
+ GET_OPENTIMEOUT / SET_OPENTIMEOUT
+        TCP/IP open timeout in seconds.  Defaults to 0 (system
+       default timeout, usually 75 seconds on Unix).
+       
+ GET_READTIMEOUT / SET_READTIMEOUT
+        TCP/IP read timeout in seconds.  Defaults to 0 (no timeout).
+
+ GET_WRITETIMEOUT / SET_WRITETIMEOUT
+        TCP/IP write timeout in seconds.  Defaults to 0 (no timeout).
+
+ GET_CLOSETIMEOUT / SET_CLOSETIMEOUT
+        TCP/IP close timeout in seconds.  Defaults to 0 (no timeout).
+
+ GET_TIMEOUT / SET_TIMEOUT
+        If non-NIL, points to the function called when a TCP/IP
+       timeout occurs.  This function is called with the number of
+       seconds since the start of the TCP operation.  If it returns
+       non-zero, the TCP/IP operation is continued; if it returns
+       non-zero, the TCP/IP connection is aborted.
+
+ GET_RSHTIMEOUT / SET_RSHTIMEOUT
+        rsh connection timeout in seconds.  Defaults to 15 seconds.
+
+ GET_MAXLOGINTRIALS / SET_MAXLOGINTRIALS
+        The maximum number of login attempts permitted in an IMAP or
+       POP connection.  Defaults to 3.
+
+ GET_LOOKAHEAD / SET_LOOKAHEAD
+        The number of subsequent envelopes prefetched in IMAP when an
+       envelope is fetched.  Defaults to 20.
+
+ GET_IMAPPORT / SET_IMAPPORT
+        The IMAP port number.  Defaults to 143.
+
+ GET_PREFETCH / SET_PREFETCH
+        The number of envelopes prefetched in IMAP from the results
+       of a SEARCH.  Defaults to 20.
+
+ GET_CLOSEONERROR / SET_CLOSEONERROR
+        If non-NIL, close an opening IMAP connection if the SELECT
+       command fails instead of returning a half-open stream.
+       Defaults to NIL.
+
+ GET_POP3PORT / SET_POP3PORT
+        The POP3 port number.  Defaults to 110.
+
+ GET_UIDLOOKAHEAD / SET_UIDLOOKAHEAD
+        The number of UIDs premapped when a message number is
+       translated to a UID.  Defaults to 1000.
+
+ GET_MBXPROTECTION / SET_MBXPROTECTION
+        Default file protection for newly created mailboxes.
+       Defaults to 0600.
+
+ GET_DIRPROTECTION / SET_DIRPROTECTION
+        Default file protection for newly created directories.
+       Defaults to 0700.
+
+ GET_LOCKPROTECTION / SET_LOCKPROTECTION
+        Default file protection for locks.  Defaults to 0666.
+       WARNING: don't blithely change this.  If other processes
+       can't get access to a lock then they will have trouble in
+       locking properly.
+
+ GET_FROMWIDGET / SET_FROMWIDGET
+        If non-NIL, APPEND in the Unix mbox format will insert a
+       ">" character in front of all lines which begin with the
+       string "From ".  If NIL, it will only do so if the entire
+       line looks like a message delimiter (that is, the date is
+       also in correct format).  Defaults to T.
+
+ GET_NEWSACTIVE / SET_NEWSACTIVE
+        Netnews active file path name.
+
+ GET_NEWSSPOOL / SET_NEWSSPOOL
+        Netnews spool directory path name.
+
+ GET_NEWSRC / SET_NEWSRC
+        Netnews newsgroup reading status file (.newsrc) path name.
+
+ GET_EXTENSION / SET_EXTENSION
+        If non-NIL, points to a string holding the extension for all
+       mailbox files.  This is only supported on DOS and Win16.
+
+ GET_DISABLEFCNTLLOCK / SET_DISABLEFCNTLLOCK
+        If non-NIL, disables fcntl() locking on SVR4.  This is done
+       if fcntl() tends to hang for no good reason.  Now that the
+       fcntl() code checks for NFS files and no-ops the locking,
+       this problem usually doesn't happen much any more.  Defaults
+       to NIL.
+
+ GET_LOCKEACCESERROR / SET_LOCKEACCESERROR
+        If non-NIL, give a warning if an attempt to create a .lock
+       file gets an EACCES ("Permission denied") error.  This usually
+       means that somebody protected the system inbox directory (e.g.
+       /var/mail) instead of making it public-write with the sticky
+       bit.  Defaults to non-NIL, since this is usually bad news.
+
+ GET_LISTMAXLEVEL / SET_LISTMAXLEVEL
+        The maximum depth of recusion that LIST will go on a *
+       wildcard.  Defaults to 20.
+
+ GET_ANONYMOUSHOME / SET_ANONYMOUSHOME
+        The anonymous use home directory name.
+
+
+typedef long (*readfn_t) (void *stream,unsigned long size,char *buffer);
+       stream  a designator suitable
+       size    a number of octets to read
+       buffer  a buffer of at least size octets for readin
+
+     This function reads the given number of octets into the buffer,
+using the given stream.  What sort of object the stream is depends upon
+the function and its caller, so you must make sure that the readfn is
+suitable for the caller's purpose.  Common uses include support of the
+mailgets function (see below) and of reading from local files on systems
+with limited address space.
+
+
+typedef char *(*mailgets_t) (readfn_t f,void *stream,unsigned long size);
+       f       the readfn to use
+       stream  stream argument for the readfn
+       size    total number of octets to read
+
+     This is the argument to the SET_GETS mail_parameter() call.  This
+function must read size octets from the stream, using the readfn f.  It
+may call f multiple times to accomplish this; this will read the data in
+a serial fashion.  So, for example, if size is a megabyte and there is
+only 4K of available buffer space, it can call f 256 times to satisfy
+the request.  There is no way to back up in the reading, so any
+processing or saving of the data must be done when it is read.
+
+     The function mm_gets() in mail.c is a sample mailgets function; it
+reads the first MAXMESSAGESIZE of data into memory and discards the
+rest.
+
+
+typedef void *(*mailcache_t) (MAILSTREAM *stream,unsigned long msgno,long op);
+       stream  stream to cache manage
+       msgno   message to cache manage in the stream
+       op      cache management operation
+
+     This function manages the c-client cache.  Normally, a program will
+use the default c-client cache manager routine mm_cache().  However, a
+main program may want to supply its own cache manager, e.g. it may want
+to store the data on a disk file instead of in memory on DOS and Win16
+where memory is tight.
+
+     If you write your own cache manager, you need to examine the
+default mm_cache() manager closely, as well as paying close attention to
+what goes into an elt (a MESSAGECACHE element).  It is highly likely
+that if you roll elts out to disk, you will want to set stream->scache
+and *NOT* use long elts (because long elts have ENVELOPE and BODY
+pointers that you would have to know how to write to disk and read back).
+
+     The cache management functions are one of the following:
+
+ CH_INIT        Initialize the entire cache for the stream.  This is
+               called only when creating a new stream or when freeing
+               it.  The msgno argument is ignored.
+
+ CH_SIZE        Make sure that the cache is at least large enough to
+               support msgno.  This is a request to grow the cache if
+               necessary, not shrink it.
+
+ CH_MAKELELT    Return a long elt for msgno, creating it if necessary.
+               This is the underlying support function for mail_lelt().
+
+ CH_LELT        Return the long elt for msgno, or NIL if it does not
+               already exist.
+
+ CH_MAKEELT     Return an elt for msgno, creating it if necessary.
+               This is the underlying support function for mail_elt().
+
+ CH_ELT                 Return the elt for msgno, or NIL if it does not already
+               exist.
+
+ CH_FREE        Free the [l]elt for msgno.
+
+ CH_EXPUNGE     Free the [l]elt for msgno, and reclaim its position.
+               All subsequent elts are renumbered with their elt->msgno
+               decremented by 1.  [Hence msgno+1 becomes msgno, etc.]
+               This supports message expunging from the cache.
+
+
+typedef long (*tcptimeout_t) (long time);
+       time    total time spent since TCP operation started
+
+     This function is called when a TCP operation times out.  It is set
+by the SET_TIMEOUT mail_parameter().  The function can return non-zero
+to continue the TCP operation (e.g. after outputting a "do you still
+want to wait" prompt) or zero if it wants the TCP operation to abort and
+close.  If the TCP operation aborts, it will likely cause the upper
+level IMAP, SMTP, etc. stream to abort and close as well.
+
+
+DRIVER *mail_valid (MAILSTREAM *stream,char *mailbox,char *purpose);
+       stream  if non-NIL, stream to use for validation
+       mailbox mailbox name to validate
+       purpose filled in as xxx in "Can't xxx" in error messages
+
+     This function validates the given mailbox name.  It successful, it
+returns the driver that can open that name if successful, otherwise it
+returns NIL.  If stream is non-NIL, the mailbox name must be valid for
+the type of mailbox associated with that stream (e.g. an NNTP name can
+not be used with an IMAP stream).  If purpose is non-NIL, an error
+message is passed via mm_log() when an error occurs.
+
+
+DRIVER *mail_valid_net (char *name,DRIVER *drv,char *host,char *mailbox);
+       name    mailbox name to validate
+       drv     driver name to validate against
+       host    buffer to return host name if non-NIL
+       mailbox buffer to return remote mailbox name if non-NIL
+
+     This function is an alternative to mail_valid_net_parse().  It
+validates the given mailbox name as a network name and makes sure that
+its service name is the same as the driver in drv.  If successful, it
+returns drv, and copies the host and mailbox strings as needed.
+Otherwise it returns NIL.
+
+
+long mail_valid_net_parse (char *name,NETMBX *mb);
+       name    mailbox name to parse
+       mb      pointer to NETMBX structure to return
+
+     This function parses a network mailbox name.  If the name is a
+network mailbox name, it returns non-NIL, with the NETMBX structure
+loaded with the results form the parse.
+\f
+                      Mailbox Access Functions
+
+void mail_list (MAILSTREAM *stream,char *ref,char *pat);
+void mail_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
+       stream  if non-NIL, stream to use
+       ref     mailbox reference string
+       pat     mailbox pattern string
+       contents contents to search
+
+     This function returns a list of mailboxes via the mm_list()
+callback.  The reference is applied to the pattern in an implementation
+dependent fashion, and the resulting string is used to search for
+matching mailbox names.  "*" is a wildcard which matches zero or more
+characters; "%" is a variant which does not descend a hierarchy level.
+Read the IMAP specification for more information.
+
+     mail_scan() is a variant which takes a string to search for in the
+text of the mailbox.  The string is a free-text string, without regard
+for message boundaries, and thus the choice of strings must be made
+with care.
+
+
+void mail_lsub (MAILSTREAM *stream,char *ref,char *pat);
+       stream  if non-NIL, stream to use
+       ref     mailbox reference string
+       pat     mailbox pattern string
+
+     This function returns a list of subscribed mailboxes via the
+mm_lsub() callback.  The reference is applied to the pattern in an
+implementation dependent fashion, and the resulting string is used to
+search for matching mailbox names in the subscription list.  "*" is a
+wildcard which matches zero or more characters; "%" is a variant which
+does not descend a hierarchy level.  Read the IMAP specification for
+more information.
+
+
+long mail_subscribe (MAILSTREAM *stream,char *mailbox);
+       stream  if non-NIL, stream to use
+       mailbox mailbox name
+
+     This function adds the given name to the subscription list.  It
+returns T if successful, NIL if unsuccessful.  If unsuccessful, an
+error message is returned via the mm_log() callback.
+
+
+long mail_unsubscribe (MAILSTREAM *stream,char *mailbox);
+       stream  if non-NIL, stream to use
+       mailbox mailbox name
+
+     This function removes the given name from the subscription list.
+It returns T if successful, NIL if unsuccessful.  If unsuccessful, an
+error message is returned via the mm_log() callback.
+
+
+long mail_create (MAILSTREAM *stream,char *mailbox);
+       stream  if non-NIL, stream to use
+       mailbox mailbox name
+
+     This function creates a mailbox with the given name.  It returns T
+if successful, NIL if unsuccessful.  If unsuccessful, an error message
+is returned via the mm_log() callback.
+
+     It is an error to create INBOX or a mailbox name which already
+exists.
+
+
+long mail_delete (MAILSTREAM *stream,char *mailbox);
+       stream  if non-NIL, stream to use
+       mailbox mailbox name
+
+     This function deletes the named mailbox.  It returns T if
+successful, NIL if unsuccessful.  If unsuccessful, an error message is
+returned via the mm_log() callback.
+
+     It is an error to delete INBOX or a mailbox name which does not
+already exist.
+
+
+long mail_rename (MAILSTREAM *stream,char *old,char *newname);
+       stream  if non-NIL, stream to use
+       old     existing mailbox name
+       newname new (not yet existing) mailbox name
+
+     This function renames the old mailbox to the new mailbox name.
+It returns T if successful, NIL if unsuccessful.  If unsuccessful, an
+error message is returned via the mm_log() callback.
+
+     It is an error to reanme a mailbox that does not exist, or rename
+a mailbox to a name that already exists.  It is permitted to rename
+INBOX; a new empty INBOX is created in its place.
+
+
+long mail_status (MAILSTREAM *stream,char *mbx,long flags);
+       stream  if non-NIL, stream to use
+       mbx     mailbox name
+       flags   option flags
+
+     This function returns the status of the given mailbox name via the
+mm_status() callback.  It returns T if successful, NIL if unsuccessful.
+If unsuccessful, an error message is returned via the mm_log()
+callback.
+
+     The options are a bit mask with one or more of the following,
+indicating the data which should be returned.
+       SA_MESSAGES     number of messages in the mailbox
+       SA_RECENT       number of recent messages in the mailbox
+       SA_UNSEEN       number of unseen messages in the mailbox
+       SA_UIDNEXT      next UID value to be assigned
+       SA_UIDVALIDITY  UID validity value
+
+     Note that, depending upon implementation, some of these values may
+be more costly to get than others.  For example, calculating the
+number of unseen messages may require opening the mailbox and scanning
+all of the message flags.  A mail_status() call should thus be used
+with option flags specifying only the data that is actually needed.
+
+
+MAILSTREAM *mail_open (MAILSTREAM *oldstream,char *name,long options);
+       oldstream if non-NIL, stream to recycle
+       name    mailbox name to open
+       options option flags.
+
+     This function opens the mailbox and if successful returns a stream
+suitable for use by the other MAIL functions.
+
+     If oldstream is non-NIL, an attempt is made to reuse oldstream as
+the stream for this mailbox; this is useful when you want to open
+another mailbox to the same IMAP or NNTP server without having to open
+a new connection.  Doing this will close the previously open mailbox.
+
+     The options are a bit mask with one or more of the following:
+       OP_DEBUG        Log IMAP protocol telemetry through mm_debug()
+       OP_READONLY     Open mailbox read-only.
+       OP_ANONYMOUS    Don't use or update a .newsrc file for news.
+       OP_SHORTCACHE   Don't cache envelopes or body structures
+       OP_SILENT       Don't pass mailbox events (internal use only)
+       OP_PROTOTYPE    Return the "prototype stream" for the driver
+                        associated with this mailbox instead of
+                        opening the stream
+       OP_HALFOPEN     For IMAP and NNTP names, open a connection
+                        to the server but don't open a mailbox.
+       OP_EXPUNGE      Silently expunge the oldstream before recycling
+
+ NIL is returned if this function fails for any reason.
+
+
+MAILSTREAM *mail_close (MAILSTREAM *stream);
+MAILSTREAM *mail_close_full (MAILSTREAM *stream,long options);
+       stream  stream to close
+       options option flags
+     This function closes the MAIL stream and frees all resources
+associated with it that it may have created (subject to any handles
+existing).
+
+     The options for mail_close_full() are a bit mask with one or more
+of the following:
+       CL_EXPUNGE      Silently expunge before closing
+
+     This function always returns NIL, so it can be used as:
+       stream = mail_close (stream);
+\f
+                          Handle Functions
+
+     Handles are used when an entity that wishes to access the stream
+may survive the stream without knowing that it outlived it.  For
+example, an object reading a message may have a handle to a stream,
+but the message selection object that spawned it (and which owns the
+stream) may have gone away.  A stream can be closed or recycled while
+handles are pointing at it, but it is not completely freed until all
+handles are gone.  A stream may have an arbitrary number of handles.
+
+
+MAILHANDLE *mail_makehandle (MAILSTREAM *stream);
+       stream  stream to make handle to
+
+     This function creates and returns a handle to the stream.
+
+
+void mail_free_handle (MAILHANDLE **handle);
+       handle  pointer to handle to release
+
+     This function frees the handle and notifies the stream that it has
+one fewer handle.  If this is the last handle on the stream and the
+stream has been closed, then the stream is freed.
+
+
+MAILSTREAM *mail_stream (MAILHANDLE *handle);
+       handle  handle to look up
+
+     This function returns the stream associated with the handle if and
+only if the stream still represents the same MAIL connection associated
+with the handle.  Otherwise, NIL is returned (meaning that there is no
+active stream associated with this handle).
+\f
+                   Message Data Fetching Functions
+
+[Note!!  There is an important difference between a "sequence" and a
+ "msgno".  A sequence is a string representing one or more messages in
+ IMAP4-style sequence format ("n", "n:m", or combination of these
+ delimited by commas), whereas a msgno is an int representing a single
+ message.] 
+
+void mail_fetchfast (MAILSTREAM *stream,char *sequence);
+void mail_fetchfast_full (MAILSTREAM *stream,char *sequence,long flags);
+       stream  stream to fetch on
+       sequence IMAP-format set of message sequence numbers
+       flags   option flags
+
+     This function causes a cache load of all the "fast" information
+(internal date, RFC 822 size, and flags) for the given sequence.  Since
+all this information is also fetched by mail_fetchstructure(), this
+function is generally not used unless the OP_SHORTCACHE option in the
+mail_open() call is used.
+
+     The options for mail_fetchfast_full() are a bit mask with one or
+more of the following:
+       FT_UID          The sequence argument contains UIDs instead of
+                        sequence numbers
+
+
+void mail_fetchflags (MAILSTREAM *stream,char *sequence);
+void mail_fetchflags_full (MAILSTREAM *stream,char *sequence,long flags);
+
+     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) as part of a "check
+entire mailbox" (as opposed to "check for new messages") operation.
+
+ The options for mail_fetchflags_full() are a bit mask with one or more
+of the following:
+       FT_UID          The sequence argument contains UIDs instead of
+                        sequence numbers
+
+
+ENVELOPE *mail_fetchenvelope (MAILSTREAM *stream,unsigned long msgno);
+ENVELOPE *mail_fetchstructure (MAILSTREAM *stream,unsigned long msgno,
+                              BODY **body);
+ENVELOPE *mail_fetchstructure_full (MAILSTREAM *stream,unsigned long msgno,
+                                   BODY **body,long flags);
+       stream  stream to fetch on
+       msgno   message sequence number
+       body    pointer to where to return BODY structure if non-NIL
+       flags   option flags
+     This function causes a fetch of all the structured information
+(envelope, internal date, RFC 822 size, flags, and body structure) for
+the given msgno and, in the case of IMAP, 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 and the BODY for this msgno is returned.
+It is possible for the BODY to be NIL, in which case no information is
+available about the structure of the message body.
+
+     The options for mail_fetchstructure_full() are a bit mask with one
+or more of the following:
+       FT_UID          The msgno argument is a UID 
+
+     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 mail_elt().
+
+
+char *mail_fetchheader (MAILSTREAM *stream,unsigned long msgno);
+char *mail_fetchheader_full (MAILSTREAM *stream,unsigned long msgno,
+                            STRINGLIST *lines,unsigned long *len,long flags);
+       stream  stream to fetch on
+       msgno   message sequence number
+       lines   list of header lines to fetch
+       len     returned length in octets
+       flags   option flags
+
+     This function causes a fetch of the complete, unfiltered RFC 822
+format header of the specified message as a text string and returns
+that text string.
+
+     If the lines argument is non-NIL, it contains a list of header
+field names to use in subsetting the header text.  Only those lines
+which have that header field name are returned, unless FT_NOT is set in
+which case only those lines which do not have that header field name
+are returned.
+
+     If the len argument is non-NIL, it holds a pointer in which the
+length of the string in octets is returned.  This is useful in cases
+where there may be an embedded null in the string.
+
+     This function always returns a valid string pointer; if no header
+exists or if it can not be fetched (e.g. by a deceased IMAP stream) an
+empty string is returned.
+
+     The options for mail_fetchheader_full() are a bit mask with one or
+more of the following:
+       FT_UID          The msgno argument is a UID 
+       FT_NOT          The returned header lines are those that are
+                        not in the lines argument
+       FT_INTERNAL     The return string is in "internal" format,
+                        without any attempt to canonicalize to CRLF
+                         newlines
+       FT_PREFETCHTEXT The RFC822.TEXT should be pre-fetched at the
+                        same time.  This avoids an extra RTT on an
+                        IMAP connection if a full message text is
+                        desired (e.g. in a "save to local file"
+                        operation)
+                
+
+char *mail_fetchtext (MAILSTREAM *stream,unsigned long msgno);
+char *mail_fetchtext_full (MAILSTREAM *stream,unsigned long msgno,
+                          unsigned long *len,long flags);
+       stream  stream to fetch on
+       msgno   message sequence number
+       len     returned length in octets
+       flags   option flags
+
+     This function causes a fetch of the non-header text of the
+specified message as a text string and returns that text string.  No
+attempt is made to segregate individual body parts.
+
+     If the len argument is non-NIL, it holds a pointer in which the
+length of the string in octets is returned.  This is useful in cases
+where there may be an embedded null in the string.
+
+     This function always returns a valid string pointer; if no header
+exists or if it can not be fetched (e.g. by a deceased IMAP stream) an
+empty string is returned.
+
+      The options for mail_fetchtext_full() are a bit mask with one or
+more of the following:
+       FT_UID          The msgno argument is a UID 
+       FT_PEEK         Do not set the \Seen flag if it not already set
+       FT_INTERNAL     The return string is in "internal" format,
+                        without any attempt to canonicalize to CRLF
+                         newlines
+
+
+char *mail_fetchbody (MAILSTREAM *stream,unsigned long msgno,char *sec,
+                     unsigned long *len);
+char *mail_fetchbody_full (MAILSTREAM *stream,unsigned long msgno,char *sec,
+                          unsigned long *len,long flags);
+       stream  stream to fetch on
+       msgno   message sequence number
+       sec     section specifier
+       len     returned length in octets
+       flags   option flags
+
+      This function causes a fetch of the particular section of the
+body of the specified message as a text string and returns that text
+string.  The section specification is a string of integers delimited by
+period which index into a body part list as per the IMAP4
+specification.  Body parts are not decoded by this function; see
+rfc822_base64() and rfc822_quotedprintable().
+
+     If the len argument is non-NIL, it holds a pointer in which the
+length of the string in octets is returned.  This is useful in cases
+where there may be an embedded null in the string.
+
+      This function may return NIL on error.
+
+      The options for mail_fetchbody_full() are a bit mask with one or
+more of the following:
+       FT_UID          The msgno argument is a UID 
+       FT_PEEK         Do not set the \Seen flag if it not already set
+       FT_INTERNAL     The return string is in "internal" format,
+                        without any attempt to canonicalize to CRLF
+                         newlines
+
+
+unsigned long mail_uid (MAILSTREAM *stream,unsigned long msgno);
+       stream  stream to fetch on
+       msgno   message sequence number
+
+      This function returns the UID for the given message sequence
+number.
+
+
+void mail_fetchfrom (char *s,MAILSTREAM *stream,unsigned long msgno,
+                    long length);
+       s       destination string
+       stream  stream to fetch on
+       msgno   message sequence number
+       length  maximum field length
+
+     This function writes a "from" string of the specified length for
+the specified message, suitable for display to the user in a menu line,
+into the string pointed to by s.
+
+      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 the length argument.
+
+
+void mail_fetchsubject (char *s,MAILSTREAM *stream,unsigned long msgno,
+                       long length);
+       s       destination string
+       stream  stream to fetch on
+       msgno   message sequence number
+       length  maximum field 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
+mail_fetchfrom(), this function can return a string of shorter length
+than what the caller requested.
+
+
+LONGCACHE *mail_lelt (MAILSTREAM *stream,unsigned long msgno);
+MESSAGECACHE *mail_elt (MAILSTREAM *stream,unsigned long msgno);
+       stream  stream to access
+       msgno   message sequence number
+
+     This function returns the cache entry for the specified message.
+Although it 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 mail_fetchfast() or
+mail_fetchstructure() on the message first.
+
+     A cache entry holds the internal date/time, flags, and RFC 822
+size of a message.  It holds other data as well, but that is for
+internal use only.
+
+     mail_lelt() is a variant that returns a `long' cache entry, which
+consists of an cache entry (as a structure, not a pointer), an envelope
+pointer, and a body pointer.  This is used in conjunction with the elt
+lock count functionality, to allow an application to associate the
+cached envelope and body of a message with an open window even if the
+message is subsequently expunged or if the stream is closed.
+
+     Unless your application wants to look at cached envelopes and
+bodies even after the message is expunged or the stream is closed, it
+should not use mail_lelt().  Instead, it should use a returned elt from
+mail_elt() and use the elt->msgsno as the argument to
+mail_fetchstructure().
+
+       BEWARE: the behavior of mail_lelt() is undefined if the
+       stream is open with OP_SHORTCACHE.  mail_lelt() is extremely
+       special purpose, and should only be used in sophisticated
+       special purpose applications after discussing its use with
+       the c-client author.  If you think you need this function,
+       you are probably mistaken.  In almost all cases, you should
+       use mail_elt() and mail_fetchstructure() instead.
+\f
+                Message Status Manipulation Functions
+
+void mail_setflag (MAILSTREAM *stream,char *sequence,char *flag);
+void mail_setflag_full (MAILSTREAM *stream,char *sequence,char *flag,
+                       long flags);
+       stream  stream to use
+       sequence IMAP-format set of message sequence numbers
+       flag    IMAP-format flag string
+       flags   option flags
+
+    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 mm_log() facility.
+
+     The options for mail_setflag_full() are a bit mask with one or
+more of the following:
+       ST_UID          The sequence argument contains UIDs instead of
+                        sequence numbers
+       ST_SILENT       Do not update the local cache with the new
+                        value of the flags.  This is useful to save
+                        network bandwidth, at the cost of invalidating
+                        the cache.
+
+
+void mail_clearflag (MAILSTREAM *stream,char *sequence,char *flag);
+void mail_clearflag_full (MAILSTREAM *stream,char *sequence,char *flag,
+                         long flags);
+       stream  stream to use
+       sequence IMAP-format set of message sequence numbers
+       flag    IMAP-format flag string
+       flags   option flags
+
+     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 mm_log() facility.
+
+     The options for mail_setflag_full() are a bit mask with one or
+more of the following:
+       ST_UID          The sequence argument contains UIDs instead of
+                        sequence numbers
+       ST_SILENT       Do not update the local cache with the new
+                        value of the flags.  This is useful to save
+                        network bandwidth, at the cost of invalidating
+                        the cache.
+\f
+                          Mailbox Searching
+
+void mail_search (MAILSTREAM *stream,char *criteria);
+void mail_search_full (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,
+                      long flags);
+       stream  stream to search
+       charset MIME character set to use when searching strings
+       pgm     search program
+       flags   option flags
+
+     This function causes a mailbox search, using the given MIME
+charset (NIL means the default, US-ASCII) and the given search program.
+A search program is a structure that holds the following data:
+
+SEARCHSET *msgno;      a set of message sequence numbers
+SEARCHSET *uid;                a set of unique identifiers
+SEARCHOR *or;          OR result of two search programs
+SEARCHPGMLIST *not;    AND result of list of NOT'ed search programs
+SEARCHHEADER *header;  message headers
+STRINGLIST *bcc;       string(s) appear in bcc list
+STRINGLIST *body;      string(s) appear in message body text
+STRINGLIST *cc;                string(s) appear in cc list
+STRINGLIST *from;      string(s) appear in from
+STRINGLIST *keyword;   user flag string(s) set
+STRINGLIST *unkeyword; user flag strings() not set
+STRINGLIST *subject;   string(s) appear in subject
+STRINGLIST *text;      string(s) appear in message header or body
+STRINGLIST *to;                string(s) appear in to list
+unsigned long larger;  larger than this many octets
+unsigned long smaller; smaller than this many octes
+       The following dates are in form:
+               ((year - BASEYEAR) << 9) + (month << 5) + day
+unsigned short sentbefore;
+                       sent before this date
+unsigned short senton; sent on this date
+unsigned short sentsince;
+                       sent since this date
+unsigned short before; received before this date
+unsigned short on;     received on this date
+unsigned short since;  received since this date
+unsigned int answered : 1;
+                       message answered
+unsigned int unanswered : 1;
+                       message not answered
+unsigned int deleted : 1;
+                       message deleted
+unsigned int undeleted : 1;
+                       message not deleted
+unsigned int draft : 1;        message is a draft
+unsigned int undraft : 1;
+                       message is not a draft
+unsigned int flagged : 1;
+                       message flagged as urgent
+unsigned int unflagged : 1;
+                       message not flagged as urgent
+unsigned int recent : 1;
+                       message recent since last parse of mailbox
+unsigned int old : 1;  message not recent since last parse of mailbox
+unsigned int seen : 1; message read
+unsigned int unseen : 1;
+                       message not read
+
+     The following auxillary structures are used by search programs:
+       SEARCHHEADER:   header line searching
+char *line;            header line field name
+char *text;            text header line
+SEARCHHEADER *next;    next SEARCHHEADER in list (AND'ed)
+
+       SEARCHSET:      message number set
+unsigned long first;   first number in set
+unsigned long last;    if non-zero, last number in set
+SEARCHSET *next;       next SEARCHSET in list (AND'ed)
+
+       SEARCHOR:       two search programs, OR'ed together
+SEARCHPGM *first;      first program
+SEARCHPGM *second;     second program
+SEARCHOR *next;                next SEARCHOR in list
+
+       SEARCHPGMLIST:  list of search programs
+SEARCHPGM *pgm;                search program (AND'd with others in list)
+SEARCHPGMLIST *next;   next SEARCHPGM in list
+
+     mail_search(), the older interface, accepts a search criteria
+argument as a character string in IMAP2 (RFC-1176) format.  Do not try
+to use any IMAP4 search criteria with this interface.
+
+     The application's mm_searched() function is called for each
+message that matches the search criteria.  In addition, after the
+search is completed, the "fast" information (see mail_fetchfast_full()
+and envelopes of the searched messages are fetched (this is called
+pre-fetching).
+
+     If there is any problem in searching, a message will be passed to
+the application via the mm_log() facility.
+
+     The flags for mail_search_full() are a bit mask with one or more
+of the following:
+       SE_UID          Return UIDs instead of sequence numbers
+       SE_FREE         Return the search program to free storage after
+                        finishing
+       SE_NOPREFETCH   Don't prefetch searched messages.
+
+
+unsigned long *mail_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg,
+                         SORTPGM *pgm,long flags);
+       stream  stream to sort
+       charset MIME character set to use when sorting strings
+       spg     search program
+       pgm     sort program
+       flags   option flags
+
+
+     This function is a variant of mail_search_full().  It accepts an
+additional argument, a sort program, which specifies one or more sort
+rules to be applied to the result.  If the searching and sorting are
+successful, it returns a 0-terminated vector of message sequence
+numbers (or UIDs if SE_UID is set).  This vector is created out of
+free storage, and must be freed with fs_give() when finished with it.
+
+     A sort program is a structure that holds the following data:
+unsigned int reverse : 1;
+                       reverse sorting of this key
+short function;                sort rule, one of the following:
+               SORTDATE        message Date
+               SORTARRIVAL     arrival date
+               SORTFROM        mailbox in first From address
+               SORTSUBJECT     message Subject
+               SORTTO          mailbox in first To address 
+               SORTCC          mailbox in first cc address 
+               SORTSIZE        size of message in octets
+SORTPGM *next;         next sort program to be applied if two or more
+                        messages collate identically with this rule
+
+     The flags for mail_search_full() are a bit mask with one or more
+of the following:
+       SE_UID          Return UIDs instead of sequence numbers
+       SE_FREE         Return the search program to free storage after
+                        finishing
+       SE_NOPREFETCH   Don't prefetch searched messages.
+       SO_FREE         Return the sort program to free storage after
+                        finishing
+\f
+             Miscellaneous Mailbox and Message Functions
+
+long mail_ping (MAILSTREAM *stream);
+       stream  string to ping
+
+     The function pings the stream to see if it is still active.  It may
+discover new mail; this is the preferred method for a periodic "new mail
+check" as well as a "keep alive" for servers which have an inactivity
+timeout.  It returns T if the stream is still alive, NIL otherwise.
+
+     If new mail is found, the application's mm_exists() function is
+called with the newly-determined number of messages in the mailbox.
+
+
+void mail_check (MAILSTREAM *stream);
+       stream  stream to checkpoint
+
+      This function causes a mailstore-defined checkpoint of the
+mailbox.  This may include such things as a writeback to disk, a check
+for flag changes in a shared mailbox, etc.  It is not a "check for new
+mail"; mail_ping() performs this function (as potentially does any other
+function).  The status of the check is passed to the application via the
+mm_log() facility.
+
+
+void mail_expunge (MAILSTREAM *stream);
+       stream  string to expunge
+
+     This function causes an expunge (permanent removal of messages
+which are marked as deleted) 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 mm_log() 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.
+
+
+long mail_copy (MAILSTREAM *stream,char *sequence,char *mailbox);
+long mail_move (MAILSTREAM *stream,char *sequence,char *mailbox);
+long mail_copy_full (MAILSTREAM *stream,char *sequence,char *mailbox,
+                    long options);
+       stream  stream to copy
+       sequence IMAP-format set of message numbers
+       mailbox destination mailbox name
+       options option flags
+
+     This function causes the messages in the specified sequence to be
+copied to the specified mailbox.  T is returned if the copy is
+successful.  mail_move() is equivalent to setting CP_MOVE in the options.
+
+     If there is any problem in copying, a message will be passed to
+the application via the mm_log() facility and the function returns NIL.
+No copying is actually done in this case.
+
+      Note that the mailbox must be on the same host as the stream and
+is a mailbox of the type of the source mailbox only.
+
+     The flags for mail_search_full() are a bit mask with one or more
+of the following:
+       CP_UID          The sequence argument contains UIDs instead of
+                        sequence numbers
+       CP_MOVE         Delete the messages from the current mailbox
+                        after copying to the destination.
+
+
+long mail_append (MAILSTREAM *stream,char *mailbox,STRING *message);
+long mail_append_full (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
+                      STRING *message);
+       stream  stream to use if non-NIL (in the IMAP case)
+       mailbox destination mailbox name
+       flags   flags to set on message if non-NIL
+       date    internal date (received date) to set on message if non-NIL
+       message string structure of message to write
+
+     This function writes the message in the string structure to the
+destination mailbox, along with the flags and date if specified.  This
+is useful in those cases where you can't use mail_copy(), e.g. when
+copying from one server to another; you can always fetch the message
+and then mail_append() it to the destination.  It may also be useful
+for maintaining an outbox of your outgoing mail.
+
+
+void mail_gc (MAILSTREAM *stream,long gcflags);
+       stream  stream to GC if non-NIL (else GC's all streams)
+       flags   option flags
+
+      This function garbage collects (purges) the cache of entries of
+a specific type.  Some drivers do not allow purging of particular
+cache types, and an attempt to do so is ignored.
+
+      The flags for mail_gc() are a bit mask with one or more of the
+following:
+       GC_ELT          message cache elements
+       GC_ENV          ENVELOPEs and BODYs
+       GC_TEXTS        cached texts
+\f
+                    Date/Time Handling Functions
+
+
+char *mail_date (char *string,MESSAGECACHE *elt);
+       string  destination string
+       elt     message cache element containing date
+
+      This function accepts a message cache element that contains date
+information, and writes an IMAP-4 date string, that is, one in form:
+       dd-mmm-yyyy hh:mm:ss +zzzz
+based upon the data in the elt.  The destination string must be large
+enough to hold this string.
+
+
+char *mail_cdate (char *string,MESSAGECACHE *elt);
+       string  destination string
+       elt     message cache element containing date
+
+      This function accepts a message cache element that contains date
+information, and writes a ctime() format date string, that is, one in
+form:
+       www mmm dd hh:mm:ss yyyy\n
+based upon the data in the elt.  The destination string must be large
+enough to hold this string.
+
+
+long mail_parse_date (MESSAGECACHE *elt,char *string);
+       elt     message cache element to store parsed date
+       string  source date string
+
+      This function parses the date/time stored in the given string,
+in format:
+       [www,] date [[hh:mm[:ss][-zzz| +zzzz]
+where the date can be any of:
+       mm/dd/yy, mm/dd/yyyy, dd-mmm-yy, dd-mmm-yyyy, dd mmm yy, dd mmm yyyy
+and stores the result of the parse in the elt.  If the parse is
+successful, T is returned, else NIL.
+
+
+unsigned long mail_longdate (MESSAGECACHE *elt);
+       elt     message cache element containing date.
+
+      This function accepts a message cache element that contains date
+information, and returns the number of days since the base time of the
+imap-4 toolkit.  At present, this is the same as the Unix time() value
+for that date/time, and hence can be used for functions such as utime().
+\f
+                         Utility Functions
+
+void mail_debug (MAILSTREAM *stream);
+       stream  stream to debug
+
+      This function enables telemetry logging for this stream.  All
+telemetry is passed to the application via the mm_dlog() facility.
+
+
+void mail_nodebug (MAILSTREAM *stream);
+       stream  stream to disable debugging
+
+     This function disables telemetry logging for this stream.
+
+
+long mail_sequence (MAILSTREAM *stream,char *sequence);
+       stream  stream to set the sequence bits
+       sequence IMAP-format message set string
+
+     This function parses the given sequence string for message
+numbers, sets the sequence bit in the stream's message cache element
+of all messages in the sequence (and turns it off in all other message
+cache elements).  If the parse is successful, T is returned, else NIL.
+
+
+long mail_uid_sequence (MAILSTREAM *stream,char *sequence);
+       stream  stream to set the sequence bits
+       sequence IMAP-format message set string
+
+     This function parses the given sequence string for unique
+identifiers, sets the sequence bit in the stream's message cache
+element of all messages in the sequence (and turns it off in all other
+message cache elements).  If the parse is successful, T is returned,
+else NIL.
+
+
+long mail_parse_flags (MAILSTREAM *stream,char *flag,unsigned long *uf);
+       stream  stream (used to get user flags)
+       flag    IMAP-format flag string to parse
+       uf      returned location of user flags
+
+     The function parses the given flag string, and returns the system
+flags as its return value and the user flags in the location pointed
+to by the uf argument.  If there is an error in parse, a log message
+is issued via mm_log() and this function returns NIL.
+
+
+unsigned long mail_filter (char *text,unsigned long len,STRINGLIST *lines,
+                          long flags);
+       text    RFC 822 text to filter
+       len     length in octets in the text argument
+       lines   string list of header file names to filter
+       flags   option flags
+
+     This function supports the header lines filtering function of
+mail_fetchheader_full().  The lines argument contains a list of header
+field names to use in subsetting the header text.  Only those lines
+which have that header field name are returned, unless FT_NOT is set
+in which case only those lines which do not have that header field
+name are returned.
+
+     The options for mail_filter() are a bit mask with one or more of
+the following:
+       FT_NOT          The returned header lines are those that are
+                        not in the lines argument
+
+
+long mail_search_msg (MAILSTREAM *stream,unsigned long msgno,char *charset,
+                     SEARCHPGM *pgm);
+       stream  stream to search
+       msgno   message number of message to inspect
+       charset character set of search strings
+       pgm     search program to test
+
+     This function implements mail_search_full() locally in cases when
+it is not done by a server (e.g. local mail files, NNTP/POP).  It
+inspects the given message on that stream to see if it matches the
+criteria or not.  If it matches, T is returned, else NIL.
+
+
+SEARCHPGM *mail_criteria (char *criteria);
+       criteria IMAP2-format search criteria string
+
+     This function accepts an IMAP2-format search criteria string and
+parses it.  If the parse is successful, it returns a search program
+suitable for use in mail_search_full().
+       WARNING: This function does not accept IMAP4 search criteria.
+       The source string must be writeable (this restriction was also
+       in the old IMAP2 c-client).
+\f
+          Data Structure Instantiation/Destruction functions
+
+     These functions are used to obtain structures from free storage and
+to release them.
+
+ENVELOPE *mail_newenvelope (void);
+ADDRESS *mail_newaddr (void);
+BODY *mail_newbody (void);
+BODY *mail_initbody (BODY *body);
+PARAMETER *mail_newbody_parameter (void);
+PART *mail_newbody_part (void);
+STRINGLIST *mail_newstringlist (void);
+SEARCHPGM *mail_newsearchpgm (void);
+SEARCHHEADER *mail_newsearchheader (char *line);
+SEARCHSET *mail_newsearchset (void);
+SEARCHOR *mail_newsearchor (void);
+SEARCHPGMLIST *mail_newsearchpgmlist (void);
+SORTPGM *mail_newsortpgm (void);
+
+     These functions, all named mail_new...(), create a new structure of
+the given type and initialize all of its elements to zero or empty.
+
+void mail_free_body (BODY **body);
+void mail_free_body_parameter (PARAMETER **parameter);
+void mail_free_body_part (PART **part);
+void mail_free_cache (MAILSTREAM *stream);
+void mail_free_elt (MESSAGECACHE **elt);
+void mail_free_lelt (LONGCACHE **lelt);
+void mail_free_envelope (ENVELOPE **env);
+void mail_free_address (ADDRESS **address);
+void mail_free_stringlist (STRINGLIST **string);
+void mail_free_searchpgm (SEARCHPGM **pgm);
+void mail_free_searchheader (SEARCHHEADER **hdr);
+void mail_free_searchset (SEARCHSET **set);
+void mail_free_searchor (SEARCHOR **orl);
+void mail_free_searchpgmlist (SEARCHPGMLIST **pgl);
+void mail_free_sortpgm (SORTPGM **pgm);
+
+     These functions, all named mail_free_...(), take a pointer to a
+structure pointer, free all contained strings and structures within the
+structure, and finally free the structure itself and set its pointer to
+NIL.  For example, mail_free_envelope() frees all the ADDRESS structures
+contained in the envelope.
+
+     Normally, mail_free_elt() and mail_free_lelt() are used only if the
+main program has a private pointer to cache elements.  If so, it is
+expected to increment the cache element's lockcount when it makes a
+private pointer, and to call this function when it is finished with it.
+\f
+                      Authentication Functions
+
+char *mail_auth (char *mechanism,authresponse_t resp,int argc,char *argv[]);
+       mechanism authentication mechanism name
+       resp    callback function for providing responses
+       argc    main() function argc value
+       argv    main() function argv value
+
+     This server function searches the list of authenticators that was
+established by auth_link() for an authenticator with the given name.  If
+an authenticator is found, authentication is initialized.  The function
+pointed to by resp is called as the authenticator requires responses.
+
+
+AUTHENTICATOR *mail_lookup_auth (unsigned int i);
+       i       position in authenticator list
+
+     This function returns the nth authenticator in the list, where n is
+the value of it.
+
+
+unsigned int mail_lookup_auth_name (char *mechanism);
+       mechanism authentication mechanism name
+
+     This function searches the list of authenticators for an
+authenticator with the given name, and returns its position in the
+authenticator list.
+
+
+     The functions below are provided by c-client client drivers or by
+servers to support the protocol-dependent parts of authentication.
+
+typedef void *(*authchallenge_t) (void *stream,unsigned long *len);
+       stream  stream to read challenge
+       len     pointer to returned length in octets
+
+     This driver function is called by an authenticator to read a
+challenge from the given protocol stream in a protocol-dependent way.
+It returns that challenge in binary and its length in octets to the
+authenticator.
+
+
+typedef long (*authrespond_t) (void *stream,char *s,unsigned long size);
+       stream  stream to send response
+       s       response string
+       size    length of response string in octets
+
+     This driver function is called by an authenticator to send a
+challenge response to the given stream in a protocol-dependent way.
+It returns T if successful, NIL if failure.
+
+
+typedef char *(*authresponse_t) (void *challenge,unsigned long clen,
+                                unsigned long *rlen);
+       challenge challenge string
+       clen    length of challenge string in octets
+       rlen    pointer to returned length of response string
+
+     This server function is called with a challenge string of clen
+octets.  It sends, according to whatever protocol (IMAP, POP, etc.) it
+uses, and returns the received response and response length in octets.
+
+
+typedef long (*authclient_t) (authchallenge_t challenger,
+                             authrespond_t responder,NETMBX *mb,void *s,
+                             unsigned long trial);
+       challenger pointer to protocol-dependent challenge reader function
+       responder pointer to protocol-dependent response sender function
+       mb      NETMBX struct of the mailbox desired to open
+       s       stream for protocol-dependent routines to use
+       trial   number of authentication attempts remaining
+
+     This client authenticator function negotiates reading challenges
+and sending responses for a particular authenticator (Kerberos, etc.)
+over the protocol, and returns T if authenticated or NIL if failed.
+
+
+typedef char *(*authserver_t) (authresponse_t responder,int argc,char *argv[]);
+       responder pointer to protocol-dependent responder function
+       argc    main() function argc value
+       argv    main() function argv value
+
+    This server authenticator function negotiates sending challenges and
+reading responses for a particular authenticator (Kerberos, etc.), and
+returns either the authenticated user name or NIL if authentication
+failed.
+\f
+                      Network Access Functions
+
+     These functions provide a layer of indirection between the TCP
+routines and upper level routines.  This makes it possible to insert
+additional code (e.g. privacy or checksum handling).
+
+NETSTREAM *net_open (char *host,char *service,unsigned long port);
+       host    host name
+       service contact service name
+       port    contact port number
+
+     This function opens a TCP connection to the given host and service
+or port.
+
+
+NETSTREAM *net_aopen (NETMBX *mb,char *service,char *usrbuf);
+       NETMBX  parsed mailbox specification
+       service stream to open (at present, only /etc/rimapd is used)
+       usrbuf  buffer to return login user name
+
+     This function attempts to open a preauthenticated connection to the
+given mailbox and service.  It will return the login user name of the
+preauthenticated connection, as well as an open network stream, if
+successful.
+
+
+char *net_getline (NETSTREAM *stream);
+       stream  network stream to read
+
+     This routine reads a text line from the stream.  It calls
+stream->dtb->getline, which normally points to tcp_getline() but can be
+set to some other function.
+
+
+long net_getbuffer (void *stream,unsigned long size,char *buffer);
+       stream  network stream to read
+       size    length of data in octets
+       buffer  buffer of at least size octets
+
+     This routine reads data from the stream.  It calls
+stream->dtb->getbuffer, which normally points to tcp_getbuffer() but can
+be set to some other function.
+
+
+long net_soutr (NETSTREAM *stream,char *string);
+       stream  network stream to write
+       string  null-terminated string to output
+
+     This routine writes a null-terminated string to the stream.  It
+calls stream->dtb->soutr, which normally points to tcp_soutr() but can
+be set to some other function.
+
+
+long net_sout (NETSTREAM *stream,char *string,unsigned long size);
+       stream  network stream to write
+       string  string to output
+       size    length of string in octets
+
+     This routine writes a string of length size to the stream.  It
+calls stream->dtb->sout, which normally points to tcp_sout() but can be
+set to some other function.
+
+
+void net_close (NETSTREAM *stream);
+       stream  stream to close
+
+     This routine closes the stream.  It calls stream->dtb->close, which
+normally points to tcp_close() but can point to some other function.
+
+
+char *net_host (NETSTREAM *stream);
+       stream  stream to inspect
+
+     This routine returns the remote host name of the stream.  It calls
+stream->dtb->host, which normally points to tcp_host() but can point
+to some other function.
+
+
+unsigned long net_port (NETSTREAM *stream);
+       stream  stream to inspect
+
+     This routine returns the remote port number of the stream.  It calls
+stream->dtb->port, which normally points to tcp_port() but can point
+to some other function.
+
+
+char *net_localhost (NETSTREAM *stream);
+       stream  stream to inspect
+
+     This routine returns the local host name of the stream.  It calls
+stream->dtb->localhost, which normally points to tcp_localhost() but can
+point to some other function.
+\f
+                 Subscription Management Functions
+
+long sm_subscribe (char *mailbox);
+       mailbox mailbox name to subscribe
+
+     This function adds the given mailbox name to the local subscription
+list, and returns T if successful, NIL if failure.
+
+
+long sm_unsubscribe (char *mailbox);
+       mailbox mailbox name to unsubscribe
+
+     This function removes the given mailbox name from the local
+subscription list, and returns T if successful, NIL if failure.
+
+char *sm_read (void **sdb);
+       sdb     data to use in subsequent calls, or NIL if first call
+
+     This function returns the local subscription list as null
+terminated strings.  Each call returns the next element in the list.
+The first call should be with sdb pointing to a NIL pointer; this will
+be filled in for subsequent calls.  At the last call, NIL will be
+returned.
+\f
+                   Miscellaneous Utility Functions
+
+char *ucase (char *string);
+       string  string to convert
+
+     This function converts each lowercase character of the specified
+string to uppercase and returns the string.
+
+
+char *lcase (char *string);
+       string  string to convert
+
+     This function converts each uppercase character of the specified
+string to lowercase and returns the string.
+
+
+char *cpystr (char *string);
+       string  string to copy
+
+ This function makes a copy of the string from free storage and returns
+the copy.
+
+
+long find_rightmost_bit (long *valptr);
+       valptr  pointer to value to search
+
+      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.
+
+
+long min (long i,long j);
+       i       first argument
+       j       second argument
+
+      This function returns the minimum of the two integers.
+
+long max (long i,long j);
+       i       first argument
+       j       second argument
+
+     This function returns the maximum of the two integers.
+
+long search (char *s,long c,char *pat,long patc);
+       s       string to search
+       c       size of string
+       pat     pattern to search in string
+       patc    size of pattern
+
+      This function does a fast case-independent search for the given
+pattern in pat (length patc) in base string s, and returns T if the
+pattern is found in the string.
+
+
+long pmatch (char *s,char *pat,delim);
+long pmatch_full (char *s,char *pat,delim);
+       s       string to match
+       pat     wildcard (* and %) to match in pattern
+       delim   hierarchy delimiter
+
+      This function returns T if the given wildcard pattern matches the
+string in s with hierarchy delimiter delim.  Otherwise NIL is returned.
+
+
+long dmatch (char *s,char *pat,char delim);
+       s       string to match
+       pat     wildcard (* and %) to match in pattern
+       delim   hierarchy delimiter
+
+     This function returns T if the given wildcard pattern matches the
+directory.  If not, then none of the elements in the directory are
+considered for recursive checking with pmatch_full().
+\f
+                            SMTP Functions
+
+SMTPSTREAM *smtp_open (char **hostlist,long debug);
+       hostlist vector of SMTP server host names to try
+       debug   non-zero if want protocol telemetry debugging
+
+      This function opens an SMTP connection to a one of the hosts in the
+host list and if successful returns a stream suitable for use by the
+other SMTP functions.  The hosts are tried in order until a connection is
+successfully opened.  If debug is non-NIL, protocol telemetry is logged
+via mm_dlog().  NIL is returned if this function fails to open a
+connection to any of the hosts in the list.
+
+void smtp_close (SMTPSTREAM *stream);
+       stream  stream to close
+
+     This function closes the SMTP stream and frees all resources
+associated with it that it may have created.
+
+long smtp_mail (SMTPSTREAM *stream,char *type,ENVELOPE *msg,BODY *body);
+       stream  stream to transmit mail
+       type    mail type (MAIL, SEND, SAML, SOML)
+       msg     message envelope
+       body    message body
+
+      This function negotiates an SMTP 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 stream->reply item; if
+it is associated with a recipient it is also in that address'
+address->error item.
+
+
+void smtp_debug (SMTPSTREAM *stream);
+       stream  stream to enable debugging telemetry
+
+      This function enables SMTP protocol telemetry logging for this
+stream.  All SMTP protocol operations are passed to the application via
+the mm_dlog() facility.
+
+
+void smtp_nodebug (SMTPSTREAM *stream);
+       stream  stream to disable debugging telemetry
+
+      This function disables SMTP protocol telemetry logging for this
+stream.
+
+
+typedef void (*smtpverbose_t) (char *buffer);
+       buffer  pointer to verbose reply buffer
+
+     This is the argument to the SET_SMTPVERBOSE mail_parmameter() call.
+If this function pointer is non-NIL, then if a verbose SMTP response
+(with SMTP code less than 100) is received, this function is called with
+that response text as its argument.
+\f
+                            NNTP Functions
+
+NNTPSTREAM *nntp_open (char **hostlist,long debug);
+       hostlist vector of NNTP server host names to try
+       debug   non-zero if want protocol telemetry debugging
+
+      This function opens an NNTP 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, protocol telemetry is logged
+via mm_dlog().  NIL is returned if this function fails to open a
+connection to any of the hosts in the list.
+
+
+void nntp_close (NNTPSTREAM *stream);
+       stream  stream to close
+
+     This function closes the NNTP stream and frees all resources
+associated with it that it may have created.
+
+
+long nntp_mail (NNTPSTREAM *stream,ENVELOPE *msg,BODY *body);
+       stream  stream to transmit mail
+       msg     message envelope
+       body    message body
+
+      This function negotiates an NNTP posting transaction to deliver
+the specified news message.  This function returns T if success or NIL
+if there is any failure.  The text reason for the failure is in
+stream->reply item; if it is associated with a recipient it is also in
+that address' address->error item.
+\f
+                     RFC 822 Support Functions
+
+     Although rfc822.c contains several additional functions besides
+these, only the functions documented here should be used by
+applications.  The other functions are for internal use only.
+
+
+void rfc822_header (char *header,ENVELOPE *env,BODY *body);
+       header  buffer to write RFC 822 header
+       env     message ENVELOPE (used to obtain RFC 822 information)
+       body    message BODY (used to obtain MIME information)
+
+     This function writes an RFC 822 format header into header based
+on the information in the envelope and body.  The header buffer must
+be large enough to contain the full text of the resulting header.
+
+
+void rfc822_write_address (char *dest,ADDRESS *adr);
+       dest    buffer to write address list
+       adr     RFC 822 ADDRESS list
+
+     This function writes an RFC 822 format address list into dest
+based on the information in adr.  The dest buffer must be large enough
+to contain the full text of the resulting address list.
+
+void rfc822_parse_msg (ENVELOPE **en,BODY **bdy,char *s,unsigned long i,
+                      STRING *b,char *host,char *tmp);
+       en      destination pointer where message ENVELOPE will be stored
+       bdy     destination pointer where message BODY will be stored
+       s       RFC 822 header to parse (character string)
+       i       length of RFC 822 header
+       b       stringstruct of message body
+       host    default host name if an address lacks an @host.
+       temp    scratch buffer, must be long enough to hold unwound
+                header lines (a buffer that is i octets long is OK)
+
+     This function parses the RFC 822 header pointed to by s with body
+pointed to by string structure b into the specified destination
+envelope and body pointers, using host as the default host name and
+tmp as a scratch buffer.  New ENVELOPE and BODY structures are
+created; when finished with them the application must free them with
+mail_free_envelope() and mail_free_body().  Any parsing errors are
+noted via the mm_log() mechanism using log type PARSE.
+
+
+void rfc822_parse_adrlist (ADDRESS **lst,char *string,char *host);
+       lst     destination pointer where ADDRESS will be stored
+       string  string of addresses to parse
+       host    default host name if an address lacks an @host.
+
+     This function parses the address list in the given string into an
+address list in lst.  Any addresses missing a host name are have the
+host name defaulted from the host argument.  If the destination list
+is non-empty it appends the new addresses to the list.  Any parsing
+errors are noted via the mm_log() mechanism using log type PARSE.
+
+long rfc822_output (char *t,ENVELOPE *env,BODY *body,soutr_t f,void *s,
+                   long ok8bit);
+       t       scratch buffer, large enough to hold message header
+       env     message ENVELOPE
+       body    message BODY
+       f       I/O function to write to
+       s       stream for I/O function f
+       ok8bit  non-zero if OK to output 8-bit data
+
+     This function writes the message described with the given
+envelope and body.  Any body part contents of type ENCBINARY is
+converted to ENCBASE64 before sending.  If ok8bit is NIL, any message
+data of type ENC8BIT is converted to ENCQUOTEDPRINTABLE before
+sending; if ok8bit is non-NIL then ENC8BIT data is sent as-is.  T is
+returned if the function succeeds, else NIL is returned.
+
+     The function f is typically net_soutr(), but it can be any
+function which matches
+  typedef long (*soutr_t) (void *stream,char *string);
+where stream holds sufficient information to enable the output routine
+to know where to output to, and the string is a null-terminated string
+to output.  This function returns either T or NIL, and that value is
+passed up to rfc822_output() for its return.
+
+
+void *rfc822_base64 (char *src,unsigned long srcl,unsigned long *len);
+       src     source string
+       srcl    size of source string in octets
+       len     pointer to where destination string length in octets
+                will be returned
+
+     This function decodes a BASE64 body part given a source string
+and its length.  The decoded body part as a sequence of binary octets
+is returned, and its length is returned in len.
+
+
+char *rfc822_qprint (char *src,unsigned long srcl,unsigned long *len);
+       src     source string
+       srcl    size of source string in octets
+       len     pointer to where destination string length in octets
+                will be returned
+
+     This function decodes a QUOTED-PRINTABLE body part given a source
+string and its length.  The decoded body part as an 8-bit character
+string is returned, and its length is returned in len.
+\f
+            Operating System-Dependent Public Interface
+
+     These functions are in OS-dependent code, and are rewritten each
+time c-client is ported to a new operating system.
+
+
+void rfc822_date (char *date);
+       date    buffer to write the date, must be large enough
+
+     This function is called to get the current date and time in an
+RFC 822 format string into the given buffer.
+
+
+void *fs_get (size_t size);
+       size    number of octets requested
+
+      This function allocates and returns a block of free storage of
+the specified size.  Unlike malloc(), there is no failure return; this
+function must return with the requested storage.
+
+
+void fs_resize (void **block,size_t size);
+       block   pointer to pointer to block to be resized
+       size    new size in octets
+
+     This function resizes the free storage block, updating the
+pointer if necessary.  Unlike realloc(), there is no failure return;
+this function must return with the requested storage.
+
+
+void fs_give (void **block);
+       block   pointer to pointer to block to free
+
+      This function releases a block of free storage allocated by
+fs_get().  It also erases the block pointer, so it isn't necessary to
+do this in the application.
+
+
+void fatal (char *string);
+       string  message string
+
+      This function is called when an "impossible" error is detected
+and the client wishes to crash.  The string should contain a reason.
+
+
+char *strcrlfcpy (char **dst,long *dstl,char *src,long srcl);
+       dst     pointer to destination string pointer
+       dstl    pointer to destination string size
+       src     source strin
+       srcl    source string size
+
+      This function is called to copy into a destination string dst of
+size dstl (resized if necessary), a CRLF newline form string from
+local format string src of size srcl.
+
+
+TCPSTREAM *tcp_open (char *host,long port);
+TCPSTREAM *tcp_aopen (char *host,char *service);
+char *tcp_getline (TCPSTREAM *stream);
+long tcp_getbuffer (TCPSTREAM *stream,long size,char *buffer);
+long tcp_soutr (TCPSTREAM *stream,char *string);
+void tcp_close (TCPSTREAM *stream);
+char *tcp_host (TCPSTREAM *stream);
+unsigned long tcp_port (TCPSTREAM *stream);
+char *tcp_localhost (TCPSTREAM *stream);
+
+     These functions are TCP-specific versions of the more general
+net_xxx() functions.  These should not be called directly by
+applications.
+
+
+char *tcp_clienthost (char *dst);
+       dst     destination string buffer
+
+     This function should be called only by a server called by inetd
+or similar mechanism which maps standard input to a network socket.
+It returns the host name of the other end (e.g. the client of a
+server) using the given string buffer, or NIL if it can't get this
+information.
+\f
+                       Main Program Callbacks
+
+     All applications which use the c-client must have the following
+callbacks to handle events from c-client.  Note that in any callback
+which involves a mail stream, the stream is locked and you can not
+recursively call c-client from the callback.  This may also be true in
+callbacks which do not have a stream; in general, the rule is "do not
+call c-client, especially any mail_xxx() function, from a c-client
+callback".
+
+
+void mm_flags (MAILSTREAM *stream,unsigned long number);
+       stream  stream where event happened
+       number  message number
+
+     This function is called when c-client manipulates the flags for
+the given message number.  This alerts the application that it may
+need to inspect that message's flags to see if there are any
+interesting changes.
+
+
+void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status);
+       stream  stream where event happened
+       mailbox mailbox name for this status
+       status  MAILSTATUS structure with message status
+
+     This function is called when c-client reports status of a mailbox
+(generally as the result of a mail_status() function call).  The
+returned MAILSTATUS structure has the following members:
+
+long flags;                    validity flags.  These are the same as
+                                the SA_xxx option flags in the
+                                mail_status() call, and they indicate
+                                which of the other members of the
+                                MAILSTATUS structure have usable data
+                                (i.e. if SA_MESSAGES is not set, do
+                                not believe status->messages!!).
+unsigned long messages;                number of messages if SA_MESSAGES
+unsigned long recent;          number of recent messages if SA_RECENT
+unsigned long unseen;          number of unseen messages if SA_UNSEEN
+unsigned long uidnext;         next UID to be assigned if SA_UIDNEXT
+unsigned long uidvalidity;     UID validity value if SA_UIDVALIDITY
+
+
+void mm_searched (MAILSTREAM *stream,unsigned long number);
+       stream  stream where event happened
+       number  message number
+
+     This function is called to notify the main program that this
+message number matches a search (generally as the result of a
+mail_search_full() function call).
+
+
+void mm_exists (MAILSTREAM *stream,unsigned long number);
+       stream  stream where event happened
+       number  message number
+
+     This function is called to notify the main program that there are
+this many messages in the mailbox.  It is also used to notify the main
+program of new mail, by announcing a higher number than the main
+program was previously aware.
+
+
+void mm_expunged (MAILSTREAM *stream,unsigned long number);
+       stream  stream where event happened
+       number  message number
+
+     This function is called 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.  This implicitly decrements the number of messages in the
+mailbox.
+
+
+void mm_list (MAILSTREAM *stream,char delim,char *name,long attrib);
+       stream  stream where event happened
+       delim   hierarchy delimiter
+       name    mailbox name
+       attrib  mailbox attributes
+
+     This function is called to notify the main program that this
+mailbox name matches a mailbox listing request (generally as the
+result of a mail_list() function call).  The hierarchy delimiter is a
+character that separates out levels of hierarchy in mailbox names.
+The attributes are a bit mask with one of the following:
+       LATT_NOINFERIORS
+                       it is not possible for there to be any
+                        hierarchy inferiors to this name (that is,
+                        this name followed by the hierarchy delimiter
+                        and additional name characters).
+       LATT_NOSELECT   this is not a mailbox name, just a hierarchy
+                        level, and it may not be opened by mail_open()
+       LATT_MARKED     this mailbox may have recent messages
+       LATT_UNMARKED   this mailbox does not have any recent messages
+
+
+void mm_lsub (MAILSTREAM *stream,char delim,char *name,long attrib);
+       stream  stream where event happened
+       delim   hierarchy delimiter
+       name    mailbox name
+       attrib  mailbox attributes
+
+
+     This function is called to notify the main program that this
+mailbox name matches a subscribed mailbox listing request (generally
+as the result of a mail_lsub() function call).  The hierarchy
+delimiter is a character that separates out levels of hierarchy in
+mailbox names.  The attributes are a bit mask with one of the
+following:
+       LATT_NOINFERIORS
+                       it is not possible for there to be any
+                        hierarchy inferiors to this name (that is,
+                        this name followed by the hierarchy delimiter
+                        and additional name characters).
+       LATT_NOSELECT   this is not a mailbox name, just a hierarchy
+                        level, and it may not be opened by mail_open()
+       LATT_MARKED     this mailbox may have recent messages
+       LATT_UNMARKED   this mailbox does not have any recent messages
+
+
+void mm_notify (MAILSTREAM *stream,char *string,long errflg);
+       stream  stream where event happened
+       string  message string
+       errflg  message error level
+
+     This function is called to deliver a stream-oriented message
+event.  This is the mechanism by which any IMAP response codes for any
+application (e.g. TRYCREATE) are delivered to the application.
+No newline is included in the string, so this function has to output
+its own.
+
+     The message error level is one of the following:
+
+       NIL     normal operation.  The text is `babble' that may be
+               interesting to the user, e.g. the greeting message
+               from a server.
+
+       WARN    A warning event.  This event should be displayed to
+               the user.  Examples: a mailbox rewrite failed because
+               of disk full, but the previous mailbox contents were
+               recovered.
+
+       ERROR   An error event.  This event should be displayed to
+               the user, or at least logged someplace.  This type of
+               error shouldn't happen, and so should be called to the
+               attention of support staff.  Whatever happened has
+               probably disrupted the user's work.  Examples: an
+               untagged BAD from an IMAP server.
+
+
+void mm_log (char *string,long errflg);
+       string  message string
+       errflg  message error level
+
+      This function is called to deliver a log message.  No newline is
+included in the string, so this function has to output its own.  In
+general, it is intended that these messages are logged someplace, and
+possibly shown to the user.
+
+     The message error level is one of the following:
+
+       NIL     normal operation.  The text is `babble' that may be
+               interesting to the user, e.g. "Expunged 3 messages".
+
+       PARSE   An RFC 822 parsing error.  Since bogus headers are
+               all-too-common in the real world, these can often be
+               ignored on the "garbage in, garbage out" princple.
+               However, since surprising results can be yielded when
+               trying to parse garbage, this message should be logged
+               somewhere so it can be figured out what happened.
+
+       WARN    A warning event.  This event should be displayed to
+               the user.  It occurs when an error condition has
+               happened, but c-client knows what to do to recover.
+               Examples: "Can't open read-write, so opening
+               read-only", "Empty mailbox", "Login failed, try
+               again", "Waiting for mailbox to become unlocked",
+               "IMAP protocol error".  Although a user should be
+               told about a warning, it's generally not necessary
+               to interrupt the flow of her work (e.g. it's alright
+               to display the warning in a scrolling window, but
+               not necessary to require the user to do anything).
+
+       ERROR   An error event.  This event should be displayed to
+               the user, or at least logged someplace.  This is a
+               serious error condition occured that aborted the
+               requested operation and possibly also aborted the mail
+               stream.  This ranges from normal error conditions such
+               as "Can't open mailbox", "too many login failures, go
+               away" to bizarre conditions such as "Apparent new mail
+               appeared in the mailbox that doesn't look like mail,
+               program aborting".  Errors must be called to the
+               user's attention, and probably should require some
+               sort of acknowledgement (e.g. answering a modal panel)
+               before the application proceeds.
+
+
+void mm_dlog (char *string);
+       string message string
+
+      This function is called to deliver a debugging telemetry
+message.  No newline is included in the string, so this function has
+to output its own.  This is called only when debugging is enabled.
+
+
+void mm_login (NETMBX *mb,char *user,char *pwd,long trial);
+       mb      parsed mailbox specification
+       user    pointer to where to return user name
+       pwd     pointer to where to return password
+       trial   number of prior login attempts
+
+      This function is called to get a user name and password for the
+given network mailbox.  It stores the user name and password in the
+strings pointed to by the appropriate arguments.  The trial argument
+is the number of attempts to perform the login and is initially zero
+(e.g. for a default username and password login functionality).  It is
+incremented for each subsequent trial until the maximum number of
+trials are made.
+
+
+void mm_critical (MAILSTREAM *stream);
+       stream  stream where event happened
+
+      This function is called to alert the application that c-client
+is about to run some critical code on that stream that may result in a
+clobbered mail file if it is interrupted.  It may be desirable to
+disable CTRL/C, etc. during this time.
+
+
+void mm_nocritical (MAILSTREAM *stream);
+       stream  stream where event happened
+
+      This function is called to alert the application that c-client
+is no longer running critical code on that stream that may result in a
+clobbered mail file if it is interrupted.
+
+
+long mm_diskerror (MAILSTREAM *stream,long errcode,long serious);
+       stream  stream where event happened
+       errcode OS error code for disk error
+       serious non-zero if c-client can not undo the operation (and
+                thus must retry to avoid mail file damage)
+
+      This function is called to alert the application that the
+c-client has encountered an unrecoverable write error when trying to
+update the mail file.  errcode contains the system error code.  If
+serious is non-zero, then it is probable that the disk copy of the
+mailbox has been damaged.
+
+     The return value from this function is the abort flag; if serious
+is zero and the abort flag is non-zero, the operation is aborted.  If
+the abort flag is zero or if serious was non-zero, a return from this
+function will retry the failing operation.
+
+
+void mm_fatal (char *string);
+       string  message string
+
+      This function is called from the fatal() routine in the
+operating system code to notify the main program that it is about to
+crash.  The string contains a reason.  At the very minimum, the main
+program should do something like
+ mm_log (string,ERROR);
+and then return.  No newline is included in the string, so this
+function has to output its own.
+\f
+                            Driver interface
+
+     When writing a new driver for the c-client, you must provide a
+DRIVER stucture giving a dispatch vector between MAIL and the driver.
+The DRIVER dispatch vector is described in mail.h.
+
+char *name;
+     Name by which the driver is known to c-client.
+
+unsigned long flags;
+     Attribute flags for this driver:
+       DR_DISABLE      This driver is currently disabled.
+       DR_LOCAL        This driver deals with local mailboxes; if
+                        this is off it deals with mailboxes over a
+                        network.
+       DR_MAIL         This driver supports e-mail messages.
+       DR_NEWS         This driver supports netnews messages
+       DR_READONLY     This driver only allows read-only access;
+                        mail_setflag(), mail_expunge(), etc. are
+                        no-ops.
+       DR_NOFAST       This driver does not implement mail_fetchfast()
+                        in a fast way (e.g. it may have to fetch the
+                        entire message text over a network to
+                        calculate sizes).
+       DR_NAMESPACE    This driver accepts and uses namespace format
+                        names.
+       DR_LOWMEM       This driver is designed for systems with very
+                        limited amounts of memory (e.g. DOS) and
+                        support routines called by this driver should
+                        try not to use much memory.
+
+DRIVER *next;
+     Pointer to the next driver which this application supports (or NIL if
+this is the last driver).  Drivers are lunk together via the mail_link()
+function.
+
+DRIVER *driver_valid (char *mailbox);
+     This function returns a pointer to the driver's DRIVER dispatch
+vector iff this driver accepts the given name as a valid mailbox for this
+driver.  Otherwise, it returns the value of the next driver's
+driver_valid() or NIL if there is no next driver.  In other words, calling
+driver_valid() for the first driver will return the driver dispatch vector
+for the driver which supports this type of mailbox.
+
+void *driver_parameters (long function,void *value);
+     This function implements mail_parameters() for this driver.
+
+void driver_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
+     This function implements mail_scan() for this driver.
+
+void driver_list (MAILSTREAM *stream,char *ref,char *pat);
+     This function implements mail_list() for this driver.
+
+void driver_lsub (MAILSTREAM *stream,char *ref,char *pat);
+     This function implements mail_lsub() for this driver.
+
+long driver_subscribe (MAILSTREAM *stream,char *mailbox);
+     This function implements mail_subscribe() for this driver.
+
+long driver_unsubscribe (MAILSTREAM *stream,char *mailbox);
+     This function implements mail_unsubscribe() for this driver.
+
+long driver_create (MAILSTREAM *stream,char *mailbox);
+     This function implements mail_create() for this driver.
+
+long driver_delete (MAILSTREAM *stream,char *mailbox);
+     This function implements mail_delete() for this driver.
+
+long driver_rename (MAILSTREAM *stream,char *old,char *new);
+     This function implements mail_rename() for this driver.
+
+long driver_status (MAILSTREAM *stream,char *mailbox,long flags);
+     This function implements mail_status() for this driver.
+
+MAILSTREAM *driver_open (MAILSTREAM *stream);
+     This function opens the mailbox identified by the given stream.  It
+may use the data on the stream and create additional data on stream->local
+as necessary.  It should return the given stream unless it failed to open
+the mailbox, in which case it should return NIL.
+
+void driver_close (MAILSTREAM *stream,long options);
+     This function implements mail_close() for this driver.
+
+void driver_fetchfast (MAILSTREAM *stream,char *sequence,long flags);
+     This function implements mail_fetchfast() for this driver.
+
+void driver_fetchflags (MAILSTREAM *stream,char *sequence,long flags);
+     This function implements mail_fetchflags() for this driver.
+
+ENVELOPE *driver_fetchstructure (MAILSTREAM *stream,unsigned long msgno,
+                                BODY **body,long flags);
+     This function implements mail_fetchstructure() for this driver.
+
+char *driver_fetchheader (MAILSTREAM *stream,unsigned long msgno,
+                         STRINGLIST *lines,unsigned long *len,long flags);
+     This function implements mail_fetchheader() for this driver.
+
+char *driver_fetchtext (MAILSTREAM *stream,unsigned long msgno,
+                       unsigned long *len,long flags);
+     This function implements mail_fetchtext() for this driver.
+
+char *driver_fetchbody (MAILSTREAM *stream,unsigned long msgno,char *section,
+                       unsigned long *len,long flags);
+     This function implements mail_fetchbody() for this driver.
+
+void driver_setflag (MAILSTREAM *stream,char *sequence,char *flag,long flags);
+     This function implements mail_setflag() for this driver.
+
+void driver_clearflag (MAILSTREAM *stream,char *sequence,char *flag,
+                      long flags);
+     This function implements mail_clearflag() for this driver.
+
+void driver_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,
+                   long flags);
+     This function implements mail_search() for this driver.
+
+unsigned long *driver_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg,
+                           SORTPGM *pgm,long flags);
+     This function implements mail_sort() for this driver.
+
+void *driver_thread (MAILSTREAM *stream,char *seq,long function,long flag);
+     This dispatch is reserved for a future threading capability.
+
+long driver_ping (MAILSTREAM *stream);
+      This function implements mail_ping() for this driver.
+
+void driver_check (MAILSTREAM *stream);
+      This function implements mail_check() for this driver.
+
+void driver_expunge (MAILSTREAM *stream);
+      This function implements mail_expunge() for this driver.
+
+long driver_copy (MAILSTREAM *stream,char *sequence,char *mailbox,
+                 long options);
+      This function implements mail_copy() for this driver.
+
+long driver_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
+                   STRING *message);
+      This function implements mail_append() for this driver.
+
+void driver_gc (MAILSTREAM *stream,long gcflags);
+      This function implements mail_gc() for this driver.
+\f
+                        Driver Support Functions
+
+void mail_searched (MAILSTREAM *stream,unsigned long msgno);
+       stream  stream where event happened
+       msgno   message number
+
+     This function is called by the driver to notify c-client that this
+message number matches a search.  It invokes the main program's
+mm_searched() function.
+
+void mail_exists (MAILSTREAM *stream,unsigned long nmsgs);
+       stream  stream where event happened
+       nmsgs   number of messages
+
+     This function is called by the driver to notify c-client that this
+message number exists (i.e. there are this many messages in the mailbox).
+It invokes the main program's mm_exists() function.
+
+void mail_recent (MAILSTREAM *stream,unsigned long recent);
+       stream  stream where event happened
+       recent  number of messages
+
+      This function is called by the driver to notify c-client that this
+many messages are "recent" (i.e. arrived in the mailbox since the previous
+time the mailbox was opened).
+
+void mail_expunged (MAILSTREAM *stream,unsigned long msgno);
+       stream  stream where event happened
+       msgno   number of messages
+
+      This function is called by the driver to notify MAIL 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.  It
+invokes the main program's mm_expunged() function.
+
+void mail_lock (MAILSTREAM *stream);
+       stream  stream where event happened
+      This function sets the stream lock.  It is an error to set the stream
+lock if the stream is already locked.
+
+      This is mainly used to catch errors due to a callback function
+(e.g. mm_exists) inadvertantly recursing back to the MAIL routines and
+establishing an infinite recursion.  Normally, drivers will set the lock
+prior to calling one of the callback functions above or, more likely, in
+the beginning of the driver's non-reentrant "do operation" section.  In the
+IMAP4 driver, the stream lock is set when entering imap_send() and cleared
+on exit.
+
+void mail_unlock (MAILSTREAM *stream);
+       stream  stream where event happened
+
+     This function releases the stream lock.  It is an error to release the
+stream lock if the stream is not locked.