home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / imap / src / osdep / amiga / mmdf.h < prev    next >
Text File  |  1998-10-22  |  11KB  |  268 lines

  1. /*
  2.  * Program:    MMDF mail routines
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    15 May 1993
  13.  * Last Edited:    22 October 1998
  14.  *
  15.  * Copyright 1998 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35.  
  36. /* Supposedly, this page has everything the MMDF driver needs to know about
  37.  * the MMDF delimiter.  By changing these macros, the MMDF driver should
  38.  * change with it.  Note that if you change the length of MMDFHDRTXT you
  39.  * also need to change the ISMMDF and RETIFMMDFWRD macros to reflect the new
  40.  * size.
  41.  */
  42.  
  43.  
  44. /* Useful MMDF constants */
  45.  
  46. #define MMDFCHR '\01'        /* MMDF character */
  47. #define MMDFCHRS 0x01010101    /* MMDF header character spread in a word */
  48.                 /* MMDF header text */
  49. #define MMDFHDRTXT "\01\01\01\01\n"
  50.                 /* length of MMDF header text */
  51. #define MMDFHDRLEN (sizeof (MMDFHDRTXT) - 1)
  52.  
  53.  
  54. /* Validate MMDF header
  55.  * Accepts: pointer to candidate string to validate as an MMDF header
  56.  * Returns: T if valid; else NIL
  57.  */
  58.  
  59. #define ISMMDF(s)                            \
  60.   ((*(s) == MMDFCHR) && ((s)[1] == MMDFCHR) && ((s)[2] == MMDFCHR) &&    \
  61.    ((s)[3] == MMDFCHR) && ((s)[4] == '\n'))
  62.  
  63.  
  64. /* Return if a 32-bit word has the start of an MMDF header
  65.  * Accepts: pointer to word of four bytes to validate as an MMDF header
  66.  * Returns: pointer to MMDF header, else proceeds
  67.  */
  68.  
  69. #define RETIFMMDFWRD(s) {                        \
  70.   if (s[3] == MMDFCHR) {                        \
  71.     if ((s[4] == MMDFCHR) && (s[5] == MMDFCHR) && (s[6] == MMDFCHR) &&    \
  72.     (s[7] == '\n')) return s + 3;                    \
  73.     else if (s[2] == MMDFCHR) {                        \
  74.       if ((s[4] == MMDFCHR) && (s[5] == MMDFCHR) && (s[6] == '\n'))    \
  75.     return s + 2;                            \
  76.       else if (s[1] == MMDFCHR) {                    \
  77.     if ((s[4] == MMDFCHR) && (s[5] == '\n')) return s + 1;        \
  78.     else if ((*s == MMDFCHR) && (s[4] == '\n')) return s;        \
  79.       }                                    \
  80.     }                                    \
  81.   }                                    \
  82. }
  83.  
  84. /* Validate line
  85.  * Accepts: pointer to candidate string to validate as a From header
  86.  *        return pointer to end of date/time field
  87.  *        return pointer to offset from t of time (hours of ``mmm dd hh:mm'')
  88.  *        return pointer to offset from t of time zone (if non-zero)
  89.  * Returns: t,ti,zn set if valid From string, else ti is NIL
  90.  */
  91.  
  92. #define VALID(s,x,ti,zn) {                        \
  93.   ti = 0;                                \
  94.   if ((*s == 'F') && (s[1] == 'r') && (s[2] == 'o') && (s[3] == 'm') &&    \
  95.       (s[4] == ' ')) {                            \
  96.     for (x = s + 5; *x && *x != '\n'; x++);                \
  97.     if (*x) {                                \
  98.       if (x - s >= 41) {                        \
  99.     for (zn = -1; x[zn] != ' '; zn--);                \
  100.     if ((x[zn-1] == 'm') && (x[zn-2] == 'o') && (x[zn-3] == 'r') &&    \
  101.         (x[zn-4] == 'f') && (x[zn-5] == ' ') && (x[zn-6] == 'e') &&    \
  102.         (x[zn-7] == 't') && (x[zn-8] == 'o') && (x[zn-9] == 'm') &&    \
  103.         (x[zn-10] == 'e') && (x[zn-11] == 'r') && (x[zn-12] == ' '))\
  104.       x += zn - 12;                            \
  105.       }                                    \
  106.       if (x - s >= 27) {                        \
  107.     if (x[-5] == ' ') {                        \
  108.       if (x[-8] == ':') zn = 0,ti = -5;                \
  109.       else if (x[-9] == ' ') ti = zn = -9;                \
  110.       else if ((x[-11] == ' ') && ((x[-10]=='+') || (x[-10]=='-')))    \
  111.         ti = zn = -11;                        \
  112.     }                                \
  113.     else if (x[-4] == ' ') {                    \
  114.       if (x[-9] == ' ') zn = -4,ti = -9;                \
  115.     }                                \
  116.     else if (x[-6] == ' ') {                    \
  117.       if ((x[-11] == ' ') && ((x[-5] == '+') || (x[-5] == '-')))    \
  118.         zn = -6,ti = -11;                        \
  119.     }                                \
  120.     if (ti && !((x[ti - 3] == ':') &&                \
  121.             (x[ti -= ((x[ti - 6] == ':') ? 9 : 6)] == ' ') &&    \
  122.             (x[ti - 3] == ' ') && (x[ti - 7] == ' ') &&        \
  123.             (x[ti - 11] == ' '))) ti = 0;            \
  124.       }                                    \
  125.     }                                    \
  126.   }                                    \
  127. }
  128.  
  129. /* You are not expected to understand this macro, but read the next page if
  130.  * you are not faint of heart.
  131.  *
  132.  * Known formats to the VALID macro are:
  133.  *        From user Wed Dec  2 05:53 1992
  134.  * BSD        From user Wed Dec  2 05:53:22 1992
  135.  * SysV        From user Wed Dec  2 05:53 PST 1992
  136.  * rn        From user Wed Dec  2 05:53:22 PST 1992
  137.  *        From user Wed Dec  2 05:53 -0700 1992
  138.  * emacs    From user Wed Dec  2 05:53:22 -0700 1992
  139.  *        From user Wed Dec  2 05:53 1992 PST
  140.  *        From user Wed Dec  2 05:53:22 1992 PST
  141.  *        From user Wed Dec  2 05:53 1992 -0700
  142.  * Solaris    From user Wed Dec  2 05:53:22 1992 -0700
  143.  *
  144.  * Plus all of the above with `` remote from xxx'' after it. Thank you very
  145.  * much, smail and Solaris, for making my life considerably more complicated.
  146.  */
  147.  
  148. /*
  149.  * What?  You want to understand the VALID macro anyway?  Alright, since you
  150.  * insist.  Actually, it isn't really all that difficult, provided that you
  151.  * take it step by step.
  152.  *
  153.  * Line 1    Initializes the return ti value to failure (0);
  154.  * Lines 2-3    Validates that the 1st-5th characters are ``From ''.
  155.  * Lines 4-5    Validates that there is an end of line and points x at it.
  156.  * Lines 6-13    First checks to see if the line is at least 41 characters long.
  157.  *        If so, it scans backwards to find the rightmost space.  From
  158.  *        that point, it scans backwards to see if the string matches
  159.  *        `` remote from''.  If so, it sets x to point to the space at
  160.  *        the start of the string.
  161.  * Line 14    Makes sure that there are at least 27 characters in the line.
  162.  * Lines 15-20    Checks if the date/time ends with the year (there is a space
  163.  *        five characters back).  If there is a colon three characters
  164.  *        further back, there is no timezone field, so zn is set to 0
  165.  *        and ti is set in front of the year.  Otherwise, there must
  166.  *        either to be a space four characters back for a three-letter
  167.  *        timezone, or a space six characters back followed by a + or -
  168.  *        for a numeric timezone; in either case, zn and ti become the
  169.  *        offset of the space immediately before it.
  170.  * Lines 21-23    Are the failure case for line 14.  If there is a space four
  171.  *        characters back, it is a three-letter timezone; there must be a
  172.  *        space for the year nine characters back.  zn is the zone
  173.  *        offset; ti is the offset of the space.
  174.  * Lines 24-27    Are the failure case for line 20.  If there is a space six
  175.  *        characters back, it is a numeric timezone; there must be a
  176.  *        space eleven characters back and a + or - five characters back.
  177.  *        zn is the zone offset; ti is the offset of the space.
  178.  * Line 28-31    If ti is valid, make sure that the string before ti is of the
  179.  *        form www mmm dd hh:mm or www mmm dd hh:mm:ss, otherwise
  180.  *        invalidate ti.  There must be a colon three characters back
  181.  *        and a space six or nine    characters back (depending upon
  182.  *        whether or not the character six characters back is a colon).
  183.  *        There must be a space three characters further back (in front
  184.  *        of the day), one seven characters back (in front of the month),
  185.  *        and one eleven characters back (in front of the day of week).
  186.  *        ti is set to be the offset of the space before the time.
  187.  *
  188.  * Why a macro?  It gets invoked a *lot* in a tight loop.  On some of the
  189.  * newer pipelined machines it is faster being open-coded than it would be if
  190.  * subroutines are called.
  191.  *
  192.  * Why does it scan backwards from the end of the line, instead of doing the
  193.  * much easier forward scan?  There is no deterministic way to parse the
  194.  * ``user'' field, because it may contain unquoted spaces!  Yes, I tested it to
  195.  * see if unquoted spaces were possible.  They are, and I've encountered enough
  196.  * evil mail to be totally unwilling to trust that ``it will never happen''.
  197.  */
  198.  
  199. /* Build parameters */
  200.  
  201. #define KODRETRY 15        /* kiss-of-death retry in seconds */
  202. #define LOCKTIMEOUT 5        /* lock timeout in minutes */
  203. #define CHUNK 16384        /* read-in chunk size */
  204.  
  205.  
  206. /* MMDF I/O stream local data */
  207.  
  208. typedef struct mmdf_local {
  209.   unsigned int dirty : 1;    /* disk copy needs updating */
  210.   int fd;            /* mailbox file descriptor */
  211.   int ld;            /* lock file descriptor */
  212.   char *name;            /* local file name for recycle case */
  213.   char *lname;            /* lock file name */
  214.   off_t filesize;        /* file size parsed */
  215.   time_t filetime;        /* last file time */
  216.   char *buf;            /* temporary buffer */
  217.   unsigned long buflen;        /* current size of temporary buffer */
  218.   char *line;            /* returned line */
  219. } MMDFLOCAL;
  220.  
  221.  
  222. /* Convenient access to local data */
  223.  
  224. #define LOCAL ((MMDFLOCAL *) stream->local)
  225.  
  226. /* Function prototypes */
  227.  
  228. DRIVER *mmdf_valid (char *name);
  229. long mmdf_isvalid (char *name,char *tmp);
  230. long mmdf_isvalid_fd (int fd,char *tmp);
  231. void *mmdf_parameters (long function,void *value);
  232. void mmdf_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);
  233. void mmdf_list (MAILSTREAM *stream,char *ref,char *pat);
  234. void mmdf_lsub (MAILSTREAM *stream,char *ref,char *pat);
  235. long mmdf_create (MAILSTREAM *stream,char *mailbox);
  236. long mmdf_delete (MAILSTREAM *stream,char *mailbox);
  237. long mmdf_rename (MAILSTREAM *stream,char *old,char *newname);
  238. MAILSTREAM *mmdf_open (MAILSTREAM *stream);
  239. void mmdf_close (MAILSTREAM *stream,long options);
  240. char *mmdf_header (MAILSTREAM *stream,unsigned long msgno,
  241.            unsigned long *length,long flags);
  242. long mmdf_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
  243. char *mmdf_text_work (MAILSTREAM *stream,MESSAGECACHE *elt,
  244.               unsigned long *length,long flags);
  245. void mmdf_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);
  246. long mmdf_ping (MAILSTREAM *stream);
  247. void mmdf_check (MAILSTREAM *stream);
  248. void mmdf_check (MAILSTREAM *stream);
  249. void mmdf_expunge (MAILSTREAM *stream);
  250. long mmdf_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
  251. long mmdf_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
  252.           STRING *message);
  253.  
  254. void mmdf_abort (MAILSTREAM *stream);
  255. char *mmdf_file (char *dst,char *name);
  256. int mmdf_lock (char *file,int flags,int mode,char *lock,int op);
  257. void mmdf_unlock (int fd,MAILSTREAM *stream,char *lock);
  258. int mmdf_parse (MAILSTREAM *stream,char *lock,int op);
  259. char *mmdf_mbxline (MAILSTREAM *stream,STRING *bs,unsigned long *size);
  260. unsigned long mmdf_pseudo (MAILSTREAM *stream,char *hdr);
  261. unsigned long mmdf_xstatus (MAILSTREAM *stream,char *status,MESSAGECACHE *elt,
  262.                 long flag);
  263. long mmdf_rewrite (MAILSTREAM *stream,unsigned long *nexp);
  264. long mmdf_write_message (FILE *f,MAILSTREAM *stream,MESSAGECACHE *elt,
  265.              unsigned long *size);
  266. long mmdf_fwrite (FILE *f,char *s,unsigned long i,unsigned long *size);
  267. long mmdf_punt_scratch (FILE *f);
  268.