From 6b9ce90fc59b48f8615964b69d04a200750945c3 Mon Sep 17 00:00:00 2001 From: Simon Schubert Date: Mon, 21 Sep 2009 13:16:07 +0200 Subject: [PATCH] dma: rework config parsing --- libexec/dma/conf.c | 263 +++++++++++++++++++++++++++------------------------ libexec/dma/crypto.c | 22 ++--- libexec/dma/dma.c | 55 +++++++---- libexec/dma/dma.h | 26 ++--- libexec/dma/mail.c | 4 +- libexec/dma/net.c | 51 +++++----- libexec/dma/spool.c | 12 +-- libexec/dma/util.c | 8 +- 8 files changed, 233 insertions(+), 208 deletions(-) diff --git a/libexec/dma/conf.c b/libexec/dma/conf.c index 4651ebe819..b676f9ce92 100644 --- a/libexec/dma/conf.c +++ b/libexec/dma/conf.c @@ -43,8 +43,8 @@ #include "dma.h" -#define DP ": \t\n" -#define EQS " \t\n" +#define DP ": \t" +#define EQS " \t" /* @@ -73,197 +73,210 @@ trim_line(char *line) } } -/* - * Add a virtual user entry to the list of virtual users - */ static void -add_virtuser(char *login, char *address) +chomp(char *str) { - struct virtuser *v; + size_t len = strlen(str); - v = malloc(sizeof(struct virtuser)); - v->login = strdup(login); - v->address = strdup(address); - SLIST_INSERT_HEAD(&virtusers, v, next); + if (len == 0) + return; + if (str[len - 1] == '\n') + str[len - 1] = 0; } /* * Read the virtual user table */ -int +void parse_virtuser(const char *path) { + char line[2048]; FILE *v; - char *word; char *data; - char line[2048]; + struct virtuser *vu; + int lineno = 0; v = fopen(path, "r"); - if (v == NULL) - return (-1); + if (v == NULL) { + errlog(1, "can not open virtuser file `%s'", path); + /* NOTREACHED */ + } while (!feof(v)) { if (fgets(line, sizeof(line), v) == NULL) break; - /* We hit a comment */ - if (strchr(line, '#')) - *strchr(line, '#') = 0; - if ((word = strtok(line, DP)) != NULL) { - data = strtok(NULL, DP); - if (data != NULL) { - add_virtuser(word, data); - } - } - } + lineno++; - fclose(v); - return (0); -} + chomp(line); -/* - * Add entry to the SMTP auth user list - */ -static int -add_smtp_auth_user(char *userstring, char *password) -{ - struct authuser *a; - char *temp; + /* We hit a comment */ + if (*line == '#') + continue; + /* Ignore empty lines */ + if (*line == 0) + continue; - a = malloc(sizeof(struct virtuser)); - a->password= strdup(password); + vu = calloc(1, sizeof(*vu)); + if (vu == NULL) + errlog(1, NULL); - temp = strrchr(userstring, '|'); - if (temp == NULL) - return (-1); + data = strdup(line); + vu->login = strsep(&data, DP); + vu->address = data; - a->host = strdup(temp+1); - a->login = strdup(strtok(userstring, "|")); - if (a->login == NULL) - return (-1); + if (vu->login == NULL || + vu->address == NULL) { + errlogx(1, "syntax error in virtuser file %s:%d", + path, lineno); + /* NOTREACHED */ + } - SLIST_INSERT_HEAD(&authusers, a, next); + SLIST_INSERT_HEAD(&virtusers, vu, next); + } - return (0); + fclose(v); } /* * Read the SMTP authentication config file + * + * file format is: + * user|host:password + * + * A line starting with # is treated as comment and ignored. */ -int +void parse_authfile(const char *path) { + char line[2048]; + struct authuser *au; FILE *a; - char *word; char *data; - char line[2048]; + int lineno = 0; a = fopen(path, "r"); - if (a == NULL) - return (-1); + if (a == NULL) { + errlog(1, "can not open auth file `%s'", path); + /* NOTREACHED */ + } while (!feof(a)) { if (fgets(line, sizeof(line), a) == NULL) break; + lineno++; + + chomp(line); + /* We hit a comment */ - if (strchr(line, '#')) - *strchr(line, '#') = 0; - if ((word = strtok(line, DP)) != NULL) { - data = strtok(NULL, DP); - if (data != NULL) { - if (add_smtp_auth_user(word, data) < 0) - return (-1); - } + if (*line == '#') + continue; + /* Ignore empty lines */ + if (*line == 0) + continue; + + au = calloc(1, sizeof(*au)); + if (au == NULL) + errlog(1, NULL); + + data = strdup(line); + au->login = strsep(&data, "|"); + au->host = strsep(&data, DP); + au->password = data; + + if (au->login == NULL || + au->host == NULL || + au->password == NULL) { + errlogx(1, "syntax error in authfile %s:%d", + path, lineno); + /* NOTREACHED */ } + + SLIST_INSERT_HEAD(&authusers, au, next); } fclose(a); - return (0); } /* * XXX TODO - * Check if the user supplied a value. If not, fill in default * Check for bad things[TM] */ -int +void parse_conf(const char *config_path) { char *word; char *data; FILE *conf; char line[2048]; + int lineno = 0; conf = fopen(config_path, "r"); - if (conf == NULL) - return (-1); - - /* Reset features */ - config->features = 0; + if (conf == NULL) { + /* Don't treat a non-existing config file as error */ + if (errno == ENOENT) + return; + errlog(1, "can not open config `%s'", config_path); + /* NOTREACHED */ + } while (!feof(conf)) { if (fgets(line, sizeof(line), conf) == NULL) break; + lineno++; + + chomp(line); + /* We hit a comment */ if (strchr(line, '#')) *strchr(line, '#') = 0; - if ((word = strtok(line, EQS)) != NULL) { - data = strtok(NULL, EQS); - if (strcmp(word, "SMARTHOST") == 0) { - if (data != NULL) - config->smarthost = strdup(data); - } - else if (strcmp(word, "PORT") == 0) { - if (data != NULL) - config->port = atoi(strdup(data)); - } - else if (strcmp(word, "ALIASES") == 0) { - if (data != NULL) - config->aliases = strdup(data); - } - else if (strcmp(word, "SPOOLDIR") == 0) { - if (data != NULL) - config->spooldir = strdup(data); - } - else if (strcmp(word, "VIRTPATH") == 0) { - if (data != NULL) - config->virtualpath = strdup(data); - } - else if (strcmp(word, "AUTHPATH") == 0) { - if (data != NULL) - config->authpath= strdup(data); - } - else if (strcmp(word, "CERTFILE") == 0) { - if (data != NULL) - config->certfile = strdup(data); - } - else if (strcmp(word, "MAILNAME") == 0) { - if (data != NULL) - config->mailname = strdup(data); - } - else if (strcmp(word, "MAILNAMEFILE") == 0) { - if (data != NULL) - config->mailnamefile = strdup(data); - } - else if (strcmp(word, "VIRTUAL") == 0) - config->features |= VIRTUAL; - else if (strcmp(word, "STARTTLS") == 0) - config->features |= STARTTLS; - else if (strcmp(word, "SECURETRANSFER") == 0) - config->features |= SECURETRANS; - else if (strcmp(word, "DEFER") == 0) - config->features |= DEFER; - else if (strcmp(word, "INSECURE") == 0) - config->features |= INSECURE; - else if (strcmp(word, "FULLBOUNCE") == 0) - config->features |= FULLBOUNCE; - else { - errno = EINVAL; - return (-1); - } + + data = line; + word = strsep(&data, EQS); + + /* Ignore empty lines */ + if (word == NULL || *word == 0) + continue; + + if (data != NULL && *data != 0) + data = strdup(data); + else + data = NULL; + + if (strcmp(word, "SMARTHOST") == 0 && data != NULL) + config.smarthost = data; + else if (strcmp(word, "PORT") == 0 && data != NULL) + config.port = atoi(data); + else if (strcmp(word, "ALIASES") == 0 && data != NULL) + config.aliases = data; + else if (strcmp(word, "SPOOLDIR") == 0 && data != NULL) + config.spooldir = data; + else if (strcmp(word, "VIRTPATH") == 0 && data != NULL) + config.virtualpath = data; + else if (strcmp(word, "AUTHPATH") == 0 && data != NULL) + config.authpath= data; + else if (strcmp(word, "CERTFILE") == 0 && data != NULL) + config.certfile = data; + else if (strcmp(word, "MAILNAME") == 0 && data != NULL) + config.mailname = data; + else if (strcmp(word, "MAILNAMEFILE") == 0 && data != NULL) + config.mailnamefile = data; + else if (strcmp(word, "VIRTUAL") == 0 && data == NULL) + config.features |= VIRTUAL; + else if (strcmp(word, "STARTTLS") == 0 && data == NULL) + config.features |= STARTTLS; + else if (strcmp(word, "SECURETRANSFER") == 0 && data == NULL) + config.features |= SECURETRANS; + else if (strcmp(word, "DEFER") == 0 && data == NULL) + config.features |= DEFER; + else if (strcmp(word, "INSECURE") == 0 && data == NULL) + config.features |= INSECURE; + else if (strcmp(word, "FULLBOUNCE") == 0 && data == NULL) + config.features |= FULLBOUNCE; + else { + errlogx(1, "syntax error in %s:%d", config_path, lineno); + /* NOTREACHED */ } } fclose(conf); - return (0); } - diff --git a/libexec/dma/crypto.c b/libexec/dma/crypto.c index 8a7252a953..f96797ca32 100644 --- a/libexec/dma/crypto.c +++ b/libexec/dma/crypto.c @@ -98,8 +98,8 @@ smtp_init_crypto(int fd, int feature) } /* User supplied a certificate */ - if (config->certfile != NULL) { - error = init_cert_file(ctx, config->certfile); + if (config.certfile != NULL) { + error = init_cert_file(ctx, config.certfile); if (error) { syslog(LOG_WARNING, "remote delivery deferred"); return (1); @@ -112,7 +112,7 @@ smtp_init_crypto(int fd, int feature) if (((feature & SECURETRANS) != 0) && (feature & STARTTLS) != 0) { /* TLS init phase, disable SSL_write */ - config->features |= NOSSL; + config.features |= NOSSL; send_remote_command(fd, "EHLO %s", hostname()); if (read_remote(fd, 0, NULL) == 2) { @@ -120,26 +120,26 @@ smtp_init_crypto(int fd, int feature) if (read_remote(fd, 0, NULL) != 2) { syslog(LOG_ERR, "remote delivery deferred:" " STARTTLS not available: %s", neterr); - config->features &= ~NOSSL; + config.features &= ~NOSSL; return (1); } } /* End of TLS init phase, enable SSL_write/read */ - config->features &= ~NOSSL; + config.features &= ~NOSSL; } - config->ssl = SSL_new(ctx); - if (config->ssl == NULL) { + config.ssl = SSL_new(ctx); + if (config.ssl == NULL) { syslog(LOG_NOTICE, "remote delivery deferred: SSL struct creation failed: %s", ssl_errstr()); return (1); } /* Set ssl to work in client mode */ - SSL_set_connect_state(config->ssl); + SSL_set_connect_state(config.ssl); /* Set fd for SSL in/output */ - error = SSL_set_fd(config->ssl, fd); + error = SSL_set_fd(config.ssl, fd); if (error == 0) { syslog(LOG_NOTICE, "remote delivery deferred: SSL set fd failed: %s", ssl_errstr()); @@ -147,7 +147,7 @@ smtp_init_crypto(int fd, int feature) } /* Open SSL connection */ - error = SSL_connect(config->ssl); + error = SSL_connect(config.ssl); if (error < 0) { syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s", ssl_errstr()); @@ -155,7 +155,7 @@ smtp_init_crypto(int fd, int feature) } /* Get peer certificate */ - cert = SSL_get_peer_certificate(config->ssl); + cert = SSL_get_peer_certificate(config.ssl); if (cert == NULL) { syslog(LOG_WARNING, "remote delivery deferred: Peer did not provide certificate: %s", ssl_errstr()); diff --git a/libexec/dma/dma.c b/libexec/dma/dma.c index 363d49c22b..dadf0564ec 100644 --- a/libexec/dma/dma.c +++ b/libexec/dma/dma.c @@ -56,26 +56,38 @@ #include "dma.h" - static void deliver(struct qitem *); struct aliases aliases = LIST_HEAD_INITIALIZER(aliases); struct strlist tmpfs = SLIST_HEAD_INITIALIZER(tmpfs); 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; +struct config config = { + .smarthost = NULL, + .port = 25, + .aliases = "/var/mail/aliases", + .spooldir = "/var/spool/dma", + .virtualpath = NULL, + .authpath = NULL, + .certfile = NULL, + .features = 0, + .mailname = NULL, + .mailnamefile = NULL, +}; + + static char * set_from(struct queue *queue, const char *osender) { struct virtuser *v; char *sender; - if ((config->features & VIRTUAL) != 0) { + if ((config.features & VIRTUAL) != 0) { SLIST_FOREACH(v, &virtusers, next) { if (strcmp(v->login, username) == 0) { sender = strdup(v->address); @@ -108,9 +120,16 @@ out: static int read_aliases(void) { - yyin = fopen(config->aliases, "r"); - if (yyin == NULL) - return (0); /* not fatal */ + yyin = fopen(config.aliases, "r"); + if (yyin == NULL) { + /* + * Non-existing aliases file is not a fatal error + */ + if (errno == ENOENT) + return (0); + /* Other problems are. */ + return (-1); + } if (yyparse()) return (-1); /* fatal error, probably malloc() */ fclose(yyin); @@ -459,22 +478,16 @@ skipopts: /* XXX fork root here */ - config = calloc(1, sizeof(*config)); - if (config == NULL) - errlog(1, NULL); + parse_conf(CONF_PATH); - if (parse_conf(CONF_PATH) < 0) { - free(config); - errlog(1, "can not read config file"); + if (config.features & VIRTUAL) { + if (config.virtualpath == NULL) + errlogx(1, "no virtuser file specified, but VIRTUAL configured"); + parse_virtuser(config.virtualpath); } - if (config->features & VIRTUAL) - if (parse_virtuser(config->virtualpath) < 0) - errlog(1, "can not read virtual user file `%s'", - config->virtualpath); - - if (parse_authfile(config->authpath) < 0) - errlog(1, "can not read SMTP authentication file"); + if (config.authpath != NULL) + parse_authfile(config.authpath); if (showq) { if (load_queue(&queue) < 0) @@ -491,7 +504,7 @@ skipopts: } if (read_aliases() != 0) - errlog(1, "can not read aliases file `%s'", config->aliases); + errlog(1, "can not read aliases file `%s'", config.aliases); if ((sender = set_from(&queue, sender)) == NULL) errlog(1, NULL); @@ -520,7 +533,7 @@ skipopts: /* From here on the mail is safe. */ - if (config->features & DEFER || queue_only) + if (config.features & DEFER || queue_only) return (0); run_queue(&queue); diff --git a/libexec/dma/dma.h b/libexec/dma/dma.h index cb49b65879..c96ae193cd 100644 --- a/libexec/dma/dma.h +++ b/libexec/dma/dma.h @@ -111,17 +111,19 @@ struct queue { }; struct config { - char *smarthost; + const char *smarthost; int port; - char *aliases; - char *spooldir; - char *virtualpath; - char *authpath; - char *certfile; + const char *aliases; + const char *spooldir; + const char *virtualpath; + const char *authpath; + const char *certfile; int features; + const char *mailname; + const char *mailnamefile; + + /* XXX does not belong into config */ SSL *ssl; - char *mailname; - char *mailnamefile; }; @@ -152,7 +154,7 @@ struct mx_hostentry { /* global variables */ extern struct aliases aliases; -extern struct config *config; +extern struct config config; extern struct strlist tmpfs; extern struct virtusers virtusers; extern struct authusers authusers; @@ -167,9 +169,9 @@ extern FILE *yyin; /* conf.c */ void trim_line(char *); -int parse_conf(const char *); -int parse_virtuser(const char *); -int parse_authfile(const char *); +void parse_conf(const char *); +void parse_virtuser(const char *); +void parse_authfile(const char *); /* crypto.c */ void hmac_md5(unsigned char *, int, unsigned char *, int, caddr_t); diff --git a/libexec/dma/mail.c b/libexec/dma/mail.c index 0058e89b71..8d907026ce 100644 --- a/libexec/dma/mail.c +++ b/libexec/dma/mail.c @@ -94,7 +94,7 @@ bounce(struct qitem *it, const char *reason) VERSION, hostname(), it->addr, reason, - config->features & FULLBOUNCE ? + config.features & FULLBOUNCE ? "Original message follows." : "Message headers follow."); if (error < 0) @@ -102,7 +102,7 @@ bounce(struct qitem *it, const char *reason) if (fseek(it->mailf, 0, SEEK_SET) != 0) goto fail; - if (config->features & FULLBOUNCE) { + if (config.features & FULLBOUNCE) { while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) { if (fwrite(line, 1, pos, bounceq.mailf) != pos) goto fail; diff --git a/libexec/dma/net.c b/libexec/dma/net.c index f34490c686..8b2a2c2c12 100644 --- a/libexec/dma/net.c +++ b/libexec/dma/net.c @@ -96,10 +96,10 @@ send_remote_command(int fd, const char* fmt, ...) strcat(cmd, "\r\n"); len = strlen(cmd); - if (((config->features & SECURETRANS) != 0) && - ((config->features & NOSSL) == 0)) { - while ((s = SSL_write(config->ssl, (const char*)cmd, len)) <= 0) { - s = SSL_get_error(config->ssl, s); + if (((config.features & SECURETRANS) != 0) && + ((config.features & NOSSL) == 0)) { + while ((s = SSL_write(config.ssl, (const char*)cmd, len)) <= 0) { + s = SSL_get_error(config.ssl, s); if (s != SSL_ERROR_WANT_READ && s != SSL_ERROR_WANT_WRITE) { strncpy(neterr, ssl_errstr(), sizeof(neterr)); @@ -150,9 +150,9 @@ read_remote(int fd, int extbufsize, char *extbuf) memmove(buff, buff + pos, len - pos); len -= pos; pos = 0; - if (((config->features & SECURETRANS) != 0) && - (config->features & NOSSL) == 0) { - if ((rlen = SSL_read(config->ssl, buff + len, + if (((config.features & SECURETRANS) != 0) && + (config.features & NOSSL) == 0) { + if ((rlen = SSL_read(config.ssl, buff + len, sizeof(buff) - len)) == -1) { strncpy(neterr, ssl_errstr(), sizeof(neterr)); return (-1); @@ -228,8 +228,8 @@ smtp_login(int fd, char *login, char* password) return (1); } - if ((config->features & INSECURE) != 0 || - (config->features & SECURETRANS) != 0) { + if ((config.features & INSECURE) != 0 || + (config.features & SECURETRANS) != 0) { /* Send AUTH command according to RFC 2554 */ send_remote_command(fd, "AUTH LOGIN"); if (read_remote(fd, 0, NULL) != 3) { @@ -303,12 +303,12 @@ open_connection(struct mx_hostentry *h) static void close_connection(int fd) { - if (((config->features & SECURETRANS) != 0) && - ((config->features & NOSSL) == 0)) - SSL_shutdown(config->ssl); + if (((config.features & SECURETRANS) != 0) && + ((config.features & NOSSL) == 0)) + SSL_shutdown(config.ssl); - if (config->ssl != NULL) - SSL_free(config->ssl); + if (config.ssl != NULL) + SSL_free(config.ssl); close(fd); } @@ -331,16 +331,16 @@ deliver_to_host(struct qitem *it, struct mx_hostentry *host, void *errmsgc) return (1); /* Check first reply from remote host */ - config->features |= NOSSL; + config.features |= NOSSL; res = read_remote(fd, 0, NULL); if (res != 2) { syslog(LOG_WARNING, "Invalid initial response: %i", res); return(1); } - config->features &= ~NOSSL; + config.features &= ~NOSSL; - if ((config->features & SECURETRANS) != 0) { - error = smtp_init_crypto(fd, config->features); + if ((config.features & SECURETRANS) != 0) { + error = smtp_init_crypto(fd, config.features); if (error >= 0) syslog(LOG_DEBUG, "SSL initialization successful"); else @@ -382,7 +382,7 @@ deliver_to_host(struct qitem *it, struct mx_hostentry *host, void *errmsgc) * Check if the user wants plain text login without using * encryption. */ - syslog(LOG_INFO, "using SMTP authentication"); + syslog(LOG_INFO, "using SMTP authentication for user %s", a->login); error = smtp_login(fd, a->login, a->password); if (error < 0) { syslog(LOG_ERR, "remote delivery failed:" @@ -454,7 +454,7 @@ deliver_remote(struct qitem *it, const char **errmsg) /* asprintf can't take const */ void *errmsgc = __DECONST(char **, errmsg); struct mx_hostentry *hosts, *h; - char *host; + const char *host; int port; int error = 1, smarthost = 0; @@ -472,14 +472,11 @@ deliver_remote(struct qitem *it, const char **errmsg) port = SMTP_PORT; /* Smarthost support? */ - if (config->smarthost != NULL && strlen(config->smarthost) > 0) { - syslog(LOG_INFO, "using smarthost (%s:%i)", - config->smarthost, config->port); - host = config->smarthost; + if (config.smarthost != NULL) { + host = config.smarthost; + port = config.port; + syslog(LOG_INFO, "using smarthost (%s:%i)", host, port); smarthost = 1; - - if (config->port != 0) - port = config->port; } error = dns_get_mx_list(host, port, &hosts, smarthost); diff --git a/libexec/dma/spool.c b/libexec/dma/spool.c index 0c5d50beb9..dbf0822695 100644 --- a/libexec/dma/spool.c +++ b/libexec/dma/spool.c @@ -72,7 +72,7 @@ newspoolf(struct queue *queue) struct stritem *t; int fd; - if (snprintf(fn, sizeof(fn), "%s/%s", config->spooldir, "tmp_XXXXXXXXXX") <= 0) + if (snprintf(fn, sizeof(fn), "%s/%s", config.spooldir, "tmp_XXXXXXXXXX") <= 0) return (-1); fd = mkstemp(fn); @@ -237,9 +237,9 @@ linkspool(struct queue *queue) LIST_FOREACH(it, &queue->queue, next) { if (asprintf(&it->queueid, "%s.%"PRIxPTR, queue->id, (uintptr_t)it) <= 0) goto delfiles; - if (asprintf(&it->queuefn, "%s/Q%s", config->spooldir, it->queueid) <= 0) + if (asprintf(&it->queuefn, "%s/Q%s", config.spooldir, it->queueid) <= 0) goto delfiles; - if (asprintf(&it->mailfn, "%s/M%s", config->spooldir, it->queueid) <= 0) + if (asprintf(&it->mailfn, "%s/M%s", config.spooldir, it->queueid) <= 0) goto delfiles; /* Neither file may not exist yet */ @@ -282,7 +282,7 @@ load_queue(struct queue *queue) bzero(queue, sizeof(queue)); LIST_INIT(&queue->queue); - spooldir = opendir(config->spooldir); + spooldir = opendir(config.spooldir); if (spooldir == NULL) err(1, "reading queue"); @@ -295,9 +295,9 @@ load_queue(struct queue *queue) continue; if (de->d_name[0] != 'Q') continue; - if (asprintf(&queuefn, "%s/Q%s", config->spooldir, de->d_name + 1) < 0) + if (asprintf(&queuefn, "%s/Q%s", config.spooldir, de->d_name + 1) < 0) goto fail; - if (asprintf(&mailfn, "%s/M%s", config->spooldir, de->d_name + 1) < 0) + if (asprintf(&mailfn, "%s/M%s", config.spooldir, de->d_name + 1) < 0) goto fail; if (stat(mailfn, &sb) != 0) diff --git a/libexec/dma/util.c b/libexec/dma/util.c index c66657fcbf..cf26acc60b 100644 --- a/libexec/dma/util.c +++ b/libexec/dma/util.c @@ -54,13 +54,13 @@ hostname(void) if (initialized) return (name); - if (config->mailname != NULL && config->mailname[0] != '\0') { - snprintf(name, sizeof(name), "%s", config->mailname); + 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 (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); -- 2.11.4.GIT