mirror of
https://github.com/openbsd/src.git
synced 2026-04-23 21:54:32 +00:00
Use sysexits.h exit values to distinguish between tempfail and permfail.
Unix MTAs use the exit value of the MDA (here mail.local) to determine whether or not a failure to deliver mail should be considered to be a temporary or permanent failure. OK semarie@ beck@
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: lockspool.c,v 1.20 2019/01/25 00:19:26 millert Exp $ */
|
||||
/* $OpenBSD: lockspool.c,v 1.21 2020/02/09 14:59:20 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Theo de Raadt <deraadt@theos.com>
|
||||
@@ -63,7 +63,7 @@ main(int argc, char *argv[])
|
||||
if (argc != 1 && argc != 2)
|
||||
usage();
|
||||
if (argc == 2 && getuid() != 0)
|
||||
merr(FATAL, "you must be root to lock someone else's spool");
|
||||
merr(1, "you must be root to lock someone else's spool");
|
||||
|
||||
signal(SIGTERM, unhold);
|
||||
signal(SIGINT, unhold);
|
||||
@@ -114,5 +114,5 @@ void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
merr(FATAL, "usage: %s [username]", __progname);
|
||||
merr(1, "usage: %s [username]", __progname);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: locking.c,v 1.13 2020/02/02 23:17:09 millert Exp $ */
|
||||
/* $OpenBSD: locking.c,v 1.14 2020/02/09 14:59:20 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com>
|
||||
@@ -96,8 +96,7 @@ getlock(const char *name, struct passwd *pw)
|
||||
break;
|
||||
again:
|
||||
if (tries > 10) {
|
||||
merr(NOTFATAL, "%s: %s", lpath,
|
||||
strerror(errno));
|
||||
mwarn("%s: %s", lpath, strerror(errno));
|
||||
seteuid(0);
|
||||
return(-1);
|
||||
}
|
||||
@@ -129,7 +128,7 @@ again:
|
||||
S_IRUSR|S_IWUSR)) != -1)
|
||||
break;
|
||||
if (tries > 9) {
|
||||
merr(NOTFATAL, "%s: %s", lpath, strerror(errno));
|
||||
mwarn("%s: %s", lpath, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
sleep(1U << tries);
|
||||
@@ -154,19 +153,27 @@ baditem(char *path)
|
||||
if (rename(path, npath) == -1)
|
||||
unlink(npath);
|
||||
else
|
||||
merr(NOTFATAL, "nasty spool item %s renamed to %s",
|
||||
path, npath);
|
||||
mwarn("nasty spool item %s renamed to %s", path, npath);
|
||||
/* XXX if we fail to rename, another attempt will happen later */
|
||||
}
|
||||
|
||||
void
|
||||
merr(int isfatal, const char *fmt, ...)
|
||||
mwarn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsyslog(LOG_ERR, fmt, ap);
|
||||
va_end(ap);
|
||||
if (isfatal)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
merr(int eval, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsyslog(LOG_ERR, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mail.local.c,v 1.38 2020/02/07 02:27:37 millert Exp $ */
|
||||
/* $OpenBSD: mail.local.c,v 1.39 2020/02/09 14:59:20 millert Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com>
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sysexits.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
@@ -69,7 +70,7 @@ main(int argc, char *argv[])
|
||||
case 'f':
|
||||
case 'r': /* backward compatible */
|
||||
if (from)
|
||||
merr(FATAL, "multiple -f options");
|
||||
merr(EX_USAGE, "multiple -f options");
|
||||
from = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
@@ -98,8 +99,10 @@ main(int argc, char *argv[])
|
||||
from = (pw = getpwuid(uid)) ? pw->pw_name : "???";
|
||||
|
||||
fd = storemail(from);
|
||||
for (eval = 0; *argv; ++argv)
|
||||
eval |= deliver(fd, *argv, lockfile);
|
||||
for (eval = 0; *argv; ++argv) {
|
||||
if ((ch = deliver(fd, *argv, lockfile)) != 0)
|
||||
eval = ch;
|
||||
}
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
@@ -113,9 +116,9 @@ storemail(char *from)
|
||||
char *line, *tbuf;
|
||||
|
||||
if ((tbuf = strdup(_PATH_LOCTMP)) == NULL)
|
||||
merr(FATAL, "unable to allocate memory");
|
||||
merr(EX_OSERR, "unable to allocate memory");
|
||||
if ((fd = mkstemp(tbuf)) == -1 || !(fp = fdopen(fd, "w+")))
|
||||
merr(FATAL, "unable to open temporary file");
|
||||
merr(EX_OSERR, "unable to open temporary file");
|
||||
(void)unlink(tbuf);
|
||||
free(tbuf);
|
||||
|
||||
@@ -129,7 +132,7 @@ storemail(char *from)
|
||||
else {
|
||||
/* No trailing newline, so alloc space and copy */
|
||||
if ((tbuf = malloc(len + 1)) == NULL)
|
||||
merr(FATAL, "unable to allocate memory");
|
||||
merr(EX_OSERR, "unable to allocate memory");
|
||||
memcpy(tbuf, line, len);
|
||||
tbuf[len] = '\0';
|
||||
line = tbuf;
|
||||
@@ -152,7 +155,7 @@ storemail(char *from)
|
||||
(void)putc('\n', fp);
|
||||
(void)fflush(fp);
|
||||
if (ferror(fp))
|
||||
merr(FATAL, "temporary file write error");
|
||||
merr(EX_OSERR, "temporary file write error");
|
||||
return(fd);
|
||||
}
|
||||
|
||||
@@ -161,7 +164,7 @@ deliver(int fd, char *name, int lockfile)
|
||||
{
|
||||
struct stat sb, fsb;
|
||||
struct passwd *pw;
|
||||
int mbfd=-1, rval=1, lfd=-1;
|
||||
int mbfd=-1, lfd=-1, rval=EX_OSERR;
|
||||
char biffmsg[100], buf[8*1024], path[PATH_MAX];
|
||||
off_t curoff;
|
||||
size_t off;
|
||||
@@ -172,8 +175,8 @@ deliver(int fd, char *name, int lockfile)
|
||||
* handled in the sendmail aliases file.
|
||||
*/
|
||||
if (!(pw = getpwnam(name))) {
|
||||
merr(NOTFATAL, "unknown name: %s", name);
|
||||
return(1);
|
||||
mwarn("unknown name: %s", name);
|
||||
return(EX_NOUSER);
|
||||
}
|
||||
|
||||
(void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name);
|
||||
@@ -181,14 +184,14 @@ deliver(int fd, char *name, int lockfile)
|
||||
if (lockfile) {
|
||||
lfd = lockspool(name, pw);
|
||||
if (lfd == -1)
|
||||
return (1);
|
||||
return(EX_OSERR);
|
||||
}
|
||||
|
||||
/* after this point, always exit via bad to remove lockfile */
|
||||
retry:
|
||||
if (lstat(path, &sb)) {
|
||||
if (errno != ENOENT) {
|
||||
merr(NOTFATAL, "%s: %s", path, strerror(errno));
|
||||
mwarn("%s: %s", path, strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
if ((mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|O_EXLOCK,
|
||||
@@ -197,7 +200,8 @@ retry:
|
||||
/* file appeared since lstat */
|
||||
goto retry;
|
||||
} else {
|
||||
merr(NOTFATAL, "%s: %s", path, strerror(errno));
|
||||
mwarn("%s: %s", path, strerror(errno));
|
||||
rval = EX_CANTCREAT;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -208,32 +212,32 @@ retry:
|
||||
* was a reason for doing so.
|
||||
*/
|
||||
if (fchown(mbfd, pw->pw_uid, pw->pw_gid) == -1) {
|
||||
merr(NOTFATAL, "chown %u:%u: %s",
|
||||
pw->pw_uid, pw->pw_gid, name);
|
||||
mwarn("chown %u:%u: %s", pw->pw_uid, pw->pw_gid, name);
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) {
|
||||
merr(NOTFATAL, "%s: linked or special file", path);
|
||||
mwarn("%s: linked or special file", path);
|
||||
goto bad;
|
||||
}
|
||||
if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
|
||||
S_IRUSR|S_IWUSR)) == -1) {
|
||||
merr(NOTFATAL, "%s: %s", path, strerror(errno));
|
||||
mwarn("%s: %s", path, strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
if (fstat(mbfd, &fsb) == -1) {
|
||||
/* relating error to path may be bad style */
|
||||
merr(NOTFATAL, "%s: %s", path, strerror(errno));
|
||||
mwarn("%s: %s", path, strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) {
|
||||
merr(NOTFATAL, "%s: changed after open", path);
|
||||
mwarn("%s: changed after open", path);
|
||||
goto bad;
|
||||
}
|
||||
/* paranoia? */
|
||||
if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) {
|
||||
merr(NOTFATAL, "%s: linked or special file", path);
|
||||
mwarn("%s: linked or special file", path);
|
||||
rval = EX_CANTCREAT;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -241,14 +245,14 @@ retry:
|
||||
curoff = lseek(mbfd, 0, SEEK_END);
|
||||
(void)snprintf(biffmsg, sizeof biffmsg, "%s@%lld\n", name, curoff);
|
||||
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
||||
merr(NOTFATAL, "temporary file: %s", strerror(errno));
|
||||
mwarn("temporary file: %s", strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
while ((nr = read(fd, buf, sizeof(buf))) > 0)
|
||||
for (off = 0; off < nr; off += nw)
|
||||
if ((nw = write(mbfd, buf + off, nr - off)) == -1) {
|
||||
merr(NOTFATAL, "%s: %s", path, strerror(errno));
|
||||
mwarn("%s: %s", path, strerror(errno));
|
||||
(void)ftruncate(mbfd, curoff);
|
||||
goto bad;
|
||||
}
|
||||
@@ -257,7 +261,7 @@ retry:
|
||||
rval = 0;
|
||||
} else {
|
||||
(void)ftruncate(mbfd, curoff);
|
||||
merr(FATAL, "temporary file: %s", strerror(errno));
|
||||
mwarn("temporary file: %s", strerror(errno));
|
||||
}
|
||||
|
||||
bad:
|
||||
@@ -292,8 +296,7 @@ notifybiff(char *msg)
|
||||
if (error) {
|
||||
/* Be silent if biff service not available. */
|
||||
if (error != EAI_SERVICE) {
|
||||
merr(NOTFATAL, "localhost: %s",
|
||||
gai_strerror(error));
|
||||
mwarn("localhost: %s", gai_strerror(error));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -308,13 +311,13 @@ notifybiff(char *msg)
|
||||
}
|
||||
}
|
||||
if (f == -1) {
|
||||
merr(NOTFATAL, "socket: %s", strerror(errno));
|
||||
mwarn("socket: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
len = strlen(msg) + 1; /* XXX */
|
||||
if (sendto(f, msg, len, 0, res->ai_addr, res->ai_addrlen) != len)
|
||||
merr(NOTFATAL, "sendto biff: %s", strerror(errno));
|
||||
mwarn("sendto biff: %s", strerror(errno));
|
||||
}
|
||||
|
||||
static int lockfd = -1;
|
||||
@@ -331,21 +334,21 @@ lockspool(const char *name, struct passwd *pw)
|
||||
|
||||
/* If not privileged, open pipe to lockspool(1) instead */
|
||||
if (pipe2(pfd, O_CLOEXEC) == -1) {
|
||||
merr(FATAL, "pipe: %s", strerror(errno));
|
||||
merr(EX_OSERR, "pipe: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
switch ((lockpid = fork())) {
|
||||
case -1:
|
||||
merr(FATAL, "fork: %s", strerror(errno));
|
||||
merr(EX_OSERR, "fork: %s", strerror(errno));
|
||||
return -1;
|
||||
case 0:
|
||||
/* child */
|
||||
close(pfd[0]);
|
||||
dup2(pfd[1], STDOUT_FILENO);
|
||||
execl(_PATH_LOCKSPOOL, "lockspool", (char *)NULL);
|
||||
merr(FATAL, "execl: lockspool: %s", strerror(errno));
|
||||
merr(EX_OSERR, "execl: lockspool: %s", strerror(errno));
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
default:
|
||||
@@ -357,7 +360,7 @@ lockspool(const char *name, struct passwd *pw)
|
||||
|
||||
if (read(lockfd, &ch, 1) != 1 || ch != '1') {
|
||||
unlockspool();
|
||||
merr(FATAL, "lockspool: unable to get lock");
|
||||
merr(EX_OSERR, "lockspool: unable to get lock");
|
||||
}
|
||||
|
||||
return lockfd;
|
||||
@@ -379,5 +382,5 @@ unlockspool(void)
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
merr(FATAL, "usage: mail.local [-Ll] [-f from] user ...");
|
||||
merr(EX_USAGE, "usage: mail.local [-Ll] [-f from] user ...");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mail.local.h,v 1.6 2020/02/02 23:17:09 millert Exp $ */
|
||||
/* $OpenBSD: mail.local.h,v 1.7 2020/02/09 14:59:21 millert Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
@@ -29,12 +29,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define FATAL 1
|
||||
#define NOTFATAL 0
|
||||
|
||||
void baditem(char *);
|
||||
int deliver(int, char *, int);
|
||||
void merr(int, const char *, ...);
|
||||
void mwarn(const char *, ...);
|
||||
int getlock(const char *, struct passwd *);
|
||||
void notifybiff(char *);
|
||||
void rellock(void);
|
||||
|
||||
Reference in New Issue
Block a user