diff options
Diffstat (limited to 'mail.local/mail.local.c')
-rw-r--r-- | mail.local/mail.local.c | 671 |
1 files changed, 515 insertions, 156 deletions
diff --git a/mail.local/mail.local.c b/mail.local/mail.local.c index e7f1211..abe1a19 100644 --- a/mail.local/mail.local.c +++ b/mail.local/mail.local.c @@ -1,34 +1,12 @@ -/*- +/* + * Copyright (c) 1998 Sendmail, Inc. All rights reserved. * 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. + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. * - * 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. */ #ifndef lint @@ -38,21 +16,22 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; +static char sccsid[] = "@(#)mail.local.c 8.83 (Berkeley) 12/17/1998"; #endif /* not lint */ /* - * This is not intended to compile on System V derived systems + * This is not intended to work on System V derived systems * such as Solaris or HP-UX, since they use a totally different * approach to mailboxes (essentially, they have a setgid program * rather than setuid, and they rely on the ability to "give away" * files to do their work). IT IS NOT A BUG that this doesn't - * compile on such architectures. + * work on such architectures. */ #include <sys/param.h> #include <sys/stat.h> #include <sys/socket.h> +#include <sys/file.h> #include <netinet/in.h> @@ -72,7 +51,7 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; #include <sysexits.h> #include <ctype.h> -#if __STDC__ +#ifdef __STDC__ #include <stdarg.h> #else #include <varargs.h> @@ -84,12 +63,37 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; # define _PATH_MAILDIR "/var/mail" #endif +#if (defined(sun) && !defined(__svr4__)) && !defined(__SVR4) +# ifdef __dead +# undef __dead +# define __dead +# endif +#endif + #if defined(_AIX) # define USE_LOCKF 1 -# define USET_SETEUID 1 +# define USE_SETEUID 1 # define USE_VSYSLOG 0 #endif +#if defined(__hpux) +# define USE_LOCKF 1 +# define USE_SETRESUID 1 +# define USE_VSYSLOG 0 +# ifdef __dead +# undef __dead +# define __dead +# endif +#endif + +#if defined(_CRAY) +# if !defined(MAXPATHLEN) +# define MAXPATHLEN PATHSIZE +# endif +# define USE_VSYSLOG 0 +# define _PATH_MAILDIR "/usr/spool/mail" +#endif + #if defined(ultrix) # define USE_VSYSLOG 0 #endif @@ -98,7 +102,7 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; # define USE_VSYSLOG 0 #endif -#if defined(NeXT) +#if defined(NeXT) && !defined(__APPLE__) # include <libc.h> # define _PATH_MAILDIR "/usr/spool/mail" # define __dead /* empty */ @@ -106,6 +110,11 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; # define S_IWUSR S_IWRITE #endif +#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# include <paths.h> +# define HASSTRERROR 1 /* has strerror(3) */ +#endif + /* * If you don't have flock, you could try using lockf instead. */ @@ -123,7 +132,7 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; # include <sys/file.h> #endif -#ifdef BSD4_4 +#if defined(BSD4_4) || defined(__GLIBC__) # include "pathnames.h" #endif @@ -146,21 +155,40 @@ static char sccsid[] = "@(#)mail.local.c 8.43 (Berkeley) 8/2/97"; #ifdef BSD4_4 # define HAS_ST_GEN 1 #else -# define _BSD_VA_LIST_ va_list +# ifndef _BSD_VA_LIST_ +# define _BSD_VA_LIST_ va_list +# endif #endif #if defined(BSD4_4) || defined(linux) # define HASSNPRINTF 1 #else -extern char *strerror __P((int)); -extern int snprintf __P((char *, size_t, const char *, ...)); +# ifndef ultrix extern FILE *fdopen __P((int, const char *)); +# endif #endif #if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) # define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ #endif +#if !HASSNPRINTF +extern int snprintf __P((char *, size_t, const char *, ...)); +# ifndef _CRAY +extern int vsnprintf __P((char *, size_t, const char *, ...)); +# endif +#endif + +#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) +# ifndef HASSTRERROR +# define HASSTRERROR 1 +# endif +#endif + +#if !HASSTRERROR +extern char *strerror __P((int)); +#endif + /* * If you don't have setreuid, and you have saved uids, and you have * a seteuid() call that doesn't try to emulate using setuid(), then @@ -170,6 +198,13 @@ extern FILE *fdopen __P((int, const char *)); # define setreuid(r, e) seteuid(e) #endif +/* + * And of course on hpux you have setresuid() + */ +#ifdef USE_SETRESUID +# define setreuid(r, e) setresuid(-1, e, -1) +#endif + #ifndef _PATH_LOCTMP # define _PATH_LOCTMP "/tmp/local.XXXXXX" #endif @@ -181,18 +216,23 @@ extern FILE *fdopen __P((int, const char *)); # define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) #endif -int eval = EX_OK; /* sysexits.h error value. */ +#ifndef MAILER_DAEMON +# define MAILER_DAEMON "MAILER-DAEMON" +#endif + +int eval = EX_OK; /* sysexits.h error value. */ +int lmtpmode = 0; +u_char tTdvect[100]; void deliver __P((int, char *)); void e_to_sys __P((int)); -__dead void err __P((const char *, ...)); void notifybiff __P((char *)); -int store __P((char *)); +int store __P((char *, int)); void usage __P((void)); void vwarn __P((const char *, _BSD_VA_LIST_)); -void warn __P((const char *, ...)); void lockmbox __P((char *)); void unlockmbox __P((void)); +void mailerr __P((const char *, const char *, ...)); int main(argc, argv) @@ -205,6 +245,7 @@ main(argc, argv) char *from; extern char *optarg; extern int optind; + extern void dolmtp __P((void)); /* make sure we have some open file descriptors */ for (fd = 10; fd < 30; fd++) @@ -220,18 +261,21 @@ main(argc, argv) #endif from = NULL; - while ((ch = getopt(argc, argv, "df:r:")) != EOF) + while ((ch = getopt(argc, argv, "df:r:l")) != EOF) switch(ch) { case 'd': /* Backward compatible. */ break; case 'f': case 'r': /* Backward compatible. */ if (from != NULL) { - warn("multiple -f options"); + mailerr(NULL, "multiple -f options"); usage(); } from = optarg; break; + case 'l': + lmtpmode++; + break; case '?': default: usage(); @@ -239,6 +283,9 @@ main(argc, argv) argc -= optind; argv += optind; + if (lmtpmode) + dolmtp(); + if (!*argv) usage(); @@ -261,16 +308,289 @@ main(argc, argv) * failures. This results in the delivery being reattempted later * at the expense of repeated failures and multiple deliveries. */ - for (fd = store(from); *argv; ++argv) + for (fd = store(from, 0); *argv; ++argv) deliver(fd, *argv); exit(eval); } +char * +parseaddr(s) + char *s; +{ + char *p; + int len; + + if (*s++ != '<') + return NULL; + + p = s; + + /* at-domain-list */ + while (*p == '@') { + p++; + if (*p == '[') { + p++; + while (isascii(*p) && + (isalnum(*p) || *p == '.' || + *p == '-' || *p == ':')) + p++; + if (*p++ != ']') + return NULL; + } else { + while ((isascii(*p) && isalnum(*p)) || + strchr(".-_", *p)) + p++; + } + if (*p == ',' && p[1] == '@') + p++; + else if (*p == ':' && p[1] != '@') + p++; + else + return NULL; + } + + s = p; + + /* local-part */ + if (*p == '\"') { + p++; + while (*p && *p != '\"') { + if (*p == '\\') { + if (!*++p) + return NULL; + } + p++; + } + if (!*p++) + return NULL; + } else { + while (*p && *p != '@' && *p != '>') { + if (*p == '\\') { + if (!*++p) + return NULL; + } else { + if (*p <= ' ' || (*p & 128) || + strchr("<>()[]\\,;:\"", *p)) + return NULL; + } + p++; + } + } + + /* @domain */ + if (*p == '@') { + p++; + if (*p == '[') { + p++; + while (isascii(*p) && + (isalnum(*p) || *p == '.' || + *p == '-' || *p == ':')) + p++; + if (*p++ != ']') + return NULL; + } else { + while ((isascii(*p) && isalnum(*p)) || + strchr(".-_", *p)) + p++; + } + } + + if (*p++ != '>') + return NULL; + if (*p && *p != ' ') + return NULL; + len = p - s - 1; + if (*s == '\0' || len <= 0) + { + s = MAILER_DAEMON; + len = strlen(s); + } + + p = malloc(len + 1); + if (p == NULL) { + printf("421 4.3.0 memory exhausted\r\n"); + exit(EX_TEMPFAIL); + } + + strncpy(p, s, len); + p[len] = '\0'; + return p; +} + +char * +process_recipient(addr) + char *addr; +{ + if (getpwnam(addr) == NULL) { + return "550 5.1.1 user unknown"; + } + + return NULL; +} + + +#define RCPT_GROW 30 + +void +dolmtp() +{ + char *return_path = NULL; + char **rcpt_addr = NULL; + int rcpt_num = 0; + int rcpt_alloc = 0; + char myhostname[1024]; + char buf[4096]; + char *err; + int msgfd; + char *p; + int i; + + gethostname(myhostname, sizeof myhostname - 1); + + printf("220 %s LMTP ready\r\n", myhostname); + for (;;) { + fflush(stdout); + if (fgets(buf, sizeof(buf)-1, stdin) == NULL) { + exit(EX_OK); + } + p = buf + strlen(buf) - 1; + if (p >= buf && *p == '\n') + *p-- = '\0'; + if (p >= buf && *p == '\r') + *p-- = '\0'; + + switch (buf[0]) { + + case 'd': + case 'D': + if (strcasecmp(buf, "data") == 0) { + if (rcpt_num == 0) { + printf("503 5.5.1 No recipients\r\n"); + continue; + } + msgfd = store(return_path, rcpt_num); + if (msgfd == -1) + continue; + + for (i = 0; i < rcpt_num; i++) { + p = strchr(rcpt_addr[i], '+'); + if (p != NULL) + *p++ = '\0'; + deliver(msgfd, rcpt_addr[i]); + } + close(msgfd); + goto rset; + } + goto syntaxerr; + + case 'l': + case 'L': + if (strncasecmp(buf, "lhlo ", 5) == 0) { + printf("250-%s\r\n250-8BITMIME\r\n250-ENHANCEDSTATUSCODES\r\n250 PIPELINING\r\n", + myhostname); + continue; + } + goto syntaxerr; + + case 'm': + case 'M': + if (strncasecmp(buf, "mail ", 5) == 0) { + if (return_path != NULL) { + printf("503 5.5.1 Nested MAIL command\r\n"); + continue; + } + if (strncasecmp(buf+5, "from:", 5) != 0 || + ((return_path = parseaddr(buf+10)) == NULL)) { + printf("501 5.5.4 Syntax error in parameters\r\n"); + continue; + } + printf("250 2.5.0 ok\r\n"); + continue; + } + goto syntaxerr; + + case 'n': + case 'N': + if (strcasecmp(buf, "noop") == 0) { + printf("250 2.0.0 ok\r\n"); + continue; + } + goto syntaxerr; + + case 'q': + case 'Q': + if (strcasecmp(buf, "quit") == 0) { + printf("221 2.0.0 bye\r\n"); + exit(EX_OK); + } + goto syntaxerr; + + case 'r': + case 'R': + if (strncasecmp(buf, "rcpt ", 5) == 0) { + if (return_path == NULL) { + printf("503 5.5.1 Need MAIL command\r\n"); + continue; + } + if (rcpt_num >= rcpt_alloc) { + rcpt_alloc += RCPT_GROW; + rcpt_addr = (char **) + realloc((char *)rcpt_addr, + rcpt_alloc * sizeof(char **)); + if (rcpt_addr == NULL) { + printf("421 4.3.0 memory exhausted\r\n"); + exit(EX_TEMPFAIL); + } + } + if (strncasecmp(buf+5, "to:", 3) != 0 || + ((rcpt_addr[rcpt_num] = parseaddr(buf+8)) == NULL)) { + printf("501 5.5.4 Syntax error in parameters\r\n"); + continue; + } + if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL) { + printf("%s\r\n", err); + continue; + } + rcpt_num++; + printf("250 2.1.5 ok\r\n"); + continue; + } + else if (strcasecmp(buf, "rset") == 0) { + printf("250 2.0.0 ok\r\n"); + + rset: + while (rcpt_num) { + free(rcpt_addr[--rcpt_num]); + } + if (return_path != NULL) + free(return_path); + return_path = NULL; + continue; + } + goto syntaxerr; + + case 'v': + case 'V': + if (strncasecmp(buf, "vrfy ", 5) == 0) { + printf("252 2.3.3 try RCPT to attempt delivery\r\n"); + continue; + } + goto syntaxerr; + + default: + syntaxerr: + printf("500 5.5.2 Syntax error\r\n"); + continue; + } + } +} + int -store(from) +store(from, lmtprcpts) char *from; + int lmtprcpts; { - FILE *fp; + FILE *fp = NULL; time_t tval; int fd, eline; char line[2048]; @@ -278,16 +598,42 @@ store(from) strcpy(tmpbuf, _PATH_LOCTMP); if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { - e_to_sys(errno); - err("unable to open temporary file"); + if (lmtprcpts) { + printf("451 4.3.0 unable to open temporary file\r\n"); + return -1; + } else { + mailerr("451 4.3.0", "unable to open temporary file"); + exit(eval); + } } (void)unlink(tmpbuf); + if (lmtpmode) { + printf("354 go ahead\r\n"); + fflush(stdout); + } + (void)time(&tval); (void)fprintf(fp, "From %s %s", from, ctime(&tval)); line[0] = '\0'; for (eline = 1; fgets(line, sizeof(line), stdin);) { + size_t line_len = strlen(line); + + if (line_len >= 2 && + line[line_len - 2] == '\r' && + line[line_len - 1] == '\n') { + strcpy(line + line_len - 2, "\n"); + } + if (lmtprcpts && line[0] == '.') { + char *src = line + 1, *dest = line; + + if (line[1] == '\n') + goto lmtpdot; + while (*src != '\0') + *dest++ = *src++; + *dest = '\0'; + } if (line[0] == '\n') eline = 1; else { @@ -298,20 +644,47 @@ store(from) } (void)fprintf(fp, "%s", line); if (ferror(fp)) { - e_to_sys(errno); - err("temporary file write error"); + if (lmtprcpts) { + while (lmtprcpts--) { + printf("451 4.3.0 temporary file write error\r\n"); + } + fclose(fp); + return -1; + } else { + mailerr("451 4.3.0", + "temporary file write error"); + fclose(fp); + exit(eval); + } } } + if (lmtprcpts) { + /* Got a premature EOF -- toss message and exit */ + exit(EX_OK); + } + /* If message not newline terminated, need an extra. */ - if (!strchr(line, '\n')) + if (strchr(line, '\n') == NULL) (void)putc('\n', fp); + + lmtpdot: + /* 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"); + if (lmtprcpts) { + while (lmtprcpts--) { + printf("451 4.3.0 temporary file write error\r\n"); + } + fclose(fp); + return -1; + } else { + mailerr("451 4.3.0", "temporary file write error"); + fclose(fp); + exit(eval); + } } return (fd); } @@ -327,15 +700,31 @@ deliver(fd, name) char *p; char biffmsg[100], buf[8*1024], path[MAXPATHLEN]; off_t curoff; + extern char *quad_to_string(); /* * Disallow delivery to unknown names -- special mailboxes can be * handled in the sendmail aliases file. */ - if (!(pw = getpwnam(name))) { + if ((pw = getpwnam(name)) == NULL) { if (eval != EX_TEMPFAIL) eval = EX_UNAVAILABLE; - warn("unknown name: %s", name); + if (lmtpmode) { + if (eval == EX_TEMPFAIL) { + printf("451 4.3.0 cannot lookup name: %s\r\n", name); + } else { + printf("550 5.1.1 unknown name: %s\r\n", name); + } + } + else { + char *errcode = NULL; + + if (eval == EX_TEMPFAIL) + errcode = "451 4.3.0"; + else + errcode = "550 5.1.1"; + mailerr(errcode, "unknown name: %s", name); + } return; } endpwent(); @@ -385,11 +774,12 @@ tryagain: lockmbox(path); if (lstat(path, &sb) < 0) { mbfd = open(path, - O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); + O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); if (lstat(path, &sb) < 0) { eval = EX_CANTCREAT; - warn("%s: lstat: file changed after open", path); + mailerr("550 5.2.0", + "%s: lstat: file changed after open", path); goto err1; } else @@ -398,25 +788,24 @@ tryagain: 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); + mailerr("451 4.3.0", "chown %u.%u: %s", + pw->pw_uid, pw->pw_gid, name); goto err1; } } else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) { - e_to_sys(errno); - warn("%s: irregular file", path); + mailerr("550 5.2.0", "%s: irregular file", path); goto err0; } else if (sb.st_uid != pw->pw_uid) { eval = EX_CANTCREAT; - warn("%s: wrong ownership (%d)", path, sb.st_uid); + mailerr("550 5.2.0", "%s: wrong ownership (%d)", + path, sb.st_uid); goto err0; } else { mbfd = open(path, O_APPEND|O_WRONLY, 0); } if (mbfd == -1) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); + mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); goto err0; } else if (fstat(mbfd, &fsb) < 0 || fsb.st_nlink != 1 || @@ -429,32 +818,34 @@ tryagain: #endif sb.st_uid != fsb.st_uid) { eval = EX_TEMPFAIL; - warn("%s: fstat: file changed after open", path); + mailerr("550 5.2.0", "%s: fstat: file changed after open", + path); goto err1; } /* 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)); + mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); goto err1; } /* Get the starting offset of the new message for biff. */ curoff = lseek(mbfd, (off_t)0, SEEK_END); - (void)snprintf(biffmsg, sizeof(biffmsg), - sizeof curoff > sizeof(long) ? "%s@%qd\n" : "%s@%ld\n", - name, curoff); + if (sizeof curoff > sizeof(long)) + (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n", + name, quad_to_string(curoff)); + else + (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\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)); + mailerr("450 4.2.0", "temporary file: %s", + strerror(errno)); goto err1; } if (setreuid(0, pw->pw_uid) < 0) { - e_to_sys(errno); - warn("setreuid(0, %d): %s (r=%d, e=%d)", + mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", pw->pw_uid, strerror(errno), getuid(), geteuid()); goto err1; } @@ -464,50 +855,56 @@ tryagain: while ((nr = read(fd, buf, sizeof(buf))) > 0) for (off = 0; off < nr; off += nw) if ((nw = write(mbfd, buf + off, nr - off)) < 0) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); + mailerr("450 4.2.0", "%s: %s", + path, strerror(errno)); goto err3; } if (nr < 0) { - e_to_sys(errno); - warn("temporary file: %s", strerror(errno)); + mailerr("450 4.2.0", "temporary file: %s", + strerror(errno)); goto err3; } /* Flush to disk, don't wait for update. */ if (fsync(mbfd)) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); + mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); err3: if (setreuid(0, 0) < 0) { +#if 0 + /* already printed an error above for this recipient */ e_to_sys(errno); - warn("setreuid(0, 0): %s", strerror(errno)); + mailerr("450 4.2.0", "setreuid(0, 0): %s", + strerror(errno)); +#endif } #ifdef DEBUG printf("reset euid = %d\n", geteuid()); #endif -err2: (void)ftruncate(mbfd, curoff); + (void)ftruncate(mbfd, curoff); err1: (void)close(mbfd); err0: unlockmbox(); return; } - + /* Close and check -- NFS doesn't write until the close. */ if (close(mbfd)) { - e_to_sys(errno); - warn("%s: %s", path, strerror(errno)); + mailerr("450 4.2.0", "%s: %s", path, strerror(errno)); truncate(path, curoff); } else notifybiff(biffmsg); if (setreuid(0, 0) < 0) { - e_to_sys(errno); - warn("setreuid(0, 0): %s", strerror(errno)); + mailerr("450 4.2.0", "setreuid(0, 0): %s", + strerror(errno)); + goto err0; } #ifdef DEBUG printf("reset euid = %d\n", geteuid()); #endif unlockmbox(); + if (lmtpmode) { + printf("250 2.1.5 %s OK\r\n", name); + } } /* @@ -530,7 +927,7 @@ lockmbox(path) return; if (strlen(path) + 6 > sizeof lockname) return; - sprintf(lockname, "%s.lock", path); + snprintf(lockname, sizeof lockname, "%s.lock", path); for (;; sleep(5)) { int fd; struct stat st; @@ -538,6 +935,8 @@ lockmbox(path) fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0); if (fd >= 0) { + /* defeat lock checking programs which test pid */ + write(fd, "0", 2); locked = 1; close(fd); return; @@ -574,12 +973,11 @@ notifybiff(msg) struct servent *sp; int len; - if (!addr.sin_family) { + if (addr.sin_family == 0) { /* Be silent if biff service not available. */ - if (!(sp = getservbyname("biff", "udp"))) + if ((sp = getservbyname("biff", "udp")) == NULL) return; - if (!(hp = gethostbyname("localhost"))) { - warn("localhost: %s", strerror(errno)); + if ((hp = gethostbyname("localhost")) == NULL) { return; } addr.sin_family = hp->h_addrtype; @@ -587,63 +985,49 @@ notifybiff(msg) 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) sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)); } void usage() { eval = EX_USAGE; - err("usage: mail.local [-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); - + mailerr(NULL, "usage: mail.local [-l] [-f from] user ..."); exit(eval); } void -#if __STDC__ -warn(const char *fmt, ...) +#ifdef __STDC__ +mailerr(const char *hdr, const char *fmt, ...) #else -warn(fmt, va_alist) +mailerr(hdr, fmt, va_alist) + const char *hdr; const char *fmt; va_dcl #endif { va_list ap; -#if __STDC__ +#ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); #endif - vwarn(fmt, ap); - va_end(ap); + if (lmtpmode) + { + if (hdr != NULL) + printf("%s ", hdr); + vprintf(fmt, ap); + printf("\r\n"); + } + else + { + e_to_sys(errno); + vwarn(fmt, ap); + } } void @@ -669,7 +1053,7 @@ vwarn(fmt, ap) { char fmtbuf[10240]; - (void) vsprintf(fmtbuf, fmt, ap); + (void) vsnprintf(fmtbuf, sizeof fmtbuf, fmt, ap); syslog(LOG_ERR, "%s", fmtbuf); } #endif @@ -768,7 +1152,7 @@ e_to_sys(num) } } -#if !defined(BSD4_4) && !defined(__osf__) +#if !HASSTRERROR char * strerror(eno) @@ -778,40 +1162,15 @@ strerror(eno) extern char *sys_errlist[]; static char ebuf[60]; - if (eno >= 0 && eno <= sys_nerr) + if (eno >= 0 && eno < sys_nerr) return sys_errlist[eno]; (void) sprintf(ebuf, "Error %d", eno); return ebuf; } -#endif /* !defined(BSD4_4) && !defined(__osf__) */ - -#if !HASSNPRINTF - -# if __STDC__ -snprintf(char *buf, size_t bufsiz, const char *fmt, ...) -# else -snprintf(buf, bufsiz, fmt, va_alist) - char *buf; - size_t bufsiz; - const char *fmt; - va_dcl -# endif -{ - va_list ap; - -# if __STDC__ - va_start(ap, fmt); -# else - va_start(ap); -# endif - vsprintf(buf, fmt, ap); - va_end(ap); -} - -#endif /* !HASSNPRINTF */ +#endif /* !HASSTRERROR */ -#ifdef ultrix +#if defined(ultrix) || defined(_CRAY) /* * Copyright (c) 1987, 1993 @@ -931,7 +1290,7 @@ _gettemp(path, doopen) if (*trv == 'z') *trv++ = 'a'; else { - if (isdigit(*trv)) + if (isascii(*trv) && isdigit(*trv)) *trv = 'a'; else ++*trv; |