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 / phile.c < prev    next >
C/C++ Source or Header  |  1998-09-16  |  15KB  |  515 lines

  1. /*
  2.  * Program:    File 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:    25 August 1993
  13.  * Last Edited:    29 July 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. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <errno.h>
  39. extern int errno;        /* just in case */
  40. #include <signal.h>
  41. #include "mail.h"
  42. #include "osdep.h"
  43. #include <pwd.h>
  44. #include <sys/stat.h>
  45. #include <sys/time.h>
  46. #include "phile.h"
  47. #include "rfc822.h"
  48. #include "misc.h"
  49. #include "dummy.h"
  50.  
  51. /* File routines */
  52.  
  53.  
  54. /* Driver dispatch used by MAIL */
  55.  
  56. DRIVER philedriver = {
  57.   "phile",            /* driver name */
  58.                 /* driver flags */
  59.   DR_LOCAL|DR_READONLY|DR_NOSTICKY,
  60.   (DRIVER *) NIL,        /* next driver */
  61.   phile_valid,            /* mailbox is valid for us */
  62.   phile_parameters,        /* manipulate parameters */
  63.   phile_scan,            /* scan mailboxes */
  64.   phile_list,            /* list mailboxes */
  65.   phile_lsub,            /* list subscribed mailboxes */
  66.   NIL,                /* subscribe to mailbox */
  67.   NIL,                /* unsubscribe from mailbox */
  68.   phile_create,            /* create mailbox */
  69.   phile_delete,            /* delete mailbox */
  70.   phile_rename,            /* rename mailbox */
  71.   NIL,                /* status of mailbox */
  72.   phile_open,            /* open mailbox */
  73.   phile_close,            /* close mailbox */
  74.   NIL,                /* fetch message "fast" attributes */
  75.   NIL,                /* fetch message flags */
  76.   NIL,                /* fetch overview */
  77.   phile_structure,        /* fetch message envelopes */
  78.   phile_header,            /* fetch message header only */
  79.   phile_text,            /* fetch message body only */
  80.   NIL,                /* fetch partial message text */
  81.   NIL,                /* unique identifier */
  82.   NIL,                /* message number */
  83.   NIL,                /* modify flags */
  84.   NIL,                /* per-message modify flags */
  85.   NIL,                /* search for message based on criteria */
  86.   NIL,                /* sort messages */
  87.   NIL,                /* thread messages */
  88.   phile_ping,            /* ping mailbox to see if still alive */
  89.   phile_check,            /* check for new messages */
  90.   phile_expunge,        /* expunge deleted messages */
  91.   phile_copy,            /* copy messages to another mailbox */
  92.   phile_append,            /* append string message to mailbox */
  93.   NIL                /* garbage collect stream */
  94. };
  95.  
  96.                 /* prototype stream */
  97. MAILSTREAM phileproto = {&philedriver};
  98.  
  99. /* File validate mailbox
  100.  * Accepts: mailbox name
  101.  * Returns: our driver if name is valid, NIL otherwise
  102.  */
  103.  
  104. DRIVER *phile_valid (char *name)
  105. {
  106.   char tmp[MAILTMPLEN];
  107.   return phile_isvalid (name,tmp) ? &philedriver : NIL;
  108. }
  109.  
  110.  
  111. /* File test for valid mailbox
  112.  * Accepts: mailbox name
  113.  * Returns: T if valid, NIL otherwise
  114.  */
  115.  
  116. int phile_isvalid (char *name,char *tmp)
  117. {
  118.   struct stat sbuf;
  119.   char *s;
  120.                 /* INBOX never accepted, any other name is */
  121.   return ((s = mailboxfile (tmp,name)) && *s && !stat (s,&sbuf) &&
  122.       !(sbuf.st_mode & S_IFDIR) &&
  123.                 /* only allow empty files if #ftp */
  124.       (sbuf.st_size || ((*name == '#') &&
  125.                 ((name[1] == 'f') || (name[1] == 'F')) &&
  126.                 ((name[2] == 't') || (name[2] == 'T')) &&
  127.                 ((name[3] == 'p') || (name[3] == 'P')) &&
  128.                 (name[4] == '/'))));
  129. }
  130.  
  131. /* File manipulate driver parameters
  132.  * Accepts: function code
  133.  *        function-dependent value
  134.  * Returns: function-dependent return value
  135.  */
  136.  
  137. void *phile_parameters (long function,void *value)
  138. {
  139.   return NIL;
  140. }
  141.  
  142. /* File mail scan mailboxes
  143.  * Accepts: mail stream
  144.  *        reference
  145.  *        pattern to search
  146.  *        string to scan
  147.  */
  148.  
  149. void phile_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
  150. {
  151.   if (stream) dummy_scan (NIL,ref,pat,contents);
  152. }
  153.  
  154.  
  155. /* File list mailboxes
  156.  * Accepts: mail stream
  157.  *        reference
  158.  *        pattern to search
  159.  */
  160.  
  161. void phile_list (MAILSTREAM *stream,char *ref,char *pat)
  162. {
  163.   if (stream) dummy_list (NIL,ref,pat);
  164. }
  165.  
  166.  
  167. /* File list subscribed mailboxes
  168.  * Accepts: mail stream
  169.  *        reference
  170.  *        pattern to search
  171.  */
  172.  
  173. void phile_lsub (MAILSTREAM *stream,char *ref,char *pat)
  174. {
  175.   if (stream) dummy_lsub (NIL,ref,pat);
  176. }
  177.  
  178. /* File create mailbox
  179.  * Accepts: MAIL stream
  180.  *        mailbox name to create
  181.  * Returns: T on success, NIL on failure
  182.  */
  183.  
  184. long phile_create (MAILSTREAM *stream,char *mailbox)
  185. {
  186.   return dummy_create (stream,mailbox);
  187. }
  188.  
  189.  
  190. /* File delete mailbox
  191.  * Accepts: MAIL stream
  192.  *        mailbox name to delete
  193.  * Returns: T on success, NIL on failure
  194.  */
  195.  
  196. long phile_delete (MAILSTREAM *stream,char *mailbox)
  197. {
  198.   return dummy_delete (stream,mailbox);
  199. }
  200.  
  201.  
  202. /* File rename mailbox
  203.  * Accepts: MAIL stream
  204.  *        old mailbox name
  205.  *        new mailbox name (or NIL for delete)
  206.  * Returns: T on success, NIL on failure
  207.  */
  208.  
  209. long phile_rename (MAILSTREAM *stream,char *old,char *newname)
  210. {
  211.   return dummy_rename (stream,old,newname);
  212. }
  213.  
  214. /* File open
  215.  * Accepts: Stream to open
  216.  * Returns: Stream on success, NIL on failure
  217.  */
  218.  
  219. MAILSTREAM *phile_open (MAILSTREAM *stream)
  220. {
  221.   int i,k,fd;
  222.   unsigned long j,m;
  223.   char *s,tmp[MAILTMPLEN];
  224.   struct passwd *pw;
  225.   struct stat sbuf;
  226.   struct tm *t;
  227.   MESSAGECACHE *elt;
  228.   SIZEDTEXT *buf;
  229.                 /* return prototype for OP_PROTOTYPE call */
  230.   if (!stream) return &phileproto;
  231.   if (stream->local) fatal ("phile recycle stream");
  232.                 /* canonicalize the stream mailbox name */
  233.   mailboxfile (tmp,stream->mailbox);
  234.   fs_give ((void **) &stream->mailbox);
  235.   stream->mailbox = cpystr (tmp);
  236.                 /* open mailbox */
  237.   if (stat (tmp,&sbuf) || (fd = open (tmp,O_RDONLY,NIL)) < 0) {
  238.     sprintf (tmp,"Unable to open file %s",stream->mailbox);
  239.     mm_log (tmp,ERROR);
  240.     return NIL;
  241.   }
  242.   stream->local = fs_get (sizeof (PHILELOCAL));
  243.   mail_exists (stream,1);    /* make sure upper level knows */
  244.   mail_recent (stream,1);
  245.   elt = mail_elt (stream,1);    /* instantiate cache element */
  246.   elt->valid = elt->recent = T;    /* mark valid flags */
  247.   stream->sequence++;        /* bump sequence number */
  248.   stream->rdonly = T;        /* make sure upper level knows readonly */
  249.                 /* instantiate a new envelope and body */
  250.   LOCAL->env = mail_newenvelope ();
  251.   LOCAL->body = mail_newbody ();
  252.  
  253.   t = gmtime (&sbuf.st_mtime);    /* get UTC time and Julian day */
  254.   i = t->tm_hour * 60 + t->tm_min;
  255.   k = t->tm_yday;
  256.   t = localtime(&sbuf.st_mtime);/* get local time */
  257.                 /* calculate time delta */
  258.   i = t->tm_hour * 60 + t->tm_min - i;
  259.   if (k = t->tm_yday - k) i += ((k < 0) == (abs (k) == 1)) ? -24*60 : 24*60;
  260.   k = abs (i);            /* time from UTC either way */
  261.   elt->hours = t->tm_hour; elt->minutes = t->tm_min; elt->seconds = t->tm_sec;
  262.   elt->day = t->tm_mday; elt->month = t->tm_mon + 1;
  263.   elt->year = t->tm_year - (BASEYEAR - 1900);
  264.   elt->zoccident = (k == i) ? 0 : 1;
  265.   elt->zhours = k/60;
  266.   elt->zminutes = k % 60;
  267.   sprintf (tmp,"%s, %d %s %d %02d:%02d:%02d %c%02d%02d",
  268.        days[t->tm_wday],t->tm_mday,months[t->tm_mon],t->tm_year+1900,
  269.        t->tm_hour,t->tm_min,t->tm_sec,elt->zoccident ? '-' : '+',
  270.        elt->zhours,elt->zminutes);
  271.                 /* set up Date field */
  272.   LOCAL->env->date = cpystr (tmp);
  273.  
  274.                 /* fill in From field from file owner */
  275.   LOCAL->env->from = mail_newaddr ();
  276.   if (pw = getpwuid (sbuf.st_uid)) strcpy (tmp,pw->pw_name);
  277.   else sprintf (tmp,"User-Number-%ld",(long) sbuf.st_uid);
  278.   LOCAL->env->from->mailbox = cpystr (tmp);
  279.   LOCAL->env->from->host = cpystr (mylocalhost ());
  280.                 /* set subject to be mailbox name */
  281.   LOCAL->env->subject = cpystr (stream->mailbox);
  282.                 /* slurp the data */
  283.   (buf = &elt->private.special.text)->size = sbuf.st_size;
  284.   read (fd,buf->data = (unsigned char *) fs_get (buf->size + 1),buf->size);
  285.   buf->data[buf->size] = '\0';
  286.   close (fd);            /* close the file */
  287.                 /* analyze data type */
  288.   if (i = phile_type (buf->data,buf->size,&j)) {
  289.     LOCAL->body->type = TYPETEXT;
  290.     LOCAL->body->subtype = cpystr ("PLAIN");
  291.     if (!(i & PTYPECRTEXT)) {    /* change Internet newline format as needed */
  292.       s = (char *) buf->data;    /* make copy of UNIX-format string */
  293.       buf->data = NIL;        /* zap the buffer */
  294.       buf->size = strcrlfcpy ((char **) &buf->data,&m,s,buf->size);
  295.       fs_give ((void **) &s);    /* flush original UNIX-format string */
  296.     }
  297.     LOCAL->body->parameter = mail_newbody_parameter ();
  298.     LOCAL->body->parameter->attribute = cpystr ("charset");
  299.     LOCAL->body->parameter->value =
  300.       cpystr ((i & PTYPEISO2022JP) ? "ISO-2022-JP" :
  301.           (i & PTYPEISO2022KR) ? "ISO-2022-KR" :
  302.           (i & PTYPEISO2022CN) ? "ISO-2022-CN" :
  303.           (i & PTYPE8) ? "ISO-8859-1" : "US-ASCII");
  304.     LOCAL->body->encoding = (i & PTYPE8) ? ENC8BIT : ENC7BIT;
  305.     LOCAL->body->size.lines = j;
  306.   }
  307.   else {            /* binary data */
  308.     LOCAL->body->type = TYPEAPPLICATION;
  309.     LOCAL->body->subtype = cpystr ("OCTET-STREAM");
  310.     LOCAL->body->parameter = mail_newbody_parameter ();
  311.     LOCAL->body->parameter->attribute = cpystr ("name");
  312.     LOCAL->body->parameter->value =
  313.       cpystr ((s = (strrchr (stream->mailbox,'/'))) ? s+1 : stream->mailbox);
  314.     LOCAL->body->encoding = ENCBASE64;
  315.     buf->data = rfc822_binary (s = (char *) buf->data,buf->size,&buf->size);
  316.     fs_give ((void **) &s);    /* flush originary binary contents */
  317.   }
  318.   phile_header (stream,1,&j,NIL);
  319.   LOCAL->body->size.bytes = LOCAL->body->contents.text.size = buf->size;
  320.   elt->rfc822_size = j + buf->size;
  321.                 /* only one message ever... */
  322.   stream->uid_validity = sbuf.st_mtime;
  323.   stream->uid_last = elt->private.uid = 1;
  324.   return stream;        /* return stream alive to caller */
  325. }
  326.  
  327. /* File determine data type
  328.  * Accepts: data to examine
  329.  *        size of data
  330.  *        pointer to line count return
  331.  * Returns: PTYPE mask of data type
  332.  */
  333.  
  334. int phile_type (unsigned char *s,unsigned long i,unsigned long *j)
  335. {
  336.   int ret = PTYPETEXT;
  337.   char *charvec = "bbbbbbbaaalaacaabbbbbbbbbbbebbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
  338.   *j = 0;            /* no lines */
  339.                 /* check type of every character */
  340.   while (i--) switch (charvec[*s++]) {
  341.   case 'A':
  342.     ret |= PTYPE8;        /* 8bit character */
  343.     break;
  344.   case 'a':
  345.     break;            /* ASCII character */
  346.   case 'b':
  347.     return PTYPEBINARY;        /* binary byte seen, stop immediately */
  348.   case 'c':
  349.     ret |= PTYPECRTEXT;        /* CR indicates Internet text */
  350.     break;
  351.   case 'e':            /* ESC */
  352.     if (*s == '$') {        /* ISO-2022 sequence? */
  353.       switch (s[1]) {
  354.       case 'B': case '@': ret |= PTYPEISO2022JP; break;
  355.       case ')':
  356.     switch (s[2]) {
  357.     case 'A': case 'E': case 'G': ret |= PTYPEISO2022CN; break;
  358.     case 'C': ret |= PTYPEISO2022KR; break;
  359.     }
  360.       case '*':
  361.     switch (s[2]) {
  362.     case 'H': ret |= PTYPEISO2022CN; break;
  363.     }
  364.       case '+':
  365.     switch (s[2]) {
  366.     case 'I': case 'J': case 'K': case 'L': case 'M':
  367.       ret |= PTYPEISO2022CN; break;
  368.     }
  369.       }
  370.     }
  371.     break;
  372.   case 'l':            /* newline */
  373.     (*j)++;
  374.     break;
  375.   }
  376.   return ret;            /* return type of data */
  377. }
  378.  
  379. /* File close
  380.  * Accepts: MAIL stream
  381.  *        close options
  382.  */
  383.  
  384. void phile_close (MAILSTREAM *stream,long options)
  385. {
  386.   if (LOCAL) {            /* only if a file is open */
  387.     fs_give ((void **) &mail_elt (stream,1)->private.special.text.data);
  388.                 /* nuke the local data */
  389.     fs_give ((void **) &stream->local);
  390.     stream->dtb = NIL;        /* log out the DTB */
  391.   }
  392. }
  393.  
  394. /* File fetch structure
  395.  * Accepts: MAIL stream
  396.  *        message # to fetch
  397.  *        pointer to return body
  398.  *        option flags
  399.  * Returns: envelope of this message, body returned in body value
  400.  *
  401.  * Fetches the "fast" information as well
  402.  */
  403.  
  404. ENVELOPE *phile_structure (MAILSTREAM *stream,unsigned long msgno,BODY **body,
  405.                long flags)
  406. {
  407.   if (body) *body = LOCAL->body;
  408.   return LOCAL->env;        /* return the envelope */
  409. }
  410.  
  411.  
  412. /* File fetch message header
  413.  * Accepts: MAIL stream
  414.  *        message # to fetch
  415.  *        pointer to returned header text length
  416.  *        option flags
  417.  * Returns: message header in RFC822 format
  418.  */
  419.  
  420. char *phile_header (MAILSTREAM *stream,unsigned long msgno,
  421.             unsigned long *length,long flags)
  422. {
  423.   rfc822_header (LOCAL->tmp,LOCAL->env,LOCAL->body);
  424.   *length = strlen (LOCAL->tmp);
  425.   return LOCAL->tmp;
  426. }
  427.  
  428.  
  429. /* File fetch message text (body only)
  430.  * Accepts: MAIL stream
  431.  *        message # to fetch
  432.  *        pointer to returned stringstruct
  433.  *        option flags
  434.  * Returns: T, always
  435.  */
  436.  
  437. long phile_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags)
  438. {
  439.   SIZEDTEXT *buf = &mail_elt (stream,msgno)->private.special.text;
  440.   if (!(flags &FT_PEEK)) {    /* mark message as seen */
  441.     mail_elt (stream,msgno)->seen = T;
  442.     mm_flags (stream,msgno);
  443.   }
  444.   INIT (bs,mail_string,buf->data,buf->size);
  445.   return T;
  446. }
  447.  
  448. /* File ping mailbox
  449.  * Accepts: MAIL stream
  450.  * Returns: T if stream alive, else NIL
  451.  * No-op for readonly files, since read/writer can expunge it from under us!
  452.  */
  453.  
  454. long phile_ping (MAILSTREAM *stream)
  455. {
  456.   return T;
  457. }
  458.  
  459. /* File check mailbox
  460.  * Accepts: MAIL stream
  461.  * No-op for readonly files, since read/writer can expunge it from under us!
  462.  */
  463.  
  464. void phile_check (MAILSTREAM *stream)
  465. {
  466.   mm_log ("Check completed",NIL);
  467. }
  468.  
  469. /* File expunge mailbox
  470.  * Accepts: MAIL stream
  471.  */
  472.  
  473. void phile_expunge (MAILSTREAM *stream)
  474. {
  475.   mm_log ("Expunge ignored on readonly mailbox",NIL);
  476. }
  477.  
  478. /* File copy message(s)
  479.  * Accepts: MAIL stream
  480.  *        sequence
  481.  *        destination mailbox
  482.  *        copy options
  483.  * Returns: T if copy successful, else NIL
  484.  */
  485.  
  486. long phile_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
  487. {
  488.   char tmp[MAILTMPLEN];
  489.   mailproxycopy_t pc =
  490.     (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);
  491.   if (pc) return (*pc) (stream,sequence,mailbox,options);
  492.   sprintf (tmp,"Can't copy - file \"%s\" is not in valid mailbox format",
  493.        stream->mailbox);
  494.   mm_log (tmp,ERROR);
  495.   return NIL;
  496. }
  497.  
  498.  
  499. /* File append message from stringstruct
  500.  * Accepts: MAIL stream
  501.  *        destination mailbox
  502.  *        stringstruct of messages to append
  503.  * Returns: T if append successful, else NIL
  504.  */
  505.  
  506. long phile_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
  507.            STRING *message)
  508. {
  509.   char tmp[MAILTMPLEN],file[MAILTMPLEN];
  510.   sprintf (tmp,"Can't append - file \"%s\" is not in valid mailbox format",
  511.        mailboxfile (file,mailbox));
  512.   mm_log (tmp,ERROR);
  513.   return NIL;
  514. }
  515.