diff options
-rw-r--r-- | libexec/mail.local/Makefile | 9 | ||||
-rw-r--r-- | libexec/mail.local/mail.local.8 | 110 | ||||
-rw-r--r-- | libexec/mail.local/mail.local.c | 548 | ||||
-rw-r--r-- | libexec/mail.local/pathnames.h | 37 |
4 files changed, 5 insertions, 699 deletions
diff --git a/libexec/mail.local/Makefile b/libexec/mail.local/Makefile index 59eaed2..98f9108 100644 --- a/libexec/mail.local/Makefile +++ b/libexec/mail.local/Makefile @@ -1,11 +1,12 @@ # @(#)Makefile 8.1 (Berkeley) 7/19/93 -# $Id$ +# $Id: Makefile,v 1.7 1997/02/22 14:21:47 peter Exp $ + +.PATH: ${.CURDIR}/../../contrib/sendmail/mail.local \ + ${.CURDIR}/../../contrib/sendmail/src PROG= mail.local +SRCS= mail.local.c snprintf.c MAN8= mail.local.8 -.if defined(DONT_FSYNC) -CFLAGS+= -DDONT_FSYNC -.endif BINOWN= root BINMODE=4555 INSTALLFLAGS=-fschg diff --git a/libexec/mail.local/mail.local.8 b/libexec/mail.local/mail.local.8 deleted file mode 100644 index b7d1e87..0000000 --- a/libexec/mail.local/mail.local.8 +++ /dev/null @@ -1,110 +0,0 @@ -.\" Copyright (c) 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)mail.local.8 8.2 (Berkeley) 12/11/93 -.\" $Id: mail.local.8,v 1.7 1997/10/11 22:05:42 wosch Exp $ -.\" -.Dd December 11, 1993 -.Dt MAIL.LOCAL 8 -.Os -.Sh NAME -.Nm mail.local -.Nd store mail in a mailbox -.Sh SYNOPSIS -.Nm mail.local -.Op Fl f Ar from -.Op Fl b -.Ar user ... -.Sh DESCRIPTION -.Nm Mail.local -reads the standard input up to an end-of-file and appends it to each -.Ar user Ns 's -.Pa mail -file. -The -.Ar user -must be a valid user name. -.Pp -The options are as follows: -.Bl -tag -width xxxfrom -.It Fl f Ar from -Specify the sender's name. -.It Fl b -Turn off the attempts to notify the -.Dq biff -service. -.El -.Pp -Individual mail messages in the mailbox are delimited by an empty -line followed by a line beginning with the string ``From ''. -A line containing the string ``From '', the sender's name and a time stamp -is prepended to each delivered mail message. -A blank line is appended to each message. -A greater-than character (``>'') is prepended to any line in the message -which could be mistaken for a ``From '' delimiter line. -.Pp -The mail files are exclusively locked with -.Xr flock 2 -while mail is appended. -.Pp -If the ``biff'' service is returned by -.Xr getservbyname 3 , -the biff server is notified of delivered mail. -.Pp -The -.Nm mail.local -utility exits 0 on success, and >0 if an error occurs. -.Sh ENVIRONMENT -.Bl -tag -width indent -.It Ev TZ -Used to set the appropriate time zone on the timestamp. -.El -.Sh FILES -.Bl -tag -width /var/tmp/local.XXXXXX -compact -.It Pa /var/tmp/local.XXXXXX -temporary files -.It Pa /var/mail/user -user's mailbox directory -.El -.Sh SEE ALSO -.Xr mail 1 , -.Xr flock 2 , -.Xr getservbyname 3 , -.Xr comsat 8 , -.Xr sendmail 8 -.Sh HISTORY -A superset of -.Nm mail.local -(handling mailbox reading as well as mail delivery) -appeared in -.At v7 -as the program -.Nm mail . diff --git a/libexec/mail.local/mail.local.c b/libexec/mail.local/mail.local.c deleted file mode 100644 index 633196e..0000000 --- a/libexec/mail.local/mail.local.c +++ /dev/null @@ -1,548 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: mail.local.c,v 1.15 1997/12/24 19:38:18 imp Exp $ - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1990, 1993, 1994\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)mail.local.c 8.6 (Berkeley) 4/8/94"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <errno.h> -#include <fcntl.h> -#include <netdb.h> -#include <pwd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> -#include <syslog.h> -#include <time.h> -#include <unistd.h> - -#if __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -#include "pathnames.h" - -int eval = EX_OK; /* sysexits.h error value. */ - -void deliver __P((int, char *, int)); -void e_to_sys __P((int)); -void err __P((const char *, ...)) __dead2; -void notifybiff __P((char *)); -int store __P((char *)); -void usage __P((void)); -void vwarn __P((const char *, _BSD_VA_LIST_)); -void warn __P((const char *, ...)); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - struct passwd *pw; - int ch, fd, nobiff; - uid_t uid; - char *from; - - openlog("mail.local", 0, LOG_MAIL); - - from = NULL; - nobiff = 0; - while ((ch = getopt(argc, argv, "bdf:r:")) != -1) - switch(ch) { - case 'b': - nobiff++; - break; - case 'd': /* Backward compatible. */ - break; - case 'f': - case 'r': /* Backward compatible. */ - if (from != NULL) { - warn("multiple -f options"); - usage(); - } - from = optarg; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (!*argv) - usage(); - - /* - * If from not specified, use the name from getlogin() if the - * uid matches, otherwise, use the name from the password file - * corresponding to the uid. - */ - uid = getuid(); - if (!from && (!(from = getlogin()) || - !(pw = getpwnam(from)) || pw->pw_uid != uid)) - from = (pw = getpwuid(uid)) ? pw->pw_name : "???"; - - /* - * There is no way to distinguish the error status of one delivery - * from the rest of the deliveries. So, if we failed hard on one - * or more deliveries, but had no failures on any of the others, we - * return a hard failure. If we failed temporarily on one or more - * deliveries, we return a temporary failure regardless of the other - * failures. This results in the delivery being reattempted later - * at the expense of repeated failures and multiple deliveries. - */ - for (fd = store(from); *argv; ++argv) - deliver(fd, *argv, nobiff); - exit(eval); -} - -int -store(from) - char *from; -{ - FILE *fp; - time_t tval; - int fd, eline; - char *tn, line[2048]; - - tn = strdup(_PATH_LOCTMP); - if ((fd = mkstemp(tn)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { - e_to_sys(errno); - err("unable to open temporary file"); - } - (void)unlink(tn); - free(tn); - - (void)time(&tval); - (void)fprintf(fp, "From %s %s", from, ctime(&tval)); - - line[0] = '\0'; - for (eline = 1; fgets(line, sizeof(line), stdin);) { - if (line[0] == '\n') - eline = 1; - else { - if (eline && line[0] == 'F' && - !memcmp(line, "From ", 5)) - (void)putc('>', fp); - eline = 0; - } - (void)fprintf(fp, "%s", line); - if (ferror(fp)) { - e_to_sys(errno); - err("temporary file write error"); - } - } - - /* If message not newline terminated, need an extra. */ - if (!strchr(line, '\n')) - (void)putc('\n', fp); - /* Output a newline; note, empty messages are allowed. */ - (void)putc('\n', fp); - - if (fflush(fp) == EOF || ferror(fp)) { - e_to_sys(errno); - err("temporary file write error"); - } - return (fd); -} - -void -deliver(fd, name, nobiff) - int fd, nobiff; - char *name; -{ - struct stat fsb, sb; - struct passwd *pw; - int mbfd, nr, nw, off; - char biffmsg[100], buf[8*1024], path[MAXPATHLEN]; - off_t curoff; - uid_t saveeuid; - - /* - * Disallow delivery to unknown names -- special mailboxes can be - * handled in the sendmail aliases file. - */ - if (!(pw = getpwnam(name))) { - if (eval != EX_TEMPFAIL) - eval = EX_UNAVAILABLE; - warn("unknown name: %s", name); - return; - } - - (void)snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name); - - /* - * If the mailbox is linked or a symlink, fail. There's an obvious - * race here, that the file was replaced with a symbolic link after - * the lstat returned, but before the open. We attempt to detect - * this by comparing the original stat information and information - * returned by an fstat of the file descriptor returned by the open. - * - * NB: this is a symptom of a larger problem, that the mail spooling - * directory is writeable by the wrong users. If that directory is - * writeable, system security is compromised for other reasons, and - * it cannot be fixed here. - * - * If we created the mailbox, set the owner/group. If that fails, - * just return. Another process may have already opened it, so we - * can't unlink it. Historically, binmail set the owner/group at - * each mail delivery. We no longer do this, assuming that if the - * ownership or permissions were changed there was a reason. - * - * XXX - * open(2) should support flock'ing the file. - */ - saveeuid=geteuid(); - -tryagain: - if (lstat(path, &sb)) { - mbfd = open(path, - O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); - if (mbfd == -1) { - if (errno == EEXIST) - goto tryagain; - } else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) { - e_to_sys(errno); - warn("chown %u.%u: %s", pw->pw_uid, pw->pw_gid, name); - return; - } - - /* - * Now that the box is created and permissions are correct, we - * close it and go back to the top so that we will come in - * and write as the user. We dont seteuid() before the above - * open, because we have to be root/bin to write in var/mail - * -Crh (henrich@msu.edu) - */ - close(mbfd); - goto tryagain; - } else if (sb.st_nlink != 1 || S_ISLNK(sb.st_mode)) { - e_to_sys(errno); - warn("%s: linked file", path); - return; - } else { - /* Become the user, so quota enforcement will occur */ - if(seteuid(pw->pw_uid) != 0) { - warn("Unable to seteuid()"); - return; - } - - mbfd = open(path, O_APPEND|O_WRONLY, 0); - if (mbfd != -1 && - (fstat(mbfd, &fsb) || fsb.st_nlink != 1 || - S_ISLNK(fsb.st_mode) || sb.st_dev != fsb.st_dev || - sb.st_ino != fsb.st_ino)) { - warn("%s: file changed after open", path); - (void)close(mbfd); - seteuid(saveeuid); - return; - } - } - - if (mbfd == -1) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); - seteuid(saveeuid); - return; - } - - /* Wait until we can get a lock on the file. */ - if (flock(mbfd, LOCK_EX)) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); - goto err1; - } - - curoff = lseek(mbfd, (off_t)0, SEEK_END); - if (!nobiff) { - (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%qd\n", - name, curoff); - } - - /* Copy the message into the file. */ - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { - e_to_sys(errno); - warn("temporary file: %s", strerror(errno)); - goto err1; - } - while ((nr = read(fd, buf, sizeof(buf))) > 0) - for (off = 0; off < nr; nr -= nw, off += nw) - if ((nw = write(mbfd, buf + off, nr)) < 0) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); - goto err2; - } - if (nr < 0) { - e_to_sys(errno); - warn("temporary file: %s", strerror(errno)); -err2: (void)ftruncate(mbfd, curoff); -err1: (void)close(mbfd); - seteuid(saveeuid); - return; - } - -#ifndef DONT_FSYNC - /* Flush to disk, don't wait for update. */ - if (fsync(mbfd)) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); - goto err2; - } -#endif - - /* Close and check -- NFS doesn't write until the close. */ - if (close(mbfd)) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); - seteuid(saveeuid); - return; - } - - seteuid(saveeuid); - - if (!nobiff) - notifybiff(biffmsg); -} - -void -notifybiff(msg) - char *msg; -{ - static struct sockaddr_in addr; - static int f = -1; - struct hostent *hp; - struct servent *sp; - int len; - - if (!addr.sin_family) { - /* Be silent if biff service not available. */ - if (!(sp = getservbyname("biff", "udp"))) - return; - if (!(hp = gethostbyname("localhost"))) { - warn("localhost: %s", strerror(errno)); - return; - } - addr.sin_family = hp->h_addrtype; - memmove(&addr.sin_addr, hp->h_addr, - MIN(hp->h_length,sizeof(addr.sin_addr))); - addr.sin_port = sp->s_port; - } - if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - warn("socket: %s", strerror(errno)); - return; - } - len = strlen(msg) + 1; - if (sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)) - != len) - warn("sendto biff: %s", strerror(errno)); -} - -void -usage() -{ - eval = EX_USAGE; - err("usage: mail.local [-b] [-f from] user ..."); -} - -#if __STDC__ -void -err(const char *fmt, ...) -#else -void -err(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list ap; - -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - vwarn(fmt, ap); - va_end(ap); - - exit(eval); -} - -void -#if __STDC__ -warn(const char *fmt, ...) -#else -warn(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list ap; - -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - vwarn(fmt, ap); - va_end(ap); -} - -void -vwarn(fmt, ap) - const char *fmt; - _BSD_VA_LIST_ ap; -{ - /* - * Log the message to stderr. - * - * Don't use LOG_PERROR as an openlog() flag to do this, - * it's not portable enough. - */ - if (eval != EX_USAGE) - (void)fprintf(stderr, "mail.local: "); - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, "\n"); - - /* Log the message to syslog. */ - vsyslog(LOG_ERR, fmt, ap); -} - -/* - * e_to_sys -- - * Guess which errno's are temporary. Gag me. - */ -void -e_to_sys(num) - int num; -{ - /* Temporary failures override hard errors. */ - if (eval == EX_TEMPFAIL) - return; - - switch(num) { /* Hopefully temporary errors. */ -#ifdef EAGAIN - case EAGAIN: /* Resource temporarily unavailable */ -#endif -#ifdef EDQUOT - case EDQUOT: /* Disc quota exceeded */ -#endif -#ifdef EBUSY - case EBUSY: /* Device busy */ -#endif -#ifdef EPROCLIM - case EPROCLIM: /* Too many processes */ -#endif -#ifdef EUSERS - case EUSERS: /* Too many users */ -#endif -#ifdef ECONNABORTED - case ECONNABORTED: /* Software caused connection abort */ -#endif -#ifdef ECONNREFUSED - case ECONNREFUSED: /* Connection refused */ -#endif -#ifdef ECONNRESET - case ECONNRESET: /* Connection reset by peer */ -#endif -#ifdef EDEADLK - case EDEADLK: /* Resource deadlock avoided */ -#endif -#ifdef EFBIG - case EFBIG: /* File too large */ -#endif -#ifdef EHOSTDOWN - case EHOSTDOWN: /* Host is down */ -#endif -#ifdef EHOSTUNREACH - case EHOSTUNREACH: /* No route to host */ -#endif -#ifdef EMFILE - case EMFILE: /* Too many open files */ -#endif -#ifdef ENETDOWN - case ENETDOWN: /* Network is down */ -#endif -#ifdef ENETRESET - case ENETRESET: /* Network dropped connection on reset */ -#endif -#ifdef ENETUNREACH - case ENETUNREACH: /* Network is unreachable */ -#endif -#ifdef ENFILE - case ENFILE: /* Too many open files in system */ -#endif -#ifdef ENOBUFS - case ENOBUFS: /* No buffer space available */ -#endif -#ifdef ENOMEM - case ENOMEM: /* Cannot allocate memory */ -#endif -#ifdef ENOSPC - case ENOSPC: /* No space left on device */ -#endif -#ifdef EROFS - case EROFS: /* Read-only file system */ -#endif -#ifdef ESTALE - case ESTALE: /* Stale NFS file handle */ -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: /* Connection timed out */ -#endif -#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) - case EWOULDBLOCK: /* Operation would block. */ -#endif - eval = EX_TEMPFAIL; - break; - default: - eval = EX_UNAVAILABLE; - break; - } -} diff --git a/libexec/mail.local/pathnames.h b/libexec/mail.local/pathnames.h deleted file mode 100644 index 819734a..0000000 --- a/libexec/mail.local/pathnames.h +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 - */ -#include <paths.h> - -#define _PATH_LOCTMP "/var/tmp/local.XXXXXX" |