home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / deliver / part03 / mbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-14  |  4.7 KB  |  285 lines

  1. /* $Header: mbox.c,v 1.2 88/09/14 19:42:06 network Exp $
  2.  *
  3.  * Finally!  Put the message in the specified mailbox(es).
  4.  *
  5.  * $Log:    mbox.c,v $
  6.  * Revision 1.2  88/09/14  19:42:06  network
  7.  * Portability to System V and BSD.
  8.  * General fixup.
  9.  * 
  10.  * Revision 1.1  88/06/06  09:39:06  chip
  11.  * Initial revision
  12.  * 
  13.  */
  14.  
  15. #include "deliver.h"
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <errno.h>
  19.  
  20. /*
  21.  * External data.
  22.  */
  23.  
  24. extern  int     errno;
  25.  
  26. /*
  27.  * Local functions.
  28.  */
  29.  
  30. static          mbox_dest();
  31. static  int     mbox_write();
  32. static  int     mbox_copy();
  33.  
  34. /*----------------------------------------------------------------------
  35.  * Deliver mail to all valid destinations.
  36.  */
  37.  
  38. mbox_deliver()
  39. {
  40.     DEST    *d;
  41.  
  42.     for (d = first_dest(); d; d = next_dest(d))
  43.     {
  44.         switch (d->class)
  45.         {
  46.         case CL_USER:
  47.         case CL_MBOX:
  48.             if (d->state == ST_WORKING)
  49.                 mbox_dest(d);
  50.             break;
  51.         }
  52.     }
  53. }
  54.  
  55. /*----------------------------------------------------------------------
  56.  * Deliver mail to one destination.
  57.  */
  58.  
  59. static
  60. mbox_dest(d)
  61. DEST    *d;
  62. {
  63.     CONTEXT *ct;
  64.     int     ret = 0;
  65.  
  66.     if (printaddrs)
  67.     {
  68.         (void) printf("%s", d->name);
  69.         if (d->class == CL_MBOX)
  70.             (void) printf(":%s", d->mailbox);
  71.         (void) printf("\n");
  72.     }
  73.  
  74.     if (dryrun)
  75.     {
  76.         d->state = ST_DONE;
  77.         return;
  78.     }
  79.  
  80.     if ((ct = name_context(d->name)) == NULL)
  81.     {
  82.         d->state = ST_ERROR;
  83.         d->error = "Lost context in mbox_dest()";
  84.         return;
  85.     }
  86.  
  87.     if (! ok_context(ct))
  88.     {
  89.         d->state = ST_ERROR;
  90.         d->error = "No permissions for that context";
  91.         return;
  92.     }
  93.  
  94.     if (d->class == CL_MBOX)
  95.     {
  96.         give_temps(ct);
  97.  
  98.         if (sfork() == 0)
  99.         {
  100.             if (become(ct, !boxdelivery) < 0)
  101.                 exit(1);
  102.             if (mbox_write(d->mailbox, ct, FALSE) < 0)
  103.                 exit(1);
  104.             exit(0);
  105.         }
  106.  
  107.         if (await_child() != 0)
  108.             ret = -1;
  109.     }
  110.     else
  111.     {
  112.         char    mailbox[100];
  113.  
  114.         (void) sprintf(mailbox, "%s/%s",
  115. #ifdef MAILBOX_DIR
  116.             MAILBOX_DIR, d->name
  117. #else
  118.             d->home, MAILBOX_NAME
  119. #endif
  120.             );
  121.  
  122.         if (mbox_write(mailbox, ct, TRUE) < 0)
  123.             ret = -1;
  124.     }
  125.  
  126.     if (ret >= 0)
  127.         d->state = ST_DONE;
  128.     else
  129.     {
  130.         d->state = ST_ERROR;
  131.         d->error = "Error writing to mailbox";
  132.     }
  133. }
  134.  
  135. /*----------------------------------------------------------------------
  136.  * Write mail to the named mailbox.
  137.  * If we have to create the mailbox, give it to the specified user.
  138.  * If "is_sys" is true, then we're writing to a system mailbox.
  139.  */
  140.  
  141. static int
  142. mbox_write(mailbox, ct, is_sys)
  143. char    *mailbox;
  144. CONTEXT *ct;
  145. int     is_sys;
  146. {
  147.     int     fd, t;
  148.     int     ret = 0;
  149.  
  150.     if (verbose)
  151.     {
  152.         message("As %s, delivering to %s mailbox %s\n",
  153.             ct->name, (is_sys ? "system" : "user"), mailbox);
  154.     }
  155.  
  156.     if (lock_name(mailbox) < 0)
  157.         return -1;
  158.  
  159.     while ((fd = open(mailbox, O_RDWR)) == -1)
  160.     {
  161.         if (errno != ENOENT)
  162.         {
  163.             syserr("can't open %s", mailbox);
  164.             break;
  165.         }
  166.  
  167.         if ((fd = open(mailbox, O_RDWR|O_CREAT|O_EXCL,
  168.                 MAILBOX_MODE)) != -1)
  169.         {
  170.             /* Make sure the mailbox receives the correct modes */
  171.  
  172.             int mbox_gid = ct->gid;
  173.  
  174. #ifdef MAILBOX_GROUP
  175.             if (is_sys)
  176.             {
  177.                 static int mbox_gid_sv = -2;
  178.  
  179.                 if (mbox_gid_sv == -2)
  180.                     mbox_gid_sv = group_id(MAILBOX_GROUP);
  181.  
  182.                 if (mbox_gid_sv < 0)
  183.                     message("%s: no such group\n", MAILBOX_GROUP);
  184.                 else
  185.                     mbox_gid = mbox_gid_sv;
  186.             }
  187. #endif /* MAILBOX_GROUP */
  188.  
  189.             if (chown(mailbox, ct->uid, mbox_gid) == -1)
  190.             {
  191.                 /* print a message, but that's all. (???) */
  192.                 syserr("can't chown %s to %d,%d",
  193.                     mailbox, ct->uid, mbox_gid);
  194.             }
  195.             break;
  196.         }
  197.  
  198.         if (errno != EEXIST)
  199.         {
  200.             syserr("can't create %s", mailbox);
  201.             break;
  202.         }
  203.     }
  204.  
  205.     if (fd == -1)
  206.     {
  207.         (void) unlock_name(mailbox);
  208.         return -1;
  209.     }
  210.  
  211.     if (lock_fd(fd) < 0)
  212.     {
  213.         (void) close(fd);
  214.         (void) unlock_name(mailbox);
  215.         return -1;
  216.     }
  217.  
  218.     (void) lseek(fd, 0L, 2); /* No error check: may be a special file */
  219.  
  220.     for (t = 0; t < T_MAX; ++t)
  221.     {
  222.         if (lseek(tfd[t], 0L, 0) == -1)
  223.         {
  224.             syserr("lseek in %s file %s", ttype[t], tfile[t]);
  225.             ret = -1;
  226.             break;
  227.         }
  228.  
  229.         switch (mbox_copy(tfd[t], fd))
  230.         {
  231.         case 1:
  232.             syserr("can't read %s file %s", ttype[t], tfile[t]);
  233.             ret = -1;
  234.             break;
  235.         case 2:
  236.             syserr("can't write to mailbox %s as %s",
  237.                 mailbox, ct->name);
  238.             ret = -1;
  239.             break;
  240.         default:
  241.             continue;
  242.         }
  243.         break;
  244.     }
  245.  
  246.     if (verbose)
  247.     {
  248.         if (ret >= 0)
  249.             message("wrote message to %s\n", mailbox);
  250.     }
  251.  
  252.     if (unlock_fd(fd) < 0)
  253.         ret = -1;
  254.     (void) close(fd);
  255.     if (unlock_name(mailbox) < 0)
  256.         ret = -1;
  257.  
  258.     return ret;
  259. }
  260.  
  261. /*----------------------------------------------------------------------
  262.  * Copy the named file to the given file descriptor.
  263.  */
  264.  
  265. static int
  266. mbox_copy(ifd, ofd)
  267. int     ifd;
  268. int     ofd;
  269. {
  270.     char    buf[BUFSIZ];
  271.     int     rd;
  272.  
  273.     while ((rd = read(ifd, buf, sizeof(buf))) > 0)
  274.     {
  275.         errno = 255;    /* to avoid bogus syserr() output */
  276.         if (write(ofd, buf, (unsigned) rd) != rd)
  277.             return 2;
  278.     }
  279.  
  280.     if (rd == -1)
  281.         return 1;
  282.  
  283.     return 0;
  284. }
  285.