summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/mail.local/mail.local.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/mail.local/mail.local.c')
-rw-r--r--contrib/sendmail/mail.local/mail.local.c614
1 files changed, 299 insertions, 315 deletions
diff --git a/contrib/sendmail/mail.local/mail.local.c b/contrib/sendmail/mail.local/mail.local.c
index cd96c5e..8a93f01 100644
--- a/contrib/sendmail/mail.local/mail.local.c
+++ b/contrib/sendmail/mail.local/mail.local.c
@@ -10,232 +10,111 @@
*
*/
-#ifndef lint
-static char copyright[] =
+#include <sm/gen.h>
+
+SM_IDSTR(copyright,
"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1990, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* ! lint */
+ The Regents of the University of California. All rights reserved.\n")
+
+SM_IDSTR(id, "@(#)$Id: mail.local.c,v 8.235 2001/12/30 04:59:39 gshapiro Exp $")
-#ifndef lint
-static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.58 2001/06/01 05:33:31 gshapiro Exp $";
-#endif /* ! lint */
+#include <stdlib.h>
+#include <sm/errstring.h>
+#include <sm/io.h>
+#include <sm/limits.h>
+# include <unistd.h>
+# ifdef EX_OK
+# undef EX_OK /* unistd.h may have another use for this */
+# endif /* EX_OK */
+#include <sm/mbdb.h>
+#include <sm/sysexits.h>
/*
** 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"
+** approach to mailboxes (essentially, they have a set-group-ID program
+** rather than set-user-ID, and they rely on the ability to "give away"
** files to do their work). IT IS NOT A BUG that this doesn't
** work on such architectures.
*/
-/* additional mode for open() */
-# define EXTRA_MODE 0
-
-# include <sys/types.h>
-# include <sys/param.h>
-# include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <stdlib.h>
# include <sys/socket.h>
# include <sys/file.h>
-
# include <netinet/in.h>
# include <arpa/nameser.h>
-
-# include <fcntl.h>
# include <netdb.h>
-# include <pwd.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-# include <syslog.h>
-# include <time.h>
-# include <unistd.h>
-# ifdef EX_OK
-# undef EX_OK /* unistd.h may have another use for this */
-# endif /* EX_OK */
-# include <sysexits.h>
-# include <ctype.h>
+# include <pwd.h>
-# ifndef __P
-# include "sendmail/cdefs.h"
-# endif /* ! __P */
-# include "sendmail/useful.h"
-
-extern size_t strlcpy __P((char *, const char *, size_t));
-extern size_t strlcat __P((char *, const char *, size_t));
-
-# if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6)
-# ifndef HASSTRERROR
-# define HASSTRERROR 1
-# endif /* ! HASSTRERROR */
-# endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */
-
-# include "sendmail/errstring.h"
-
-# ifndef LOCKTO_RM
-# define LOCKTO_RM 300 /* timeout for stale lockfile removal */
-# endif /* ! LOCKTO_RM */
-# ifndef LOCKTO_GLOB
-# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */
-# endif /* ! LOCKTO_GLOB */
-
-# ifdef __STDC__
-# include <stdarg.h>
-# define REALLOC(ptr, size) realloc(ptr, size)
-# else /* __STDC__ */
-# include <varargs.h>
-/* define a realloc() which works for NULL pointers */
-# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size))
-# endif /* __STDC__ */
-
-# if (defined(sun) && defined(__svr4__)) || defined(__SVR4)
-# define USE_LOCKF 1
-# define USE_SETEUID 1
-# define _PATH_MAILDIR "/var/mail"
-# endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */
-
-# ifdef NCR_MP_RAS3
-# define USE_LOCKF 1
-# define HASSNPRINTF 1
-# define _PATH_MAILDIR "/var/mail"
-# endif /* NCR_MP_RAS3 */
-
-# if defined(_AIX)
-# define USE_LOCKF 1
-# define USE_SETEUID 1
-# endif /* defined(_AIX) */
-
-# if defined(__hpux)
-# define USE_LOCKF 1
-# define USE_SETRESUID 1
-# endif /* defined(__hpux) */
-
-# ifdef DGUX
-# define HASSNPRINTF 1
-# define USE_LOCKF 1
-# endif /* DGUX */
-
-# if defined(_CRAY)
-# if !defined(MAXPATHLEN)
-# define MAXPATHLEN PATHSIZE
-# endif /* !defined(MAXPATHLEN) */
-# define _PATH_MAILDIR "/usr/spool/mail"
-# endif /* defined(_CRAY) */
-
-# if defined(NeXT) && !defined(__APPLE__)
-# include <libc.h>
-# define _PATH_MAILDIR "/usr/spool/mail"
-# define S_IRUSR S_IREAD
-# define S_IWUSR S_IWRITE
-# endif /* defined(NeXT) && !defined(__APPLE__) */
-
-# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6)
-# include <paths.h>
-# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */
+#include <sm/string.h>
+#include <syslog.h>
+#include <ctype.h>
-/*
- * If you don't have flock, you could try using lockf instead.
- */
+#include <sm/conf.h>
+#include <sendmail/pathnames.h>
-# ifdef USE_LOCKF
-# define flock(a, b) lockf(a, b, 0)
-# ifdef LOCK_EX
-# undef LOCK_EX
-# endif /* LOCK_EX */
-# define LOCK_EX F_LOCK
-# endif /* USE_LOCKF */
-
-# ifndef LOCK_EX
-# include <sys/file.h>
-# endif /* ! LOCK_EX */
-
-# if defined(BSD4_4) || defined(__GLIBC__)
-# include <paths.h>
-# define _PATH_LOCTMP "/tmp/local.XXXXXX"
-# endif /* defined(BSD4_4) || defined(__GLIBC__) */
-
-# ifdef BSD4_4
-# define HAS_ST_GEN 1
-# else /* BSD4_4 */
-# ifndef _BSD_VA_LIST_
-# define _BSD_VA_LIST_ va_list
-# endif /* ! _BSD_VA_LIST_ */
-# endif /* BSD4_4 */
-
-# if defined(BSD4_4) || defined(linux)
-# define HASSNPRINTF 1
-# else /* defined(BSD4_4) || defined(linux) */
-# ifndef ultrix
-extern FILE *fdopen __P((int, const char *));
-# endif /* ! ultrix */
-# endif /* defined(BSD4_4) || defined(linux) */
-
-# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203)
-# define CONTENTLENGTH 1 /* Needs the Content-Length header */
-# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */
-
-# if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206)
-# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */
-# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */
-
-# ifdef HPUX11
-# define HASSNPRINTF 1 /* has snprintf starting in 11.X */
-# endif /* HPUX11 */
-
-# if _AIX4 >= 40300
-# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */
-# endif /* _AIX4 >= 40300 */
-
-# if !HASSNPRINTF && !SFIO
-extern int snprintf __P((char *, size_t, const char *, ...));
-# ifndef _CRAY
-extern int vsnprintf __P((char *, size_t, const char *, ...));
-# endif /* ! _CRAY */
-# endif /* !HASSNPRINTF && !SFIO */
-/*
-** 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
-** you can try defining USE_SETEUID.
-*/
+/* additional mode for open() */
+# define EXTRA_MODE 0
+
-# ifdef USE_SETEUID
-# define setreuid(r, e) seteuid(e)
-# endif /* USE_SETEUID */
+#ifndef LOCKTO_RM
+# define LOCKTO_RM 300 /* timeout for stale lockfile removal */
+#endif /* ! LOCKTO_RM */
+#ifndef LOCKTO_GLOB
+# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */
+#endif /* ! LOCKTO_GLOB */
+
+/* define a realloc() which works for NULL pointers */
+#define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size))
/*
-** And of course on hpux you have setresuid()
+** If you don't have flock, you could try using lockf instead.
*/
-# ifdef USE_SETRESUID
-# define setreuid(r, e) setresuid(-1, e, -1)
-# endif /* USE_SETRESUID */
+#ifdef LDA_USE_LOCKF
+# define flock(a, b) lockf(a, b, 0)
+# ifdef LOCK_EX
+# undef LOCK_EX
+# endif /* LOCK_EX */
+# define LOCK_EX F_LOCK
+#endif /* LDA_USE_LOCKF */
-# ifndef _PATH_LOCTMP
-# define _PATH_LOCTMP "/tmp/local.XXXXXX"
-# endif /* ! _PATH_LOCTMP */
-# ifndef _PATH_MAILDIR
-# define _PATH_MAILDIR "/var/spool/mail"
-# endif /* ! _PATH_MAILDIR */
+#ifndef LOCK_EX
+# include <sys/file.h>
+#endif /* ! LOCK_EX */
-# ifndef S_ISREG
-# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG)
-# endif /* ! S_ISREG */
+/*
+** 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
+** you can try defining LDA_USE_SETEUID.
+*/
-# ifdef MAILLOCK
-# include <maillock.h>
-# endif /* MAILLOCK */
+#ifdef LDA_USE_SETEUID
+# define setreuid(r, e) seteuid(e)
+#endif /* LDA_USE_SETEUID */
-# define U_UID pw->pw_uid
-# define U_GID pw->pw_gid
+#ifdef LDA_CONTENTLENGTH
+# define CONTENTLENGTH 1
+#endif /* LDA_CONTENTLENGTH */
#ifndef INADDRSZ
# define INADDRSZ 4 /* size of an IPv4 address in bytes */
#endif /* ! INADDRSZ */
+#ifdef MAILLOCK
+# include <maillock.h>
+#endif /* MAILLOCK */
+
#ifndef MAILER_DAEMON
# define MAILER_DAEMON "MAILER-DAEMON"
#endif /* ! MAILER_DAEMON */
@@ -246,17 +125,18 @@ off_t HeaderLength;
off_t BodyLength;
#endif /* CONTENTLENGTH */
-bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */
+bool EightBitMime = true; /* advertise 8BITMIME in LMTP */
char ErrBuf[10240]; /* error buffer */
int ExitVal = EX_OK; /* sysexits.h error value. */
-bool HoldErrs = FALSE; /* Hold errors in ErrBuf */
-bool LMTPMode = FALSE;
-bool BounceQuota = FALSE; /* permanent error when over quota */
+bool HoldErrs = false; /* Hold errors in ErrBuf */
+bool LMTPMode = false;
+bool BounceQuota = false; /* permanent error when over quota */
+char *HomeMailFile = NULL; /* store mail in homedir */
void deliver __P((int, char *));
int e_to_sys __P((int));
void notifybiff __P((char *));
-int store __P((char *, int, bool *));
+int store __P((char *, bool *));
void usage __P((void));
int lockmbox __P((char *));
void unlockmbox __P((void));
@@ -273,6 +153,8 @@ main(argc, argv)
int ch, fd;
uid_t uid;
char *from;
+ char *mbdbname = "pw";
+ int err;
extern char *optarg;
extern int optind;
@@ -291,21 +173,25 @@ main(argc, argv)
# endif /* LOG_MAIL */
from = NULL;
- while ((ch = getopt(argc, argv, "7bdf:r:l")) != -1)
+ while ((ch = getopt(argc, argv, "7bdD:f:h:r:l")) != -1)
{
switch(ch)
{
case '7': /* Do not advertise 8BITMIME */
- EightBitMime = FALSE;
+ EightBitMime = false;
break;
case 'b': /* bounce mail when over quota. */
- BounceQuota = TRUE;
+ BounceQuota = true;
break;
case 'd': /* Backward compatible. */
break;
+ case 'D': /* mailbox database type */
+ mbdbname = optarg;
+ break;
+
case 'f':
case 'r': /* Backward compatible. */
if (from != NULL)
@@ -316,8 +202,18 @@ main(argc, argv)
from = optarg;
break;
+ case 'h':
+ if (optarg != NULL || *optarg != '\0')
+ HomeMailFile = optarg;
+ else
+ {
+ mailerr(NULL, "-h: missing filename");
+ usage();
+ }
+ break;
+
case 'l':
- LMTPMode = TRUE;
+ LMTPMode = true;
break;
case '?':
@@ -331,6 +227,19 @@ main(argc, argv)
/* initialize biff structures */
notifybiff(NULL);
+ err = sm_mbdb_initialize(mbdbname);
+ if (err != EX_OK)
+ {
+ char *errcode = "521";
+
+ if (err == EX_TEMPFAIL)
+ errcode = "421";
+
+ mailerr(errcode, "Can not open mailbox database %s: %s",
+ mbdbname, sm_strexit(err));
+ exit(err);
+ }
+
if (LMTPMode)
{
extern void dolmtp __P((void));
@@ -357,7 +266,6 @@ main(argc, argv)
*/
uid = getuid();
-
if (from == NULL && ((from = getlogin()) == NULL ||
(pw = getpwnam(from)) == NULL ||
pw->pw_uid != uid))
@@ -373,9 +281,9 @@ main(argc, argv)
** at the expense of repeated failures and multiple deliveries.
*/
- HoldErrs = TRUE;
- fd = store(from, 0, NULL);
- HoldErrs = FALSE;
+ HoldErrs = true;
+ fd = store(from, NULL);
+ HoldErrs = false;
if (fd < 0)
{
flush_error();
@@ -467,6 +375,8 @@ parseaddr(s, rcpt)
s = MAILER_DAEMON;
l = strlen(s) + 1;
+ if (l < 0)
+ return NULL;
p = malloc(l);
if (p == NULL)
{
@@ -474,7 +384,7 @@ parseaddr(s, rcpt)
exit(EX_TEMPFAIL);
}
- (void) strlcpy(p, s, l);
+ (void) sm_strlcpy(p, s, l);
return p;
}
@@ -482,9 +392,22 @@ char *
process_recipient(addr)
char *addr;
{
- if (getpwnam(addr) == NULL)
+ SM_MBDB_T user;
+
+ switch (sm_mbdb_lookup(addr, &user))
+ {
+ case EX_OK:
+ return NULL;
+
+ case EX_NOUSER:
return "550 5.1.1 User unknown";
- return NULL;
+
+ case EX_TEMPFAIL:
+ return "451 4.3.0 User database failure; retry later";
+
+ default:
+ return "550 5.3.0 User database failure";
+ }
}
#define RCPT_GROW 30
@@ -496,7 +419,7 @@ dolmtp()
char **rcpt_addr = NULL;
int rcpt_num = 0;
int rcpt_alloc = 0;
- bool gotlhlo = FALSE;
+ bool gotlhlo = false;
char *err;
int msgfd;
char *p;
@@ -507,7 +430,7 @@ dolmtp()
memset(myhostname, '\0', sizeof myhostname);
(void) gethostname(myhostname, sizeof myhostname - 1);
if (myhostname[0] == '\0')
- strlcpy(myhostname, "localhost", sizeof myhostname);
+ sm_strlcpy(myhostname, "localhost", sizeof myhostname);
printf("220 %s LMTP ready\r\n", myhostname);
for (;;)
@@ -525,18 +448,18 @@ dolmtp()
{
case 'd':
case 'D':
- if (strcasecmp(buf, "data") == 0)
+ if (sm_strcasecmp(buf, "data") == 0)
{
- bool inbody = FALSE;
+ bool inbody = false;
if (rcpt_num == 0)
{
mailerr("503 5.5.1", "No recipients");
continue;
}
- HoldErrs = TRUE;
- msgfd = store(return_path, rcpt_num, &inbody);
- HoldErrs = FALSE;
+ HoldErrs = true;
+ msgfd = store(return_path, &inbody);
+ HoldErrs = false;
if (msgfd < 0 && !inbody)
{
flush_error();
@@ -566,7 +489,7 @@ dolmtp()
case 'l':
case 'L':
- if (strncasecmp(buf, "lhlo ", 5) == 0)
+ if (sm_strncasecmp(buf, "lhlo ", 5) == 0)
{
/* check for duplicate per RFC 1651 4.2 */
if (gotlhlo)
@@ -575,7 +498,7 @@ dolmtp()
myhostname);
continue;
}
- gotlhlo = TRUE;
+ gotlhlo = true;
printf("250-%s\r\n", myhostname);
if (EightBitMime)
printf("250-8BITMIME\r\n");
@@ -589,7 +512,7 @@ dolmtp()
case 'm':
case 'M':
- if (strncasecmp(buf, "mail ", 5) == 0)
+ if (sm_strncasecmp(buf, "mail ", 5) == 0)
{
if (return_path != NULL)
{
@@ -597,9 +520,9 @@ dolmtp()
"Nested MAIL command");
continue;
}
- if (strncasecmp(buf+5, "from:", 5) != 0 ||
+ if (sm_strncasecmp(buf+5, "from:", 5) != 0 ||
((return_path = parseaddr(buf + 10,
- FALSE)) == NULL))
+ false)) == NULL))
{
mailerr("501 5.5.4",
"Syntax error in parameters");
@@ -614,7 +537,7 @@ dolmtp()
case 'n':
case 'N':
- if (strcasecmp(buf, "noop") == 0)
+ if (sm_strcasecmp(buf, "noop") == 0)
{
printf("250 2.0.0 Ok\r\n");
continue;
@@ -625,7 +548,7 @@ dolmtp()
case 'q':
case 'Q':
- if (strcasecmp(buf, "quit") == 0)
+ if (sm_strcasecmp(buf, "quit") == 0)
{
printf("221 2.0.0 Bye\r\n");
exit(EX_OK);
@@ -636,7 +559,7 @@ dolmtp()
case 'r':
case 'R':
- if (strncasecmp(buf, "rcpt ", 5) == 0)
+ if (sm_strncasecmp(buf, "rcpt ", 5) == 0)
{
if (return_path == NULL)
{
@@ -658,9 +581,9 @@ dolmtp()
exit(EX_TEMPFAIL);
}
}
- if (strncasecmp(buf + 5, "to:", 3) != 0 ||
+ if (sm_strncasecmp(buf + 5, "to:", 3) != 0 ||
((rcpt_addr[rcpt_num] = parseaddr(buf + 8,
- TRUE)) == NULL))
+ true)) == NULL))
{
mailerr("501 5.5.4",
"Syntax error in parameters");
@@ -676,7 +599,7 @@ dolmtp()
printf("250 2.1.5 Ok\r\n");
continue;
}
- else if (strcasecmp(buf, "rset") == 0)
+ else if (sm_strcasecmp(buf, "rset") == 0)
{
printf("250 2.0.0 Ok\r\n");
@@ -694,7 +617,7 @@ rset:
case 'v':
case 'V':
- if (strncasecmp(buf, "vrfy ", 5) == 0)
+ if (sm_strncasecmp(buf, "vrfy ", 5) == 0)
{
printf("252 2.3.3 Try RCPT to attempt delivery\r\n");
continue;
@@ -714,25 +637,24 @@ rset:
}
int
-store(from, lmtprcpts, inbody)
+store(from, inbody)
char *from;
- int lmtprcpts;
bool *inbody;
{
FILE *fp = NULL;
time_t tval;
- bool eline;
- bool fullline = TRUE; /* current line is terminated */
+ bool eline; /* previous line was empty */
+ bool fullline = true; /* current line is terminated */
bool prevfl; /* previous line was terminated */
char line[2048];
int fd;
char tmpbuf[sizeof _PATH_LOCTMP + 1];
if (inbody != NULL)
- *inbody = FALSE;
+ *inbody = false;
(void) umask(0077);
- (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf);
+ (void) sm_strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf);
if ((fd = mkstemp(tmpbuf)) < 0 || (fp = fdopen(fd, "w+")) == NULL)
{
mailerr("451 4.3.0", "Unable to open temporary file");
@@ -746,7 +668,7 @@ store(from, lmtprcpts, inbody)
(void) fflush(stdout);
}
if (inbody != NULL)
- *inbody = TRUE;
+ *inbody = true;
(void) time(&tval);
(void) fprintf(fp, "From %s %s", from, ctime(&tval));
@@ -757,7 +679,7 @@ store(from, lmtprcpts, inbody)
#endif /* CONTENTLENGTH */
line[0] = '\0';
- eline = TRUE;
+ eline = true;
while (fgets(line, sizeof(line), stdin) != (char *) NULL)
{
size_t line_len = 0;
@@ -779,7 +701,7 @@ store(from, lmtprcpts, inbody)
}
/* Check to see if we have the full line from fgets() */
- fullline = FALSE;
+ fullline = false;
if (line_len > 0)
{
if (line[line_len - 1] == '\n')
@@ -791,7 +713,7 @@ store(from, lmtprcpts, inbody)
line[line_len - 1] = '\0';
line_len--;
}
- fullline = TRUE;
+ fullline = true;
}
else if (line[line_len - 1] == '\r')
{
@@ -800,19 +722,19 @@ store(from, lmtprcpts, inbody)
if (peek == '\n')
{
line[line_len - 1] = '\n';
- fullline = TRUE;
+ fullline = true;
}
else
(void) ungetc(peek, stdin);
}
}
else
- fullline = TRUE;
+ fullline = true;
#ifdef CONTENTLENGTH
if (prevfl && line[0] == '\n' && HeaderLength == 0)
{
- eline = FALSE;
+ eline = false;
if (fp != NULL)
HeaderLength = ftell(fp);
if (HeaderLength <= 0)
@@ -827,7 +749,7 @@ store(from, lmtprcpts, inbody)
}
#else /* CONTENTLENGTH */
if (prevfl && line[0] == '\n')
- eline = TRUE;
+ eline = true;
#endif /* CONTENTLENGTH */
else
{
@@ -835,12 +757,12 @@ store(from, lmtprcpts, inbody)
fp != NULL &&
!memcmp(line, "From ", 5))
(void) putc('>', fp);
- eline = FALSE;
+ eline = false;
#ifdef CONTENTLENGTH
/* discard existing "Content-Length:" headers */
if (prevfl && HeaderLength == 0 &&
(line[0] == 'C' || line[0] == 'c') &&
- strncasecmp(line, ContentHdr, 15) == 0)
+ sm_strncasecmp(line, ContentHdr, 15) == 0)
{
/*
** be paranoid: clear the line
@@ -895,15 +817,10 @@ store(from, lmtprcpts, inbody)
if (HeaderLength > 0 && BodyLength >= 0)
{
- extern char *quad_to_string();
-
- if (sizeof BodyLength > sizeof(long))
- snprintf(line, sizeof line, "%s\n",
- quad_to_string(BodyLength));
- else
- snprintf(line, sizeof line, "%ld\n",
- (long) BodyLength);
- strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16);
+ (void) sm_snprintf(line, sizeof line, "%lld\n",
+ (LONGLONG_T) BodyLength);
+ (void) sm_strlcpy(&ContentHdr[16], line,
+ sizeof(ContentHdr) - 16);
}
else
BodyLength = -1; /* Something is wrong here */
@@ -930,9 +847,9 @@ deliver(fd, name)
{
struct stat fsb;
struct stat sb;
- struct passwd *pw;
char path[MAXPATHLEN];
int mbfd = -1, nr = 0, nw, off;
+ int exitval;
char *p;
char *errcode;
off_t curoff;
@@ -941,26 +858,42 @@ deliver(fd, name)
int readamount;
#endif /* CONTENTLENGTH */
char biffmsg[100], buf[8*1024];
- extern char *quad_to_string();
-
+ SM_MBDB_T user;
/*
** Disallow delivery to unknown names -- special mailboxes can be
** handled in the sendmail aliases file.
*/
- if ((pw = getpwnam(name)) == NULL)
+ exitval = sm_mbdb_lookup(name, &user);
+ switch (exitval)
{
- if (ExitVal == EX_TEMPFAIL)
- errcode = "451 4.3.0";
- else
- {
- ExitVal = EX_UNAVAILABLE;
- errcode = "550 5.1.1";
- }
- mailerr(errcode, "Unknown name: %s", name);
+ case EX_OK:
+ break;
+
+ case EX_NOUSER:
+ exitval = EX_UNAVAILABLE;
+ mailerr("550 5.1.1", "%s: User unknown", name);
+ break;
+
+ case EX_TEMPFAIL:
+ mailerr("451 4.3.0", "%s: User database failure; retry later",
+ name);
+ break;
+
+ default:
+ exitval = EX_UNAVAILABLE;
+ mailerr("550 5.3.0", "%s: User database failure", name);
+ break;
+ }
+
+ if (exitval != EX_OK)
+ {
+ if (ExitVal != EX_TEMPFAIL)
+ ExitVal = exitval;
return;
}
+
endpwent();
/*
@@ -982,7 +915,29 @@ deliver(fd, name)
}
- (void) snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name);
+ if (HomeMailFile == NULL)
+ {
+ if (sm_snprintf(path, sizeof(path), "%s/%s",
+ _PATH_MAILDIR, name) >= sizeof(path))
+ {
+ exitval = EX_UNAVAILABLE;
+ mailerr("550 5.1.1", "%s: Invalid mailbox path", name);
+ return;
+ }
+ }
+ else if (*user.mbdb_homedir == '\0')
+ {
+ exitval = EX_UNAVAILABLE;
+ mailerr("550 5.1.1", "%s: User missing home directory", name);
+ return;
+ }
+ else if (sm_snprintf(path, sizeof(path), "%s/%s",
+ user.mbdb_homedir, HomeMailFile) >= sizeof(path))
+ {
+ exitval = EX_UNAVAILABLE;
+ mailerr("550 5.1.1", "%s: Invalid mailbox path", name);
+ return;
+ }
/*
@@ -1024,7 +979,7 @@ tryagain:
errcode = "551 5.3.0";
mailerr(errcode, "lockmailbox %s failed; error code %d %s",
- p, off, errno > 0 ? errstring(errno) : "");
+ p, off, errno > 0 ? sm_errstring(errno) : "");
return;
}
@@ -1032,7 +987,7 @@ tryagain:
{
int save_errno;
int mode = S_IRUSR|S_IWUSR;
- gid_t gid = U_GID;
+ gid_t gid = user.mbdb_gid;
#ifdef MAILGID
(void) umask(0007);
@@ -1058,13 +1013,13 @@ tryagain:
/* open failed, don't try again */
mailerr("450 4.2.0", "%s: %s", path,
- errstring(save_errno));
+ sm_errstring(save_errno));
goto err0;
}
- else if (fchown(mbfd, U_UID, gid) < 0)
+ else if (fchown(mbfd, user.mbdb_uid, gid) < 0)
{
mailerr("451 4.3.0", "chown %u.%u: %s",
- U_UID, gid, name);
+ user.mbdb_uid, gid, name);
goto err1;
}
else
@@ -1076,7 +1031,7 @@ tryagain:
** is no longer valid; better safe than sorry.
*/
- sb.st_uid = U_UID;
+ sb.st_uid = user.mbdb_uid;
(void) close(mbfd);
mbfd = -1;
}
@@ -1086,28 +1041,29 @@ tryagain:
mailerr("550 5.2.0", "%s: irregular file", path);
goto err0;
}
- else if (sb.st_uid != U_UID)
+ else if (sb.st_uid != user.mbdb_uid)
{
ExitVal = EX_CANTCREAT;
mailerr("550 5.2.0", "%s: wrong ownership (%d)",
- path, sb.st_uid);
+ path, (int) sb.st_uid);
goto err0;
}
/* change UID for quota checks */
- if (setreuid(0, U_UID) < 0)
+ if (setreuid(0, user.mbdb_uid) < 0)
{
mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)",
- U_UID, errstring(errno), getuid(), geteuid());
+ (int) user.mbdb_uid, sm_errstring(errno),
+ (int) getuid(), (int) geteuid());
goto err1;
}
#ifdef DEBUG
- fprintf(stderr, "new euid = %d\n", geteuid());
+ fprintf(stderr, "new euid = %d\n", (int) geteuid());
#endif /* DEBUG */
mbfd = open(path, O_APPEND|O_WRONLY|EXTRA_MODE, 0);
if (mbfd < 0)
{
- mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
+ mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno));
goto err0;
}
else if (fstat(mbfd, &fsb) < 0 ||
@@ -1127,32 +1083,65 @@ tryagain:
goto err1;
}
+#if 0
+ /*
+ ** This code could be reused if we decide to add a
+ ** per-user quota field to the sm_mbdb interface.
+ */
+
+ /*
+ ** Fail if the user has a quota specified, and delivery of this
+ ** message would exceed that quota. We bounce such failures using
+ ** EX_UNAVAILABLE, unless there were internal problems, since
+ ** storing immense messages for later retries can cause queueing
+ ** issues.
+ */
+
+ if (ui.quota > 0)
+ {
+ struct stat dsb;
+
+ if (fstat(fd, &dsb) < 0)
+ {
+ ExitVal = EX_TEMPFAIL;
+ mailerr("451 4.3.0",
+ "%s: fstat: can't stat temporary storage: %s",
+ ui.mailspool, sm_errstring(errno));
+ goto err1;
+ }
+
+ if (dsb.st_size + sb.st_size + 1 > ui.quota)
+ {
+ ExitVal = EX_UNAVAILABLE;
+ mailerr("551 5.2.2",
+ "%s: Mailbox full or quota exceeded",
+ ui.mailspool);
+ goto err1;
+ }
+ }
+#endif /* 0 */
/* Wait until we can get a lock on the file. */
if (flock(mbfd, LOCK_EX) < 0)
{
- mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
+ mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno));
goto err1;
}
/* Get the starting offset of the new message for biff. */
curoff = lseek(mbfd, (off_t) 0, SEEK_END);
- 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, (long) curoff);
+ (void) sm_snprintf(biffmsg, sizeof(biffmsg), "%s@%lld\n",
+ name, (LONGLONG_T) curoff);
/* Copy the message into the file. */
if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1)
{
mailerr("450 4.2.0", "Temporary file: %s",
- errstring(errno));
+ sm_errstring(errno));
goto err1;
}
#ifdef DEBUG
- fprintf(stderr, "before writing: euid = %d\n", geteuid());
+ fprintf(stderr, "before writing: euid = %d\n", (int) geteuid());
#endif /* DEBUG */
#ifdef CONTENTLENGTH
headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ;
@@ -1160,7 +1149,7 @@ tryagain:
{
if (headerbytes == 0)
{
- snprintf(buf, sizeof buf, "%s", ContentHdr);
+ (void) sm_snprintf(buf, sizeof buf, "%s", ContentHdr);
nr = strlen(buf);
headerbytes = -1;
readamount = 0;
@@ -1190,7 +1179,7 @@ tryagain:
errcode = "552 5.2.2";
#endif /* EDQUOT */
mailerr(errcode, "%s: %s",
- path, errstring(errno));
+ path, sm_errstring(errno));
goto err3;
}
}
@@ -1198,18 +1187,18 @@ tryagain:
if (nr < 0)
{
mailerr("450 4.2.0", "Temporary file: %s",
- errstring(errno));
+ sm_errstring(errno));
goto err3;
}
/* Flush to disk, don't wait for update. */
if (fsync(mbfd) < 0)
{
- mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
+ mailerr("450 4.2.0", "%s: %s", path, sm_errstring(errno));
err3:
(void) setreuid(0, 0);
#ifdef DEBUG
- fprintf(stderr, "reset euid = %d\n", geteuid());
+ fprintf(stderr, "reset euid = %d\n", (int) geteuid());
#endif /* DEBUG */
(void) ftruncate(mbfd, curoff);
err1: if (mbfd >= 0)
@@ -1226,7 +1215,7 @@ err0: unlockmbox();
if (errno == EDQUOT && BounceQuota)
errcode = "552 5.2.2";
#endif /* EDQUOT */
- mailerr(errcode, "%s: %s", path, errstring(errno));
+ mailerr(errcode, "%s: %s", path, sm_errstring(errno));
(void) truncate(path, curoff);
}
else
@@ -1235,11 +1224,11 @@ err0: unlockmbox();
if (setreuid(0, 0) < 0)
{
mailerr("450 4.2.0", "setreuid(0, 0): %s",
- errstring(errno));
+ sm_errstring(errno));
goto err0;
}
#ifdef DEBUG
- fprintf(stderr, "reset euid = %d\n", geteuid());
+ fprintf(stderr, "reset euid = %d\n", (int) geteuid());
#endif /* DEBUG */
unlockmbox();
if (LMTPMode)
@@ -1253,7 +1242,7 @@ err0: unlockmbox();
** EPA 11/94.
*/
-bool Locked = FALSE;
+bool Locked = false;
#ifdef MAILLOCK
int
@@ -1266,7 +1255,7 @@ lockmbox(name)
return 0;
if ((r = maillock(name, 15)) == L_SUCCESS)
{
- Locked = TRUE;
+ Locked = true;
return 0;
}
switch (r)
@@ -1293,7 +1282,7 @@ unlockmbox()
{
if (Locked)
mailunlock();
- Locked = FALSE;
+ Locked = false;
}
#else /* MAILLOCK */
@@ -1310,7 +1299,7 @@ lockmbox(path)
return 0;
if (strlen(path) + 6 > sizeof LockName)
return EX_SOFTWARE;
- (void) snprintf(LockName, sizeof LockName, "%s.lock", path);
+ (void) sm_snprintf(LockName, sizeof LockName, "%s.lock", path);
(void) time(&start);
for (; ; sleep(5))
{
@@ -1330,7 +1319,7 @@ lockmbox(path)
{
/* defeat lock checking programs which test pid */
(void) write(fd, "0", 2);
- Locked = TRUE;
+ Locked = true;
(void) close(fd);
return 0;
}
@@ -1360,7 +1349,7 @@ unlockmbox()
if (!Locked)
return;
(void) unlink(LockName);
- Locked = FALSE;
+ Locked = false;
}
#endif /* MAILLOCK */
@@ -1368,7 +1357,7 @@ void
notifybiff(msg)
char *msg;
{
- static bool initialized = FALSE;
+ static bool initialized = false;
static int f = -1;
struct hostent *hp;
struct servent *sp;
@@ -1377,7 +1366,7 @@ notifybiff(msg)
if (!initialized)
{
- initialized = TRUE;
+ initialized = true;
/* Be silent if biff service not available. */
if ((sp = getservbyname("biff", "udp")) == NULL ||
@@ -1408,11 +1397,12 @@ void
usage()
{
ExitVal = EX_USAGE;
- mailerr(NULL, "usage: mail.local [-7] [-b] [-l] [-f from] user ...");
+ mailerr(NULL, "usage: mail.local [-7] [-b] [-d] [-l] [-f from|-r from] [-h filename] user ...");
exit(ExitVal);
}
void
+/*VARARGS2*/
#ifdef __STDC__
mailerr(const char *hdr, const char *fmt, ...)
#else /* __STDC__ */
@@ -1423,25 +1413,19 @@ mailerr(hdr, fmt, va_alist)
#endif /* __STDC__ */
{
size_t len = 0;
- va_list ap;
+ SM_VA_LOCAL_DECL
(void) e_to_sys(errno);
-#ifdef __STDC__
- va_start(ap, fmt);
-#else /* __STDC__ */
- va_start(ap);
-#endif /* __STDC__ */
+ SM_VA_START(ap, fmt);
- if (LMTPMode)
+ if (LMTPMode && hdr != NULL)
{
- if (hdr != NULL)
- {
- snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr);
- len = strlen(ErrBuf);
- }
+ sm_snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr);
+ len = strlen(ErrBuf);
}
- (void) vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap);
+ (void) sm_vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap);
+ SM_VA_END(ap);
if (!HoldErrs)
flush_error();
@@ -1630,7 +1614,7 @@ _gettemp(path, doopen)
extern int errno;
register char *start, *trv;
struct stat sbuf;
- u_int pid;
+ unsigned int pid;
pid = getpid();
for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
OpenPOWER on IntegriCloud