From: Simon Schubert Date: Mon, 20 Jul 2009 20:48:00 +0000 (+0200) Subject: dma: always log error exits X-Git-Tag: v2.4.0~402^2~10 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/1da0a9f2a6a5790964feae86bd803c2a7eb7a6fe dma: always log error exits --- diff --git a/libexec/dma/Makefile b/libexec/dma/Makefile index 2a1f6fbefb..8d0c09f9c3 100644 --- a/libexec/dma/Makefile +++ b/libexec/dma/Makefile @@ -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 diff --git a/libexec/dma/conf.c b/libexec/dma/conf.c index 2fd22ea02b..4651ebe819 100644 --- a/libexec/dma/conf.c +++ b/libexec/dma/conf.c @@ -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); } } } diff --git a/libexec/dma/dma.c b/libexec/dma/dma.c index cc4f60be19..deb629bd98 100644 --- a/libexec/dma/dma.c +++ b/libexec/dma/dma.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -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. */ diff --git a/libexec/dma/dma.h b/libexec/dma/dma.h index c933cb5210..70e5f03dd2 100644 --- a/libexec/dma/dma.h +++ b/libexec/dma/dma.h @@ -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 diff --git a/libexec/dma/spool.c b/libexec/dma/spool.c index eb90539456..d9d17e2839 100644 --- a/libexec/dma/spool.c +++ b/libexec/dma/spool.c @@ -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 index 0000000000..c66657fcbf --- /dev/null +++ b/libexec/dma/util.c @@ -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 . + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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))); +} +