tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
mail.local NSS awareness (fourth patch)
Hi
I just noticed I missed a bit in the problem: mail.local defines its own
err():
void
err(int isfatal, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsyslog(LOG_ERR, fmt, ap);
va_end(ap);
if (isfatal)
exit(1);
}
So when the current implementation does the thing above, mail.local
actually returns status 1, not 0:
if (!(pw = getpwnam(name))) {
err(NOTFATAL, "unknown name: %s", name);
return(1);
}
So my claim that the message was to be silently discarded was wrong. A
DSN gets generated. I wrongly understood the issue, because when I have
been confronted to the problem, the DSN went to the original sender,
which had the same delivery failure, and it was lost.
There is still something to fix: if getpwnam() fails for a temporary
reason, mail.local should report a temporary failure, and not a
permanent one as it does today. It seems we also fire a permanent error
if a temporary file cannot be created, if we get an I/O error, or if a
memory allocation fails. That seems wrong.
In sendmail, error code handling is done here:
sendmail/libsm/stredit.c:sm_sysexmsg()
The above codes produce temporary failures, whereas all others
(including 1) cause permanent failure:
EX_OSERR
EX_IOERR
EX_TEMPFAIL
In postfix, this seems to be done here
postfix/src/global/sys_exists.c: sys_exits_table[]
The temporary failure codes are:
EX_OSERR
EX_TEMPFAIL
qmail and exim handling is not clear. If anyone is able to find where
this is done, input is welcome.
Based on this, I suggest returning EX_TEMPFAIL or EX_OSERR for non
permanent errors, and not 1. Here is my latest attempt at the problem.
While here, I renamed the mail.local specific err() into logerr(), as
the thing was quite misleading, IMO.
diff -U 4 -r1.23 mail.local.c
--- mail.local.c 27 Sep 2006 17:15:20 -0000 1.23
+++ mail.local.c 1 May 2008 06:40:01 -0000
@@ -56,16 +56,15 @@
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
+#include <sysexits.h>
-#include "pathnames.h"
-#define FATAL 1
-#define NOTFATAL 0
+#include "pathnames.h"
int deliver __P((int, char *, int));
-void err __P((int, const char *, ...))
+void logerr __P((int, const char *, ...))
__attribute__((__format__(__printf__, 2, 3)));
void notifybiff __P((char *));
int store __P((const char *));
void usage __P((void));
@@ -93,9 +92,9 @@
break;
case 'f':
case 'r': /* backward compatible */
if (from)
- err(FATAL, "multiple -f options");
+ logerr(EX_USAGE, "multiple -f options");
from = optarg;
break;
case 'l':
lockfile++;
@@ -136,11 +135,11 @@
char *tn, line[2048];
tn = strdup(_PATH_LOCTMP);
if (!tn)
- err(FATAL, "not enough core");
+ logerr(EX_OSERR, "not enough core");
if ((fd = mkstemp(tn)) == -1 || !(fp = fdopen(fd, "w+")))
- err(FATAL, "unable to open temporary file");
+ logerr(EX_OSERR, "unable to open temporary file");
(void)unlink(tn);
free(tn);
(void)time(&tval);
@@ -167,9 +166,9 @@
(void)putc('\n', fp);
(void)fflush(fp);
if (ferror(fp))
- err(FATAL, "temporary file write error");
+ logerr(EX_OSERR, "temporary file write error");
fd = dup(fd);
(void)fclose(fp);
return(fd);
}
@@ -180,21 +179,23 @@
char *name;
int lockfile;
{
struct stat sb;
- struct passwd *pw;
+ struct passwd pwres, *pw;
+ char pwbuf[1024];
int created, mbfd, nr, nw, off, rval=0, lfd=-1;
char biffmsg[100], buf[8*1024], path[MAXPATHLEN],
lpath[MAXPATHLEN];
off_t curoff;
/*
* Disallow delivery to unknown names -- special mailboxes can
be
* handled in the sendmail aliases file.
*/
- if (!(pw = getpwnam(name))) {
- err(NOTFATAL, "unknown name: %s", name);
- return(1);
- }
+ if ((getpwnam_r(name, &pwres, pwbuf, sizeof(pwbuf), &pw)) != 0)
+ logerr(EX_TEMPFAIL, "unable to find user %s: %s",
+ name, strerror(errno));
+ if (pw == NULL)
+ logerr(EX_NOUSER, "unknown name: %s", name);
(void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name);
if (lockfile) {
@@ -202,44 +203,44 @@
_PATH_MAILDIR, name);
if((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL,
S_IRUSR|S_IWUSR)) < 0) {
- err(NOTFATAL, "%s: %s", lpath, strerror(errno));
+ logerr(EX_OK, "%s: %s", lpath, strerror(errno));
return(1);
}
}
if (!(created = lstat(path, &sb)) &&
(sb.st_nlink != 1 || S_ISLNK(sb.st_mode))) {
- err(NOTFATAL, "%s: linked file", path);
+ logerr(EX_OK, "%s: linked file", path);
return(1);
}
if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
S_IRUSR|S_IWUSR)) < 0) {
if ((mbfd = open(path,
O_APPEND|O_CREAT|O_WRONLY|O_EXLOCK,
S_IRUSR|S_IWUSR)) < 0) {
- err(NOTFATAL, "%s: %s", path, strerror(errno));
+ logerr(EX_OK, "%s: %s", path, strerror(errno));
return(1);
}
}
curoff = lseek(mbfd, 0, SEEK_END);
(void)snprintf(biffmsg, sizeof biffmsg, "%s@%lld\n", name,
(long long)curoff);
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
- err(FATAL, "temporary file: %s", strerror(errno));
+ logerr(EX_OSERR, "temporary file: %s", strerror(errno));
rval = 1;
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)) < 0)
{
- err(NOTFATAL, "%s: %s", path,
strerror(errno));
+ logerr(EX_OK, "%s: %s", path,
strerror(errno));
goto trunc;
}
if (nr < 0) {
- err(FATAL, "temporary file: %s", strerror(errno));
+ logerr(EX_OSERR, "temporary file: %s", strerror(errno));
trunc: (void)ftruncate(mbfd, curoff);
rval = 1;
}
@@ -281,39 +282,40 @@
/* Be silent if biff service not available. */
if (!(sp = getservbyname("biff", "udp")))
return;
if (!(hp = gethostbyname("localhost"))) {
- err(NOTFATAL, "localhost: %s", strerror(errno));
+ logerr(EX_OK, "localhost: %s", strerror(errno));
return;
}
addr.sin_len = sizeof(struct sockaddr_in);
addr.sin_family = hp->h_addrtype;
addr.sin_port = sp->s_port;
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
}
if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- err(NOTFATAL, "socket: %s", strerror(errno));
+ logerr(EX_OK, "socket: %s", strerror(errno));
return;
}
len = strlen(msg) + 1;
if (sendto(f, msg, len, 0, (struct sockaddr *)&addr,
sizeof(addr))
!= len)
- err(NOTFATAL, "sendto biff: %s", strerror(errno));
+ logerr(EX_OK, "sendto biff: %s", strerror(errno));
}
void
usage()
{
- err(FATAL, "usage: mail.local [-l] [-f from] user ...");
+ logerr(EX_USAGE, "usage: mail.local [-l] [-f from] user ...");
}
void
-err(int isfatal, const char *fmt, ...)
+logerr(int status, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsyslog(LOG_ERR, fmt, ap);
va_end(ap);
- if (isfatal)
- exit(1);
+ if (status != EX_OK)
+ exit(status);
+ return;
}
--
Emmanuel Dreyfus
http://hcpnet.free.fr/pubz
manu%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index