dma: always log error exits
authorSimon Schubert <corecode@dragonflybsd.org>
Mon, 20 Jul 2009 20:48:00 +0000 (22:48 +0200)
committerSimon Schubert <corecode@dragonflybsd.org>
Tue, 21 Jul 2009 22:13:15 +0000 (00:13 +0200)
libexec/dma/Makefile
libexec/dma/conf.c
libexec/dma/dma.c
libexec/dma/dma.h
libexec/dma/spool.c
libexec/dma/util.c [new file with mode: 0644]

index 2a1f6fb..8d0c09f 100644 (file)
@@ -7,7 +7,7 @@ DPADD=  ${LIBSSL} ${LIBCRYPTO}
 LDADD=  -lssl -lcrypto
 
 PROG=  dma
-SRCS=  base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c
+SRCS=  base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c util.c
 MAN=   dma.8
 
 BINOWN= root
index 2fd22ea..4651ebe 100644 (file)
@@ -123,7 +123,7 @@ parse_virtuser(const char *path)
 /*
  * Add entry to the SMTP auth user list
  */
-static void
+static int
 add_smtp_auth_user(char *userstring, char *password)
 {
        struct authuser *a;
@@ -134,15 +134,16 @@ add_smtp_auth_user(char *userstring, char *password)
 
        temp = strrchr(userstring, '|');
        if (temp == NULL)
-               errx(1, "auth.conf file in wrong format");
-               /* XXX don't use errx */
+               return (-1);
 
        a->host = strdup(temp+1);
        a->login = strdup(strtok(userstring, "|"));
        if (a->login == NULL)
-               errx(1, "auth.conf file in wrong format");
+               return (-1);
 
        SLIST_INSERT_HEAD(&authusers, a, next);
+
+       return (0);
 }
 
 /*
@@ -169,7 +170,8 @@ parse_authfile(const char *path)
                if ((word = strtok(line, DP)) != NULL) {
                        data = strtok(NULL, DP);
                        if (data != NULL) {
-                               add_smtp_auth_user(word, data);
+                               if (add_smtp_auth_user(word, data) < 0)
+                                       return (-1);
                        }
                }
        }
index cc4f60b..deb629b 100644 (file)
@@ -43,7 +43,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
-#include <netdb.h>
 #include <paths.h>
 #include <pwd.h>
 #include <signal.h>
@@ -66,114 +65,9 @@ struct virtusers virtusers = LIST_HEAD_INITIALIZER(virtusers);
 struct authusers authusers = LIST_HEAD_INITIALIZER(authusers);
 struct config *config;
 const char *username;
+const char *logident_base;
 
 static int daemonize = 1;
-static const char *logident_base;
-
-const char *
-hostname(void)
-{
-       static char name[MAXHOSTNAMELEN+1];
-       int initialized = 0;
-       FILE *fp;
-       size_t len;
-
-       if (initialized)
-               return (name);
-
-       if (config->mailname != NULL && config->mailname[0] != '\0') {
-               snprintf(name, sizeof(name), "%s", config->mailname);
-               initialized = 1;
-               return (name);
-       }
-       if (config->mailnamefile != NULL && config->mailnamefile[0] != '\0') {
-               fp = fopen(config->mailnamefile, "r");
-               if (fp != NULL) {
-                       if (fgets(name, sizeof(name), fp) != NULL) {
-                               len = strlen(name);
-                               while (len > 0 &&
-                                   (name[len - 1] == '\r' ||
-                                    name[len - 1] == '\n'))
-                                       name[--len] = '\0';
-                               if (name[0] != '\0') {
-                                       initialized = 1;
-                                       return (name);
-                               }
-                       }
-                       fclose(fp);
-               }
-       }
-       if (gethostname(name, sizeof(name)) != 0)
-               strcpy(name, "(unknown hostname)");
-       initialized = 1;
-       return name;
-}
-
-static void
-setlogident(const char *fmt, ...)
-{
-       char *tag = NULL;
-
-       if (fmt != NULL) {
-               va_list ap;
-               char *sufx;
-
-               va_start(ap, fmt);
-               vasprintf(&sufx, fmt, ap);
-               if (sufx != NULL) {
-                       asprintf(&tag, "%s[%s]", logident_base, sufx);
-                       free(sufx);
-               }
-               va_end(ap);
-       }
-       closelog();
-       openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
-}
-
-static const char *
-check_username(const char *name, uid_t ckuid)
-{
-       struct passwd *pwd;
-
-       if (name == NULL)
-               return (NULL);
-       pwd = getpwnam(name);
-       if (pwd == NULL || pwd->pw_uid != ckuid)
-               return (NULL);
-       return (name);
-}
-
-static void
-set_username(void)
-{
-       struct passwd *pwd;
-       char *u = NULL;
-       uid_t uid;
-
-       uid = getuid();
-       username = check_username(getlogin(), uid);
-       if (username != NULL)
-               return;
-       username = check_username(getenv("LOGNAME"), uid);
-       if (username != NULL)
-               return;
-       username = check_username(getenv("USER"), uid);
-       if (username != NULL)
-               return;
-       pwd = getpwuid(uid);
-       if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0' &&
-           (u = strdup(pwd->pw_name)) != NULL) {
-               username = check_username(u, uid);
-               if (username != NULL)
-                       return;
-               else
-                       free(u);
-       }
-       asprintf(__DECONST(void *, &username), "%ld", (long)uid);
-       if (username != NULL)
-               return;
-       username = "unknown-or-invalid-username";
-}
 
 static char *
 set_from(const char *osender)
@@ -290,67 +184,6 @@ out:
        return (-1);
 }
 
-static void
-deltmp(void)
-{
-       struct stritem *t;
-
-       SLIST_FOREACH(t, &tmpfs, next) {
-               unlink(t->str);
-       }
-}
-
-int
-open_locked(const char *fname, int flags, ...)
-{
-       int mode = 0;
-
-       if (flags & O_CREAT) {
-               va_list ap;
-               va_start(ap, flags);
-               mode = va_arg(ap, int);
-               va_end(ap);
-       }
-
-#ifndef O_EXLOCK
-       int fd, save_errno;
-
-       fd = open(fname, flags, mode);
-       if (fd < 0)
-               return(fd);
-       if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
-               save_errno = errno;
-               close(fd);
-               errno = save_errno;
-               return(-1);
-       }
-       return(fd);
-#else
-       return(open(fname, flags|O_EXLOCK, mode));
-#endif
-}
-
-static char *
-rfc822date(void)
-{
-       static char str[50];
-       size_t error;
-       time_t now;
-
-       now = time(NULL);
-       error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
-                      localtime(&now));
-       if (error == 0)
-               strcpy(str, "(date fail)");
-       return (str);
-}
-
-static int
-strprefixcmp(const char *str, const char *prefix)
-{
-       return (strncasecmp(str, prefix, strlen(prefix)));
-}
-
 static int
 readmail(struct queue *queue, const char *sender, int nodot)
 {
@@ -774,57 +607,59 @@ skipopts:
 
        config = calloc(1, sizeof(*config));
        if (config == NULL)
-               err(1, NULL);
+               errlog(1, NULL);
 
        if (parse_conf(CONF_PATH) < 0) {
                free(config);
-               err(1, "can not read config file");
+               errlog(1, "can not read config file");
        }
 
        if (config->features & VIRTUAL)
                if (parse_virtuser(config->virtualpath) < 0)
-                       err(1, "can not read virtual user file `%s'",
+                       errlog(1, "can not read virtual user file `%s'",
                                config->virtualpath);
 
        if (parse_authfile(config->authpath) < 0)
-               err(1, "can not read SMTP authentication file");
+               errlog(1, "can not read SMTP authentication file");
 
        if (showq) {
-               load_queue(&lqueue);
+               if (load_queue(&lqueue) < 0)
+                       errlog(1, "can not load queue");
                show_queue(&lqueue);
                return (0);
        }
 
        if (doqueue) {
-               load_queue(&lqueue);
+               if (load_queue(&lqueue) < 0)
+                       errlog(1, "can not load queue");
                run_queue(&lqueue);
                return (0);
        }
 
        if (read_aliases() != 0)
-               err(1, "can not read aliases file `%s'", config->aliases);
+               errlog(1, "can not read aliases file `%s'", config->aliases);
 
        if ((sender = set_from(sender)) == NULL)
-               err(1, NULL);
+               errlog(1, NULL);
 
        for (i = 0; i < argc; i++) {
                if (add_recp(&queue, argv[i], sender, 1) != 0)
-                       errx(1, "invalid recipient `%s'", argv[i]);
+                       errlogx(1, "invalid recipient `%s'", argv[i]);
        }
 
        if (LIST_EMPTY(&queue.queue))
-               errx(1, "no recipients");
+               errlogx(1, "no recipients");
 
        if (newspoolf(&queue, sender) != 0)
-               err(1, "can not create temp file");
+               errlog(1, "can not create temp file");
 
        setlogident("%s", queue.id);
 
        if (readmail(&queue, sender, nodot) != 0)
-               err(1, "can not read mail");
+               errlog(1, "can not read mail");
 
        if (linkspool(&queue, sender) != 0)
-               err(1, "can not create spools");
+               errlog(1, "can not create spools");
 
        /* From here on the mail is safe. */
 
index c933cb5..70e5f03 100644 (file)
@@ -144,6 +144,7 @@ extern struct strlist tmpfs;
 extern struct virtusers virtusers;
 extern struct authusers authusers;
 extern const char *username;
+extern const char *logident_base;
 
 extern char neterr[BUF_SIZE];
 
@@ -173,18 +174,28 @@ int base64_encode(const void *, int, char **);
 int base64_decode(const char *, void *);
 
 /* dma.c */
-int open_locked(const char *, int, ...);
 int add_recp(struct queue *, const char *, const char *, int);
-const char *hostname(void);
 
 /* spool.c */
 int newspoolf(struct queue *, const char *);
 int linkspool(struct queue *, const char *);
-void load_queue(struct queue *);
+int load_queue(struct queue *);
 void delqueue(struct qitem *);
 int aquirespool(struct qitem *);
 void dropspool(struct queue *, struct qitem *);
 
 /* local.c */
 int deliver_local(struct qitem *, const char **errmsg);
+
+/* util.c */
+const char *hostname(void);
+void setlogident(const char *, ...);
+void errlog(int, const char *, ...);
+void errlogx(int, const char *, ...);
+void set_username(void);
+void deltmp(void);
+int open_locked(const char *, int, ...);
+char *rfc822date(void);
+int strprefixcmp(const char *, const char *);
+
 #endif
index eb90539..d9d17e2 100644 (file)
@@ -177,13 +177,13 @@ linkspool(struct queue *queue, const char *sender)
 
 delfiles:
        LIST_FOREACH(it, &queue->queue, next) {
-               unlink(it->queuefn);
                unlink(it->mailfn);
+               unlink(it->queuefn);
        }
        return (-1);
 }
 
-void
+int
 load_queue(struct queue *queue)
 {
        struct qitem *it;
@@ -269,7 +269,7 @@ load_queue(struct queue *queue)
                continue;
 
 skip_item:
-               warn("reading queue: `%s'", queuefn);
+               syslog(LOG_INFO, "could not pick up queue file: `%s'/`%s': %m", queuefn, mailfn);
                if (sender != NULL)
                        free(sender);
                if (queuefn != NULL)
@@ -284,17 +284,17 @@ skip_item:
                        fclose(mailf);
        }
        closedir(spooldir);
-       return;
+       return (0);
 
 fail:
-       err(1, "reading queue");
+       return (-1);
 }
 
 void
 delqueue(struct qitem *it)
 {
-       unlink(it->queuefn);
        unlink(it->mailfn);
+       unlink(it->queuefn);
        if (it->queuef != NULL)
                fclose(it->queuef);
        if (it->mailf != NULL)
@@ -310,19 +310,23 @@ aquirespool(struct qitem *it)
        if (it->queuef == NULL) {
                queuefd = open_locked(it->queuefn, O_RDWR);
                if (queuefd < 0)
-                       return (-1);
+                       goto fail;
                it->queuef = fdopen(queuefd, "r+");
                if (it->queuef == NULL)
-                       return (-1);
+                       goto fail;
        }
 
        if (it->mailf == NULL) {
                it->mailf = fopen(it->mailfn, "r");
                if (it->mailf == NULL)
-                       return (-1);
+                       goto fail;
        }
 
        return (0);
+
+fail:
+       syslog(LOG_INFO, "could not aquire queue file: %m");
+       return (-1);
 }
 
 void
diff --git a/libexec/dma/util.c b/libexec/dma/util.c
new file mode 100644 (file)
index 0000000..c66657f
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
+ *
+ * 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. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "dma.h"
+
+const char *
+hostname(void)
+{
+       static char name[MAXHOSTNAMELEN+1];
+       int initialized = 0;
+       FILE *fp;
+       size_t len;
+
+       if (initialized)
+               return (name);
+
+       if (config->mailname != NULL && config->mailname[0] != '\0') {
+               snprintf(name, sizeof(name), "%s", config->mailname);
+               initialized = 1;
+               return (name);
+       }
+       if (config->mailnamefile != NULL && config->mailnamefile[0] != '\0') {
+               fp = fopen(config->mailnamefile, "r");
+               if (fp != NULL) {
+                       if (fgets(name, sizeof(name), fp) != NULL) {
+                               len = strlen(name);
+                               while (len > 0 &&
+                                   (name[len - 1] == '\r' ||
+                                    name[len - 1] == '\n'))
+                                       name[--len] = '\0';
+                               if (name[0] != '\0') {
+                                       initialized = 1;
+                                       return (name);
+                               }
+                       }
+                       fclose(fp);
+               }
+       }
+       if (gethostname(name, sizeof(name)) != 0)
+               strcpy(name, "(unknown hostname)");
+       initialized = 1;
+       return name;
+}
+
+void
+setlogident(const char *fmt, ...)
+{
+       char *tag = NULL;
+
+       if (fmt != NULL) {
+               va_list ap;
+               char *sufx;
+
+               va_start(ap, fmt);
+               vasprintf(&sufx, fmt, ap);
+               if (sufx != NULL) {
+                       asprintf(&tag, "%s[%s]", logident_base, sufx);
+                       free(sufx);
+               }
+               va_end(ap);
+       }
+       closelog();
+       openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
+}
+
+void
+errlog(int exitcode, const char *fmt, ...)
+{
+       int oerrno = errno;
+       va_list ap;
+       char *outs = NULL;
+
+       if (fmt != NULL) {
+               va_start(ap, fmt);
+               vasprintf(&outs, fmt, ap);
+               va_end(ap);
+       }
+
+       if (outs != NULL) {
+               syslog(LOG_ERR, "%s: %m", outs);
+               fprintf(stderr, "%s: %s: %s\n", getprogname(), outs, strerror(oerrno));
+       } else {
+               syslog(LOG_ERR, "%m");
+               fprintf(stderr, "%s: %s\n", getprogname(), strerror(oerrno));
+       }
+
+       exit(exitcode);
+}
+
+void
+errlogx(int exitcode, const char *fmt, ...)
+{
+       va_list ap;
+       char *outs = NULL;
+
+       if (fmt != NULL) {
+               va_start(ap, fmt);
+               vasprintf(&outs, fmt, ap);
+               va_end(ap);
+       }
+
+       if (outs != NULL) {
+               syslog(LOG_ERR, "%s", outs);
+               fprintf(stderr, "%s: %s\n", getprogname(), outs);
+       } else {
+               syslog(LOG_ERR, "Unknown error");
+               fprintf(stderr, "%s: Unknown error\n", getprogname());
+       }
+
+       exit(exitcode);
+}
+
+static const char *
+check_username(const char *name, uid_t ckuid)
+{
+       struct passwd *pwd;
+
+       if (name == NULL)
+               return (NULL);
+       pwd = getpwnam(name);
+       if (pwd == NULL || pwd->pw_uid != ckuid)
+               return (NULL);
+       return (name);
+}
+
+void
+set_username(void)
+{
+       struct passwd *pwd;
+       char *u = NULL;
+       uid_t uid;
+
+       uid = getuid();
+       username = check_username(getlogin(), uid);
+       if (username != NULL)
+               return;
+       username = check_username(getenv("LOGNAME"), uid);
+       if (username != NULL)
+               return;
+       username = check_username(getenv("USER"), uid);
+       if (username != NULL)
+               return;
+       pwd = getpwuid(uid);
+       if (pwd != NULL && pwd->pw_name != NULL && pwd->pw_name[0] != '\0' &&
+           (u = strdup(pwd->pw_name)) != NULL) {
+               username = check_username(u, uid);
+               if (username != NULL)
+                       return;
+               else
+                       free(u);
+       }
+       asprintf(__DECONST(void *, &username), "%ld", (long)uid);
+       if (username != NULL)
+               return;
+       username = "unknown-or-invalid-username";
+}
+
+void
+deltmp(void)
+{
+       struct stritem *t;
+
+       SLIST_FOREACH(t, &tmpfs, next) {
+               unlink(t->str);
+       }
+}
+
+int
+open_locked(const char *fname, int flags, ...)
+{
+       int mode = 0;
+
+       if (flags & O_CREAT) {
+               va_list ap;
+               va_start(ap, flags);
+               mode = va_arg(ap, int);
+               va_end(ap);
+       }
+
+#ifndef O_EXLOCK
+       int fd, save_errno;
+
+       fd = open(fname, flags, mode);
+       if (fd < 0)
+               return(fd);
+       if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
+               save_errno = errno;
+               close(fd);
+               errno = save_errno;
+               return(-1);
+       }
+       return(fd);
+#else
+       return(open(fname, flags|O_EXLOCK, mode));
+#endif
+}
+
+char *
+rfc822date(void)
+{
+       static char str[50];
+       size_t error;
+       time_t now;
+
+       now = time(NULL);
+       error = strftime(str, sizeof(str), "%a, %d %b %Y %T %z",
+                      localtime(&now));
+       if (error == 0)
+               strcpy(str, "(date fail)");
+       return (str);
+}
+
+int
+strprefixcmp(const char *str, const char *prefix)
+{
+       return (strncasecmp(str, prefix, strlen(prefix)));
+}
+