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