Annotation of GNUtools/emacs/etc/movemail.c, revision 1.1.1.1

1.1       root        1: /* movemail foo bar -- move file foo to file bar,
                      2:    locking file foo the way /bin/mail respects.
                      3:    Copyright (C) 1986 Free Software Foundation, Inc.
                      4: 
                      5: This file is part of GNU Emacs.
                      6: 
                      7: GNU Emacs is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 1, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU Emacs is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU Emacs; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: /* Important notice: defining MAIL_USE_FLOCK *will cause loss of mail*
                     22:    if you do it on a system that does not normally use flock as its way of
                     23:    interlocking access to inbox files.  The setting of MAIL_USE_FLOCK
                     24:    *must agree* with the system's own conventions.
                     25:    It is not a choice that is up to you.
                     26: 
                     27:    So, if your system uses lock files rather than flock, then the only way
                     28:    you can get proper operation is to enable movemail to write lockfiles there.
                     29:    This means you must either give that directory access modes
                     30:    that permit everyone to write lockfiles in it, or you must make movemail
                     31:    a setuid or setgid program.  */
                     32: 
                     33: /*
                     34:  * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
                     35:  *
                     36:  * Added POP (Post Office Protocol) service.  When compiled -DPOP
                     37:  * movemail will accept input filename arguments of the form
                     38:  * "po:username".  This will cause movemail to open a connection to
                     39:  * a pop server running on $MAILHOST (environment variable).  Movemail
                     40:  * must be setuid to root in order to work with POP.
                     41:  * 
                     42:  * New module: popmail.c
                     43:  * Modified routines:
                     44:  *     main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
                     45:  *             after POP code. 
                     46:  * New routines in movemail.c:
                     47:  *     get_errmsg - return pointer to system error message
                     48:  *
                     49:  */
                     50: 
                     51: #include <sys/types.h>
                     52: #include <sys/stat.h>
                     53: #include <sys/file.h>
                     54: #include <errno.h>
                     55: #define NO_SHORTNAMES   /* Tell config not to load remap.h */
                     56: #include "../src/config.h"
                     57: 
                     58: #ifdef USG
                     59: #include <fcntl.h>
                     60: #include <unistd.h>
                     61: #ifndef F_OK
                     62: #define F_OK 0
                     63: #define X_OK 1
                     64: #define W_OK 2
                     65: #define R_OK 4
                     66: #endif
                     67: #endif /* USG */
                     68: 
                     69: #ifdef XENIX
                     70: #include <sys/locking.h>
                     71: #endif
                     72: 
                     73: #ifdef MAIL_USE_MMDF
                     74: extern int lk_open (), lk_close ();
                     75: #endif
                     76: 
                     77: /* Cancel substitutions made by config.h for Emacs.  */
                     78: #undef open
                     79: #undef read
                     80: #undef write
                     81: #undef close
                     82: 
                     83: char *concat ();
                     84: extern int errno;
                     85: 
                     86: /* Nonzero means this is name of a lock file to delete on fatal error.  */
                     87: char *delete_lockname;
                     88: 
                     89: main (argc, argv)
                     90:      int argc;
                     91:      char **argv;
                     92: {
                     93:   char *inname, *outname;
                     94:   int indesc, outdesc;
                     95:   char buf[1024];
                     96:   int nread;
                     97: 
                     98: #ifndef MAIL_USE_FLOCK
                     99:   struct stat st;
                    100:   long now;
                    101:   int tem;
                    102:   char *lockname, *p;
                    103:   char *tempname;
                    104:   int desc;
                    105: #endif /* not MAIL_USE_FLOCK */
                    106: 
                    107:   delete_lockname = 0;
                    108: 
                    109:   if (argc < 3)
                    110:     fatal ("two arguments required");
                    111: 
                    112:   inname = argv[1];
                    113:   outname = argv[2];
                    114: 
                    115: #ifdef MAIL_USE_MMDF
                    116:   mmdf_init (argv[0]);
                    117: #endif
                    118: 
                    119:   /* Check access to output file.  */
                    120:   if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
                    121:     pfatal_with_name (outname);
                    122: 
                    123:   /* Also check that outname's directory is writeable to the real uid.  */
                    124:   {
                    125:     char *buf = (char *) malloc (strlen (outname) + 1);
                    126:     char *p, q;
                    127:     strcpy (buf, outname);
                    128:     p = buf + strlen (buf);
                    129:     while (p > buf && p[-1] != '/')
                    130:       *--p = 0;
                    131:     if (p == buf)
                    132:       *p++ = '.';
                    133:     if (access (buf, W_OK) != 0)
                    134:       pfatal_with_name (buf);
                    135:     free (buf);
                    136:   }
                    137: 
                    138: #ifdef MAIL_USE_POP
                    139:   if (!bcmp (inname, "po:", 3))
                    140:     {
                    141:       int status; char *user;
                    142: 
                    143:       user = (char *) rindex (inname, ':') + 1;
                    144:       status = popmail (user, outname);
                    145:       exit (status);
                    146:     }
                    147: 
                    148:   setuid (getuid ());
                    149: #endif /* MAIL_USE_POP */
                    150: 
                    151:   /* Check access to input file.  */
                    152:   if (access (inname, R_OK | W_OK) != 0)
                    153:     pfatal_with_name (inname);
                    154: 
                    155: #ifndef MAIL_USE_MMDF
                    156: #ifndef MAIL_USE_FLOCK
                    157:   /* Use a lock file named /usr/spool/mail/$USER.lock:
                    158:      If it exists, the mail file is locked.  */
                    159:   /* Note: this locking mechanism is *required* by the mailer
                    160:      (on systems which use it) to prevent loss of mail.
                    161: 
                    162:      On systems that use a lock file, extracting the mail without locking
                    163:      WILL occasionally cause loss of mail due to timing errors!
                    164: 
                    165:      So, if creation of the lock file fails
                    166:      due to access permission on /usr/spool/mail,
                    167:      you simply MUST change the permission
                    168:      and/or make movemail a setgid program
                    169:      so it can create lock files properly.
                    170: 
                    171:      You might also wish to verify that your system is one
                    172:      which uses lock files for this purpose.  Some systems use other methods.
                    173: 
                    174:      If your system uses the `flock' system call for mail locking,
                    175:      define MAIL_USE_FLOCK in config.h or the s-*.h file
                    176:      and recompile movemail.  If the s- file for your system
                    177:      should define MAIL_USE_FLOCK but does not, send a bug report
                    178:      to [email protected] so we can fix it.  */
                    179: 
                    180:   lockname = concat (inname, ".lock", "");
                    181:   tempname = (char *) xmalloc (strlen (inname) + 20);
                    182:   strcpy (tempname, inname);
                    183:   p = tempname + strlen (tempname);
                    184:   while (p != tempname && p[-1] != '/')
                    185:     p--;
                    186:   *p = 0;
                    187:   strcpy (p, "EXXXXXX");
                    188:   mktemp (tempname);
                    189:   unlink (tempname);
                    190: 
                    191:   while (1)
                    192:     {
                    193:       /* Create the lock file, but not under the lock file name.  */
                    194:       /* Give up if cannot do that.  */
                    195:       desc = open (tempname, O_WRONLY | O_CREAT, 0666);
                    196:       if (desc < 0)
                    197:         pfatal_with_name ("lock file--see source file etc/movemail.c");
                    198:       close (desc);
                    199: 
                    200:       tem = link (tempname, lockname);
                    201:       unlink (tempname);
                    202:       if (tem >= 0)
                    203:        break;
                    204:       sleep (1);
                    205: 
                    206:       /* If lock file is a minute old, unlock it.  */
                    207:       if (stat (lockname, &st) >= 0)
                    208:        {
                    209:          now = time (0);
                    210:          if (st.st_ctime < now - 60)
                    211:            unlink (lockname);
                    212:        }
                    213:     }
                    214: 
                    215:   delete_lockname = lockname;
                    216: #endif /* not MAIL_USE_FLOCK */
                    217: 
                    218: #ifdef MAIL_USE_FLOCK
                    219:   indesc = open (inname, O_RDWR);
                    220: #else /* if not MAIL_USE_FLOCK */
                    221:   indesc = open (inname, O_RDONLY);
                    222: #endif /* not MAIL_USE_FLOCK */
                    223: #else /* MAIL_USE_MMDF */
                    224:   indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
                    225: #endif /* MAIL_USE_MMDF */
                    226: 
                    227:   if (indesc < 0)
                    228:     pfatal_with_name (inname);
                    229: 
                    230: #if defined (BSD) || defined (XENIX)
                    231:   /* In case movemail is setuid to root, make sure the user can
                    232:      read the output file.  */
                    233:   /* This is desirable for all systems
                    234:      but I don't want to assume all have the umask system call */
                    235:   umask (umask (0) & 0333);
                    236: #endif /* BSD or Xenix */
                    237:   outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
                    238:   if (outdesc < 0)
                    239:     pfatal_with_name (outname);
                    240: #ifdef MAIL_USE_FLOCK
                    241: #ifdef XENIX
                    242:   if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname);
                    243: #else
                    244:   if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname);
                    245: #endif
                    246: #endif /* MAIL_USE_FLOCK */
                    247: 
                    248:   while (1)
                    249:     {
                    250:       nread = read (indesc, buf, sizeof buf);
                    251:       if (nread != write (outdesc, buf, nread))
                    252:        {
                    253:          int saved_errno = errno;
                    254:          unlink (outname);
                    255:          errno = saved_errno;
                    256:          pfatal_with_name (outname);
                    257:        }
                    258:       if (nread < sizeof buf)
                    259:        break;
                    260:     }
                    261: 
                    262: #ifdef BSD
                    263:   if (fsync (outdesc) < 0)
                    264:     pfatal_and_delete (outname);
                    265: #endif
                    266: 
                    267:   /* Check to make sure no errors before we zap the inbox.  */
                    268:   if (close (outdesc) != 0)
                    269:     pfatal_and_delete (outname);
                    270: 
                    271: #ifdef MAIL_USE_FLOCK
                    272: #if defined (STRIDE) || defined (XENIX)
                    273:   /* Stride, xenix have file locking, but no ftruncate.  This mess will do. */
                    274:   close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
                    275: #else
                    276:   ftruncate (indesc, 0L);
                    277: #endif /* STRIDE or XENIX */
                    278: #endif /* MAIL_USE_FLOCK */
                    279: 
                    280: #ifdef MAIL_USE_MMDF
                    281:   lk_close (indesc, 0, 0, 0);
                    282: #else
                    283:   close (indesc);
                    284: #endif
                    285: 
                    286: #ifndef MAIL_USE_FLOCK
                    287:   /* Delete the input file; if we can't, at least get rid of its contents.  */
                    288:   if (unlink (inname) < 0)
                    289:     if (errno != ENOENT)
                    290:       creat (inname, 0666);
                    291: #ifndef MAIL_USE_MMDF
                    292:   unlink (lockname);
                    293: #endif /* not MAIL_USE_MMDF */
                    294: #endif /* not MAIL_USE_FLOCK */
                    295:   exit (0);
                    296: }
                    297: 
                    298: /* Print error message and exit.  */
                    299: 
                    300: fatal (s1, s2)
                    301:      char *s1, *s2;
                    302: {
                    303:   if (delete_lockname)
                    304:     unlink (delete_lockname);
                    305:   error (s1, s2);
                    306:   exit (1);
                    307: }
                    308: 
                    309: /* Print error message.  `s1' is printf control string, `s2' is arg for it. */
                    310: 
                    311: error (s1, s2, s3)
                    312:      char *s1, *s2, *s3;
                    313: {
                    314:   printf ("movemail: ");
                    315:   printf (s1, s2, s3);
                    316:   printf ("\n");
                    317: }
                    318: 
                    319: pfatal_with_name (name)
                    320:      char *name;
                    321: {
                    322:   extern int errno, sys_nerr;
                    323:   extern char *sys_errlist[];
                    324:   char *s;
                    325: 
                    326:   if (errno < sys_nerr)
                    327:     s = concat ("", sys_errlist[errno], " for %s");
                    328:   else
                    329:     s = "cannot open %s";
                    330:   fatal (s, name);
                    331: }
                    332: 
                    333: pfatal_and_delete (name)
                    334:      char *name;
                    335: {
                    336:   extern int errno, sys_nerr;
                    337:   extern char *sys_errlist[];
                    338:   char *s;
                    339: 
                    340:   if (errno < sys_nerr)
                    341:     s = concat ("", sys_errlist[errno], " for %s");
                    342:   else
                    343:     s = "cannot open %s";
                    344: 
                    345:   unlink (name);
                    346:   fatal (s, name);
                    347: }
                    348: 
                    349: /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
                    350: 
                    351: char *
                    352: concat (s1, s2, s3)
                    353:      char *s1, *s2, *s3;
                    354: {
                    355:   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
                    356:   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
                    357: 
                    358:   strcpy (result, s1);
                    359:   strcpy (result + len1, s2);
                    360:   strcpy (result + len1 + len2, s3);
                    361:   *(result + len1 + len2 + len3) = 0;
                    362: 
                    363:   return result;
                    364: }
                    365: 
                    366: /* Like malloc but get fatal error if memory is exhausted.  */
                    367: 
                    368: int
                    369: xmalloc (size)
                    370:      int size;
                    371: {
                    372:   int result = malloc (size);
                    373:   if (!result)
                    374:     fatal ("virtual memory exhausted", 0);
                    375:   return result;
                    376: }
                    377: 
                    378: /* This is the guts of the interface to the Post Office Protocol.  */
                    379: 
                    380: #ifdef MAIL_USE_POP
                    381: 
                    382: #include <sys/socket.h>
                    383: #include <netinet/in.h>
                    384: #include <netdb.h>
                    385: #include <stdio.h>
                    386: #include <pwd.h>
                    387: 
                    388: #ifdef USG
                    389: #include <fcntl.h>
                    390: /* Cancel substitutions made by config.h for Emacs.  */
                    391: #undef open
                    392: #undef read
                    393: #undef write
                    394: #undef close
                    395: #endif /* USG */
                    396: 
                    397: #define NOTOK (-1)
                    398: #define OK 0
                    399: #define DONE 1
                    400: 
                    401: char *progname;
                    402: FILE *sfi;
                    403: FILE *sfo;
                    404: char Errmsg[80];
                    405: 
                    406: static int debug = 0;
                    407: 
                    408: char *get_errmsg ();
                    409: char *getenv ();
                    410: int mbx_write ();
                    411: 
                    412: popmail (user, outfile)
                    413:      char *user;
                    414:      char *outfile;
                    415: {
                    416:   char *host;
                    417:   int nmsgs, nbytes;
                    418:   char response[128];
                    419:   register int i;
                    420:   int mbfi;
                    421:   FILE *mbf;
                    422:   struct passwd *pw = (struct passwd *) getpwuid (getuid ());
                    423:   if (pw == NULL)
                    424:     fatal ("cannot determine user name");
                    425: 
                    426:   host = getenv ("MAILHOST");
                    427:   if (host == NULL)
                    428:     {
                    429:       fatal ("no MAILHOST defined");
                    430:     }
                    431: 
                    432:   if (pop_init (host) == NOTOK)
                    433:     {
                    434:       fatal (Errmsg);
                    435:     }
                    436: 
                    437:   if (getline (response, sizeof response, sfi) != OK)
                    438:     {
                    439:       fatal (response);
                    440:     }
                    441: 
                    442:   if (pop_command ("USER %s", user) == NOTOK
                    443:       || pop_command ("RPOP %s", pw->pw_name) == NOTOK)
                    444:     {
                    445:       pop_command ("QUIT");
                    446:       fatal (Errmsg);
                    447:     }
                    448: 
                    449:   if (pop_stat (&nmsgs, &nbytes) == NOTOK)
                    450:     {
                    451:       pop_command ("QUIT");
                    452:       fatal (Errmsg);
                    453:     }
                    454: 
                    455:   if (!nmsgs)
                    456:     {
                    457:       pop_command ("QUIT");
                    458:       return 0;
                    459:     }
                    460: 
                    461:   mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
                    462:   if (mbfi < 0)
                    463:     {
                    464:       pop_command ("QUIT");
                    465:       pfatal_and_delete (outfile);
                    466:     }
                    467:   fchown (mbfi, getuid (), -1);
                    468: 
                    469:   if ((mbf = fdopen (mbfi, "w")) == NULL)
                    470:     {
                    471:       pop_command ("QUIT");
                    472:       pfatal_and_delete (outfile);
                    473:     }
                    474: 
                    475:   for (i = 1; i <= nmsgs; i++)
                    476:     {
                    477:       mbx_delimit_begin (mbf);
                    478:       if (pop_retr (i, mbx_write, mbf) != OK)
                    479:        {
                    480:          pop_command ("QUIT");
                    481:          close (mbfi);
                    482:          unlink (outfile);
                    483:          fatal (Errmsg);
                    484:        }
                    485:       mbx_delimit_end (mbf);
                    486:       fflush (mbf);
                    487:     }
                    488: 
                    489:   if (fsync (mbfi) < 0)
                    490:     {
                    491:       pop_command ("QUIT");
                    492:       pfatal_and_delete (outfile);
                    493:     }
                    494: 
                    495:   if (close (mbfi) == -1)
                    496:     {
                    497:       pop_command ("QUIT");
                    498:       pfatal_and_delete (outfile);
                    499:     }
                    500: 
                    501:   for (i = 1; i <= nmsgs; i++)
                    502:     {
                    503:       if (pop_command ("DELE %d", i) == NOTOK)
                    504:        {
                    505:          /* Better to ignore this failure.  */
                    506:        }
                    507:     }
                    508: 
                    509:   pop_command ("QUIT");
                    510:   return (0);
                    511: }
                    512: 
                    513: pop_init (host)
                    514:      char *host;
                    515: {
                    516:   register struct hostent *hp;
                    517:   register struct servent *sp;
                    518:   int lport = IPPORT_RESERVED - 1;
                    519:   struct sockaddr_in sin;
                    520:   register int s;
                    521: 
                    522:   hp = gethostbyname (host);
                    523:   if (hp == NULL)
                    524:     {
                    525:       sprintf (Errmsg, "MAILHOST unknown: %s", host);
                    526:       return NOTOK;
                    527:     }
                    528: 
                    529:   sp = getservbyname ("pop", "tcp");
                    530:   if (sp == 0)
                    531:     {
                    532:       strcpy (Errmsg, "tcp/pop: unknown service");
                    533:       return NOTOK;
                    534:     }
                    535: 
                    536:   sin.sin_family = hp->h_addrtype;
                    537:   bcopy (hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
                    538:   sin.sin_port = sp->s_port;
                    539:   s = rresvport (&lport);
                    540:   if (s < 0)
                    541:     {
                    542:       sprintf (Errmsg, "error creating socket: %s", get_errmsg ());
                    543:       return NOTOK;
                    544:     }
                    545: 
                    546:   if (connect (s, (char *)&sin, sizeof sin) < 0)
                    547:     {
                    548:       sprintf (Errmsg, "error during connect: %s", get_errmsg ());
                    549:       close (s);
                    550:       return NOTOK;
                    551:     }
                    552: 
                    553:   sfi = fdopen (s, "r");
                    554:   sfo = fdopen (s, "w");
                    555:   if (sfi == NULL || sfo == NULL)
                    556:     {
                    557:       sprintf (Errmsg, "error in fdopen: %s", get_errmsg ());
                    558:       close (s);
                    559:       return NOTOK;
                    560:     }
                    561: 
                    562:   return OK;
                    563: }
                    564: 
                    565: pop_command (fmt, a, b, c, d)
                    566:      char *fmt;
                    567: {
                    568:   char buf[128];
                    569:   char errmsg[64];
                    570: 
                    571:   sprintf (buf, fmt, a, b, c, d);
                    572: 
                    573:   if (debug) fprintf (stderr, "---> %s\n", buf);
                    574:   if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK;
                    575: 
                    576:   if (getline (buf, sizeof buf, sfi) != OK)
                    577:     {
                    578:       strcpy (Errmsg, buf);
                    579:       return NOTOK;
                    580:     }
                    581: 
                    582:   if (debug)
                    583:     fprintf (stderr, "<--- %s\n", buf);
                    584:   if (*buf != '+')
                    585:     {
                    586:       strcpy (Errmsg, buf);
                    587:       return NOTOK;
                    588:     }
                    589:   else
                    590:     {
                    591:       return OK;
                    592:     }
                    593: }
                    594: 
                    595:     
                    596: pop_stat (nmsgs, nbytes)
                    597:      int *nmsgs, *nbytes;
                    598: {
                    599:   char buf[128];
                    600: 
                    601:   if (debug)
                    602:     fprintf (stderr, "---> STAT\n");
                    603:   if (putline ("STAT", Errmsg, sfo) == NOTOK)
                    604:     return NOTOK;
                    605: 
                    606:   if (getline (buf, sizeof buf, sfi) != OK)
                    607:     {
                    608:       strcpy (Errmsg, buf);
                    609:       return NOTOK;
                    610:     }
                    611: 
                    612:   if (debug) fprintf (stderr, "<--- %s\n", buf);
                    613:   if (*buf != '+')
                    614:     {
                    615:       strcpy (Errmsg, buf);
                    616:       return NOTOK;
                    617:     }
                    618:   else
                    619:     {
                    620:       sscanf (buf, "+OK %d %d", nmsgs, nbytes);
                    621:       return OK;
                    622:     }
                    623: }
                    624: 
                    625: pop_retr (msgno, action, arg)
                    626:      int (*action)();
                    627: {
                    628:   char buf[128];
                    629: 
                    630:   sprintf (buf, "RETR %d", msgno);
                    631:   if (debug) fprintf (stderr, "%s\n", buf);
                    632:   if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK;
                    633: 
                    634:   if (getline (buf, sizeof buf, sfi) != OK)
                    635:     {
                    636:       strcpy (Errmsg, buf);
                    637:       return NOTOK;
                    638:     }
                    639: 
                    640:   while (1)
                    641:     {
                    642:       switch (multiline (buf, sizeof buf, sfi))
                    643:        {
                    644:        case OK:
                    645:          (*action)(buf, arg);
                    646:          break;
                    647:        case DONE:
                    648:          return OK;
                    649:        case NOTOK:
                    650:          strcpy (Errmsg, buf);
                    651:          return NOTOK;
                    652:        }
                    653:     }
                    654: }
                    655: 
                    656: getline (buf, n, f)
                    657:      char *buf;
                    658:      register int n;
                    659:      FILE *f;
                    660: {
                    661:   register char *p;
                    662:   int c;
                    663: 
                    664:   p = buf;
                    665:   while (--n > 0 && (c = fgetc (f)) != EOF)
                    666:     if ((*p++ = c) == '\n') break;
                    667: 
                    668:   if (ferror (f))
                    669:     {
                    670:       strcpy (buf, "error on connection");
                    671:       return NOTOK;
                    672:     }
                    673: 
                    674:   if (c == EOF && p == buf)
                    675:     {
                    676:       strcpy (buf, "connection closed by foreign host");
                    677:       return DONE;
                    678:     }
                    679: 
                    680:   *p = NULL;
                    681:   if (*--p == '\n') *p = NULL;
                    682:   if (*--p == '\r') *p = NULL;
                    683:   return OK;
                    684: }
                    685: 
                    686: multiline (buf, n, f)
                    687:      char *buf;
                    688:      register int n;
                    689:      FILE *f;
                    690: {
                    691:   if (getline (buf, n, f) != OK)
                    692:     return NOTOK;
                    693:   if (*buf == '.')
                    694:     {
                    695:       if (*(buf+1) == NULL)
                    696:        return DONE;
                    697:       else
                    698:        strcpy (buf, buf+1);
                    699:     }
                    700:   return OK;
                    701: }
                    702: 
                    703: char *
                    704: get_errmsg ()
                    705: {
                    706:   extern int errno, sys_nerr;
                    707:   extern char *sys_errlist[];
                    708:   char *s;
                    709: 
                    710:   if (errno < sys_nerr)
                    711:     s = sys_errlist[errno];
                    712:   else
                    713:     s = "unknown error";
                    714:   return (s);
                    715: }
                    716: 
                    717: putline (buf, err, f)
                    718:      char *buf;
                    719:      char *err;
                    720:      FILE *f;
                    721: {
                    722:   fprintf (f, "%s\r\n", buf);
                    723:   fflush (f);
                    724:   if (ferror (f))
                    725:     {
                    726:       strcpy (err, "lost connection");
                    727:       return NOTOK;
                    728:     }
                    729:   return OK;
                    730: }
                    731: 
                    732: mbx_write (line, mbf)
                    733:      char *line;
                    734:      FILE *mbf;
                    735: {
                    736:   fputs (line, mbf);
                    737:   fputc (0x0a, mbf);
                    738: }
                    739: 
                    740: mbx_delimit_begin (mbf)
                    741:      FILE *mbf;
                    742: {
                    743:   fputs ("\f\n0, unseen,,\n", mbf);
                    744: }
                    745: 
                    746: mbx_delimit_end (mbf)
                    747:      FILE *mbf;
                    748: {
                    749:   putc ('\037', mbf);
                    750: }
                    751: 
                    752: #endif /* MAIL_USE_POP */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.