home *** CD-ROM | disk | FTP | other *** search
- /* $Header: mbox.c,v 1.2 88/09/14 19:42:06 network Exp $
- *
- * Finally! Put the message in the specified mailbox(es).
- *
- * $Log: mbox.c,v $
- * Revision 1.2 88/09/14 19:42:06 network
- * Portability to System V and BSD.
- * General fixup.
- *
- * Revision 1.1 88/06/06 09:39:06 chip
- * Initial revision
- *
- */
-
- #include "deliver.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <errno.h>
-
- /*
- * External data.
- */
-
- extern int errno;
-
- /*
- * Local functions.
- */
-
- static mbox_dest();
- static int mbox_write();
- static int mbox_copy();
-
- /*----------------------------------------------------------------------
- * Deliver mail to all valid destinations.
- */
-
- mbox_deliver()
- {
- DEST *d;
-
- for (d = first_dest(); d; d = next_dest(d))
- {
- switch (d->class)
- {
- case CL_USER:
- case CL_MBOX:
- if (d->state == ST_WORKING)
- mbox_dest(d);
- break;
- }
- }
- }
-
- /*----------------------------------------------------------------------
- * Deliver mail to one destination.
- */
-
- static
- mbox_dest(d)
- DEST *d;
- {
- CONTEXT *ct;
- int ret = 0;
-
- if (printaddrs)
- {
- (void) printf("%s", d->name);
- if (d->class == CL_MBOX)
- (void) printf(":%s", d->mailbox);
- (void) printf("\n");
- }
-
- if (dryrun)
- {
- d->state = ST_DONE;
- return;
- }
-
- if ((ct = name_context(d->name)) == NULL)
- {
- d->state = ST_ERROR;
- d->error = "Lost context in mbox_dest()";
- return;
- }
-
- if (! ok_context(ct))
- {
- d->state = ST_ERROR;
- d->error = "No permissions for that context";
- return;
- }
-
- if (d->class == CL_MBOX)
- {
- give_temps(ct);
-
- if (sfork() == 0)
- {
- if (become(ct, !boxdelivery) < 0)
- exit(1);
- if (mbox_write(d->mailbox, ct, FALSE) < 0)
- exit(1);
- exit(0);
- }
-
- if (await_child() != 0)
- ret = -1;
- }
- else
- {
- char mailbox[100];
-
- (void) sprintf(mailbox, "%s/%s",
- #ifdef MAILBOX_DIR
- MAILBOX_DIR, d->name
- #else
- d->home, MAILBOX_NAME
- #endif
- );
-
- if (mbox_write(mailbox, ct, TRUE) < 0)
- ret = -1;
- }
-
- if (ret >= 0)
- d->state = ST_DONE;
- else
- {
- d->state = ST_ERROR;
- d->error = "Error writing to mailbox";
- }
- }
-
- /*----------------------------------------------------------------------
- * Write mail to the named mailbox.
- * If we have to create the mailbox, give it to the specified user.
- * If "is_sys" is true, then we're writing to a system mailbox.
- */
-
- static int
- mbox_write(mailbox, ct, is_sys)
- char *mailbox;
- CONTEXT *ct;
- int is_sys;
- {
- int fd, t;
- int ret = 0;
-
- if (verbose)
- {
- message("As %s, delivering to %s mailbox %s\n",
- ct->name, (is_sys ? "system" : "user"), mailbox);
- }
-
- if (lock_name(mailbox) < 0)
- return -1;
-
- while ((fd = open(mailbox, O_RDWR)) == -1)
- {
- if (errno != ENOENT)
- {
- syserr("can't open %s", mailbox);
- break;
- }
-
- if ((fd = open(mailbox, O_RDWR|O_CREAT|O_EXCL,
- MAILBOX_MODE)) != -1)
- {
- /* Make sure the mailbox receives the correct modes */
-
- int mbox_gid = ct->gid;
-
- #ifdef MAILBOX_GROUP
- if (is_sys)
- {
- static int mbox_gid_sv = -2;
-
- if (mbox_gid_sv == -2)
- mbox_gid_sv = group_id(MAILBOX_GROUP);
-
- if (mbox_gid_sv < 0)
- message("%s: no such group\n", MAILBOX_GROUP);
- else
- mbox_gid = mbox_gid_sv;
- }
- #endif /* MAILBOX_GROUP */
-
- if (chown(mailbox, ct->uid, mbox_gid) == -1)
- {
- /* print a message, but that's all. (???) */
- syserr("can't chown %s to %d,%d",
- mailbox, ct->uid, mbox_gid);
- }
- break;
- }
-
- if (errno != EEXIST)
- {
- syserr("can't create %s", mailbox);
- break;
- }
- }
-
- if (fd == -1)
- {
- (void) unlock_name(mailbox);
- return -1;
- }
-
- if (lock_fd(fd) < 0)
- {
- (void) close(fd);
- (void) unlock_name(mailbox);
- return -1;
- }
-
- (void) lseek(fd, 0L, 2); /* No error check: may be a special file */
-
- for (t = 0; t < T_MAX; ++t)
- {
- if (lseek(tfd[t], 0L, 0) == -1)
- {
- syserr("lseek in %s file %s", ttype[t], tfile[t]);
- ret = -1;
- break;
- }
-
- switch (mbox_copy(tfd[t], fd))
- {
- case 1:
- syserr("can't read %s file %s", ttype[t], tfile[t]);
- ret = -1;
- break;
- case 2:
- syserr("can't write to mailbox %s as %s",
- mailbox, ct->name);
- ret = -1;
- break;
- default:
- continue;
- }
- break;
- }
-
- if (verbose)
- {
- if (ret >= 0)
- message("wrote message to %s\n", mailbox);
- }
-
- if (unlock_fd(fd) < 0)
- ret = -1;
- (void) close(fd);
- if (unlock_name(mailbox) < 0)
- ret = -1;
-
- return ret;
- }
-
- /*----------------------------------------------------------------------
- * Copy the named file to the given file descriptor.
- */
-
- static int
- mbox_copy(ifd, ofd)
- int ifd;
- int ofd;
- {
- char buf[BUFSIZ];
- int rd;
-
- while ((rd = read(ifd, buf, sizeof(buf))) > 0)
- {
- errno = 255; /* to avoid bogus syserr() output */
- if (write(ofd, buf, (unsigned) rd) != rd)
- return 2;
- }
-
- if (rd == -1)
- return 1;
-
- return 0;
- }
-