home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / delivery / deliver.tz / deliver / mbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-07  |  6.5 KB  |  372 lines

  1. /* $Header: mbox.c,v 2.5 90/02/23 16:35:55 chip Exp $
  2.  *
  3.  * Finally!  Put the message in the specified mailbox(es).
  4.  *
  5.  * $Log:    mbox.c,v $
  6.  * Revision 2.5  90/02/23  16:35:55  chip
  7.  * \Fix problems determining legality of user references.
  8.  * 
  9.  * Revision 2.4  90/02/23  14:16:50  chip
  10.  * Support "#!" in delivery files.
  11.  * Support "user|program" and "user?error" from delivery files.
  12.  * Improve debugging and error message formatting.
  13.  * Rearrange code for clarity.
  14.  * 
  15.  * Revision 2.3  90/02/06  11:56:42  chip
  16.  * Enforce MBX_MODE regardless of UMASK.
  17.  * Enforce ordered logging with a log lockfile.
  18.  * Revise log format.
  19.  * 
  20.  * Revision 2.2  89/11/01  11:51:05  network
  21.  * Fix error code; unknown user is now reported correctly.
  22.  * 
  23.  * Revision 2.1  89/06/09  12:25:33  network
  24.  * Update RCS revisions.
  25.  * 
  26.  * Revision 1.6  89/06/09  12:23:55  network
  27.  * Baseline for 2.0 release.
  28.  * 
  29.  */
  30.  
  31. #include "deliver.h"
  32. #include <sys/stat.h>
  33. #include <errno.h>
  34.  
  35. /*
  36.  * External data.
  37.  */
  38.  
  39. extern  int     errno;
  40.  
  41. /*
  42.  * Local functions.
  43.  */
  44.  
  45. static        prog_one();
  46. static          mbox_one();
  47. static  int     mbox_write();
  48.  
  49. /*----------------------------------------------------------------------
  50.  * Deliver mail to all valid program (pipe) destinations.
  51.  * Return count of programs to which we tried to write.
  52.  */
  53.  
  54. int
  55. prog_deliver()
  56. {
  57.     DEST    *d;
  58.     int    progcount;
  59.  
  60.     progcount = 0;
  61.     for (d = first_dest(); d; d = next_dest(d))
  62.     {
  63.         if (d->d_state != ST_WORKING)
  64.             continue;
  65.  
  66.         if (d->d_class == CL_PROG)
  67.         {
  68.             prog_one(d);
  69.             ++progcount;
  70.         }
  71.     }
  72.  
  73.     return progcount;
  74. }
  75.  
  76. /*----------------------------------------------------------------------
  77.  * Deliver mail to one program.
  78.  */
  79.  
  80. static
  81. prog_one(d)
  82. DEST    *d;
  83. {
  84.     CONTEXT *ct;
  85.     char    *av[4];
  86.     int    fd;
  87.  
  88.     if (printaddrs)
  89.         (void) printf("%s|%s\n", d->d_name, d->d_param);
  90.  
  91.     if (dryrun)
  92.     {
  93.         d->d_state = ST_DONE;
  94.         return;
  95.     }
  96.  
  97.     if ((ct = name_context(d->d_name)) == NULL)
  98.     {
  99.         dest_err(d, E_NSUSER);
  100.         return;
  101.     }
  102.  
  103.     if (! ok_context(eff_uid, real_uid, real_gid, ct))
  104.     {
  105.         dest_err(d, E_CTPERM);
  106.         return;
  107.     }
  108.  
  109.     av[0] = SHELL;
  110.     av[1] = "-c";
  111.     av[2] = d->d_param;
  112.     av[3] = NULL;
  113.     if ((fd = ct_openv(ct, av[0], av, O_WRONLY)) == -1)
  114.     {
  115.         dest_err(d, E_PIPE);
  116.         return;
  117.     }
  118.  
  119.     (void) lseek(tfd[T_HDR], 0L, 0);
  120.     (void) lseek(tfd[T_BODY], 0L, 0);
  121.     if (copyfd(tfd[T_HDR], fd) < 0 || copyfd(tfd[T_BODY], fd) < 0)
  122.         dest_err(d, E_PIPE);
  123.  
  124.     if (ct_close(fd))
  125.         dest_err(d, E_PROG);
  126.     else
  127.         d->d_state = ST_DONE;
  128. }
  129.  
  130. /*----------------------------------------------------------------------
  131.  * Deliver mail to all valid mailbox destinations.
  132.  * Return count of mailboxes to which we tried to write.
  133.  */
  134.  
  135. int
  136. mbox_deliver()
  137. {
  138.     DEST    *d;
  139.     int    mboxcount;
  140.  
  141.     mboxcount = 0;
  142.     for (d = first_dest(); d; d = next_dest(d))
  143.     {
  144.         if (d->d_state != ST_WORKING)
  145.             continue;
  146.  
  147.         if (d->d_class == CL_USER || d->d_class == CL_MBOX)
  148.         {
  149.             mbox_one(d);
  150.             ++mboxcount;
  151.         }
  152.     }
  153.  
  154.     return mboxcount;
  155. }
  156.  
  157. /*----------------------------------------------------------------------
  158.  * Deliver mail to one mailbox destination.
  159.  */
  160.  
  161. static
  162. mbox_one(d)
  163. DEST    *d;
  164. {
  165.     CONTEXT *ct;
  166.     int     ret = 0;
  167.  
  168.     if (printaddrs)
  169.     {
  170.         (void) printf("%s", d->d_name);
  171.         if (d->d_class == CL_MBOX)
  172.             (void) printf(":%s", d->d_param);
  173.         (void) printf("\n");
  174.     }
  175.  
  176.     if (dryrun)
  177.     {
  178.         d->d_state = ST_DONE;
  179.         return;
  180.     }
  181.  
  182.     if ((ct = name_context(d->d_name)) == NULL)
  183.     {
  184.         dest_err(d, E_NSUSER);
  185.         return;
  186.     }
  187.  
  188.     if (! ok_context(eff_uid, real_uid, real_gid, ct))
  189.     {
  190.         dest_err(d, E_CTPERM);
  191.         return;
  192.     }
  193.  
  194.     if (d->d_class == CL_MBOX)
  195.     {
  196.         if (sfork() == 0)
  197.         {
  198.             if (become(ct, !boxdelivery) < 0)
  199.                 exit(1);
  200.             if (mbox_write(d->d_param, ct, FALSE) < 0)
  201.                 exit(1);
  202.             exit(0);
  203.         }
  204.  
  205.         if (await_child() != 0)
  206.             ret = -1;
  207.     }
  208.     else
  209.     {
  210.         char    mailbox[100];
  211.  
  212.         (void) sprintf(mailbox, "%s/%s",
  213. #ifdef MBX_DIR
  214.             MBX_DIR, d->d_name
  215. #else
  216.             d->d_home, MBX_NAME
  217. #endif
  218.             );
  219.  
  220.         if (mbox_write(mailbox, ct, TRUE) < 0)
  221.             ret = -1;
  222.     }
  223.  
  224.     if (ret >= 0)
  225.         d->d_state = ST_DONE;
  226.     else
  227.         dest_err(d, E_MBOX);
  228. }
  229.  
  230. /*----------------------------------------------------------------------
  231.  * Write mail to the named mailbox.
  232.  * If we have to create the mailbox, give it to the specified user.
  233.  * If "is_sys" is true, then we're writing to a system mailbox.
  234.  */
  235.  
  236. static int
  237. mbox_write(mailbox, ct, is_sys)
  238. char    *mailbox;
  239. CONTEXT *ct;
  240. int     is_sys;
  241. {
  242.     struct stat st;
  243.     int     fd, t, mbox_uid, mbox_gid;
  244.     int     ret = 0;
  245.  
  246.     if (verbose)
  247.     {
  248.         message("As %s, delivering to %s mailbox %s\n",
  249.             ct->ct_name, (is_sys ? "system" : "user"), mailbox);
  250.     }
  251.  
  252.     if (name_lock(mailbox) < 0)
  253.         return -1;
  254.  
  255.     while ((fd = open(mailbox, O_WRONLY)) == -1)
  256.     {
  257.         int    um;
  258.  
  259.         if (errno != ENOENT)
  260.         {
  261.             syserr("can't open %s", mailbox);
  262.             break;
  263.         }
  264.  
  265.         um = umask(0);    /* save old umask; set it to zero */
  266. #ifdef O_CREAT
  267.         fd = open(mailbox, O_WRONLY|O_CREAT|O_EXCL, MBX_MODE);
  268. #else
  269.         fd = creat(mailbox, MBX_MODE);
  270. #endif
  271.         (void) umask(um); /* restore umask; ass_u_me errno unchanged */
  272.  
  273.         if (fd == -1)
  274.         {
  275.             /* If the error is "file already there", try again. */
  276.             if (errno == EEXIST)
  277.                 continue;
  278.  
  279.             /* Something is very wrong... */
  280.             syserr("can't create %s", mailbox);
  281.             break;
  282.         }
  283.  
  284.         /* Make sure the mailbox receives the correct modes */
  285.  
  286.         mbox_uid = ct->ct_uid;
  287.         mbox_gid = ct->ct_gid;
  288.  
  289. #ifdef MBX_GROUP
  290.         if (is_sys)
  291.         {
  292.             static int mbox_sv_gid = -2;
  293.  
  294.             if (mbox_sv_gid == -2)
  295.                 mbox_sv_gid = group_id(MBX_GROUP);
  296.  
  297.             if (mbox_sv_gid < 0)
  298.                 message("%s: no such group\n", MBX_GROUP);
  299.             else
  300.                 mbox_gid = mbox_sv_gid;
  301.         }
  302. #endif /* MBX_GROUP */
  303.  
  304.         if (fstat(fd, &st) == -1)
  305.         {
  306.             syserr("can't fstat open mailbox?!");
  307.             (void) close(fd);
  308.             fd = -1;
  309.             break;
  310.         }
  311.  
  312.         /* Change mailbox ownership if it's not already correct. */
  313.  
  314.         if ((st.st_uid != mbox_uid || st.st_gid != mbox_gid)
  315.          && chown(mailbox, mbox_uid, mbox_gid) == -1)
  316.         {
  317.             /* print a message, but that's all. (???) */
  318.             syserr("can't chown %s to %d,%d",
  319.                 mailbox, mbox_uid, mbox_gid);
  320.         }
  321.  
  322.         /* It's open now, so we can stop looping now. */
  323.  
  324.         break;
  325.     }
  326.  
  327.     if (fd == -1)
  328.     {
  329.         (void) name_unlock(mailbox);
  330.         return -1;
  331.     }
  332.  
  333.     if (fd_lock(fd) < 0)
  334.     {
  335.         (void) close(fd);
  336.         (void) name_unlock(mailbox);
  337.         return -1;
  338.     }
  339.  
  340.     (void) lseek(fd, 0L, 2); /* No error check: may be a special file */
  341.  
  342.     for (t = T_HDR; t <= T_BODY; ++t)
  343.     {
  344.         if (lseek(tfd[t], 0L, 0) == -1)
  345.         {
  346.             syserr("lseek in %s file %s", ttype[t], tfile[t]);
  347.             ret = -1;
  348.             break;
  349.         }
  350.  
  351.         if (copyfd(tfd[t], fd) < 0)
  352.         {
  353.             ret = -1;
  354.             break;
  355.         }
  356.     }
  357.  
  358.     if (verbose)
  359.     {
  360.         if (ret >= 0)
  361.             message("wrote message to %s\n", mailbox);
  362.     }
  363.  
  364.     if (fd_unlock(fd) < 0)
  365.         ret = -1;
  366.     (void) close(fd);
  367.     if (name_unlock(mailbox) < 0)
  368.         ret = -1;
  369.  
  370.     return ret;
  371. }
  372.