summaryrefslogtreecommitdiff
path: root/mail.local/mail.local.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail.local/mail.local.c')
-rw-r--r--mail.local/mail.local.c671
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;