diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2017-07-20 18:39:17 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2017-07-20 18:39:17 +0000 |
commit | 596098ddd9b53eae29dc9c4d0fbfc839c61e0d9d (patch) | |
tree | 7f498ebe47dc52575b19083a3e8fa075f882b558 /usr.bin/newsyslog | |
parent | 2c8e98af62c1df3f3a55cb17244a98df70c76e5d (diff) |
Don't exit on invalid config lines, yet return a proper exit status.
newsyslog(8) is mainly used to proces log files, not rotating them
because of an invalid field means that /var will end up full.
Initially I wanted to ignore only getpwnam/getgrnam errors, but millert@
convinced me otherwise. malloc(3) errors are still fatal.
Diff prompted by a report from Harald Dunkel, ok millert@
Diffstat (limited to 'usr.bin/newsyslog')
-rw-r--r-- | usr.bin/newsyslog/newsyslog.8 | 6 | ||||
-rw-r--r-- | usr.bin/newsyslog/newsyslog.c | 141 |
2 files changed, 104 insertions, 43 deletions
diff --git a/usr.bin/newsyslog/newsyslog.8 b/usr.bin/newsyslog/newsyslog.8 index 2b6c4a326e1..3153250c62c 100644 --- a/usr.bin/newsyslog/newsyslog.8 +++ b/usr.bin/newsyslog/newsyslog.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: newsyslog.8,v 1.53 2015/11/14 01:22:04 jmc Exp $ +.\" $OpenBSD: newsyslog.8,v 1.54 2017/07/20 18:39:16 jca Exp $ .\" .\" Copyright (c) 1997, Jason Downs. All rights reserved. .\" @@ -41,7 +41,7 @@ .\" the suitability of this software for any purpose. It is .\" provided "as is" without express or implied warranty. .\" -.Dd $Mdocdate: November 14 2015 $ +.Dd $Mdocdate: July 20 2017 $ .Dt NEWSYSLOG 8 .Os .Sh NAME @@ -429,6 +429,8 @@ will not send a .It Pa /etc/newsyslog.conf default configuration file .El +.Sh EXIT STATUS +.Ex -std .Sh SEE ALSO .Xr compress 1 , .Xr gzip 1 , diff --git a/usr.bin/newsyslog/newsyslog.c b/usr.bin/newsyslog/newsyslog.c index 66763ff9604..7f95cb9a08e 100644 --- a/usr.bin/newsyslog/newsyslog.c +++ b/usr.bin/newsyslog/newsyslog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: newsyslog.c,v 1.104 2017/07/14 22:17:16 jca Exp $ */ +/* $OpenBSD: newsyslog.c,v 1.105 2017/07/20 18:39:16 jca Exp $ */ /* * Copyright (c) 1999, 2002, 2003 Todd C. Miller <Todd.Miller@courtesan.com> @@ -160,7 +160,7 @@ int movefile(char *, char *, uid_t, gid_t, mode_t); int stat_suffix(char *, size_t, char *, struct stat *, int (*)(const char *, struct stat *)); off_t sizefile(struct stat *); -void parse_file(struct entrylist *, int *); +int parse_file(struct entrylist *, int *); time_t parse8601(char *); time_t parseDWM(char *); void child_killer(int); @@ -179,7 +179,7 @@ main(int argc, char **argv) struct entrylist config, runlist; struct conf_entry *p, *q, *tmp; struct pidinfo *pidlist, *pl; - int status, listlen; + int status, listlen, ret; char **av; parse_args(argc, argv); @@ -192,7 +192,7 @@ main(int argc, char **argv) TAILQ_INIT(&config); TAILQ_INIT(&runlist); - parse_file(&config, &listlen); + ret = parse_file(&config, &listlen); if (argc == 0) TAILQ_CONCAT(&runlist, &config, next); else { @@ -272,7 +272,7 @@ main(int argc, char **argv) /* Wait for children to finish, then exit */ while (waitpid(-1, &status, 0) != -1) ; - exit(0); + return (ret); } void @@ -464,7 +464,7 @@ usage(void) * Parse a configuration file and build a linked list of all the logs * to process */ -void +int parse_file(struct entrylist *list, int *nentries) { char line[BUFSIZ], *parse, *q, *errline, *group, *tmp, *ep; @@ -472,7 +472,8 @@ parse_file(struct entrylist *list, int *nentries) struct passwd *pwd; struct group *grp; struct stat sb; - int lineno; + int lineno = 0; + int ret = 0; FILE *f; long l; @@ -482,7 +483,10 @@ parse_file(struct entrylist *list, int *nentries) err(1, "can't open %s", conf); *nentries = 0; - for (lineno = 1; fgets(line, sizeof(line), f); lineno++) { + +nextline: + while (fgets(line, sizeof(line), f) != NULL) { + lineno++; tmp = sob(line); if (*tmp == '\0' || *tmp == '#') continue; @@ -509,9 +513,13 @@ parse_file(struct entrylist *list, int *nentries) *group++ = '\0'; if (*q) { if (!(isnumberstr(q))) { - if ((pwd = getpwnam(q)) == NULL) - errx(1, "%s:%d: unknown user: %s", + if ((pwd = getpwnam(q)) == NULL) { + warnx("%s:%d: unknown user" + " %s --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } working->uid = pwd->pw_uid; } else working->uid = atoi(q); @@ -521,9 +529,13 @@ parse_file(struct entrylist *list, int *nentries) q = group; if (*q) { if (!(isnumberstr(q))) { - if ((grp = getgrnam(q)) == NULL) - errx(1, "%s:%d: unknown group: %s", + if ((grp = getgrnam(q)) == NULL) { + warnx("%s:%d: unknown group" + " %s --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } working->gid = grp->gr_gid; } else working->gid = atoi(q); @@ -538,15 +550,23 @@ parse_file(struct entrylist *list, int *nentries) } l = strtol(q, &ep, 8); - if (*ep != '\0' || l < 0 || l > ALLPERMS) - errx(1, "%s:%d: bad permissions: %s", conf, lineno, q); + if (*ep != '\0' || l < 0 || l > ALLPERMS) { + warnx("%s:%d: bad permissions: %s --> skipping", conf, + lineno, q); + ret = 1; + goto nextline; + } working->permissions = (mode_t)l; q = parse = missing_field(sob(++parse), errline, lineno); *(parse = son(parse)) = '\0'; l = strtol(q, &ep, 10); - if (*ep != '\0' || l < 0 || l >= INT_MAX) - errx(1, "%s:%d: bad number: %s", conf, lineno, q); + if (*ep != '\0' || l < 0 || l >= INT_MAX) { + warnx("%s:%d: bad number: %s --> skipping", conf, + lineno, q); + ret = 1; + goto nextline; + } working->numlogs = (int)l; q = parse = missing_field(sob(++parse), errline, lineno); @@ -560,23 +580,34 @@ parse_file(struct entrylist *list, int *nentries) q = parse = missing_field(sob(++parse), errline, lineno); *(parse = son(parse)) = '\0'; l = strtol(q, &ep, 10); - if (l < 0 || l >= INT_MAX) - errx(1, "%s:%d: interval out of range: %s", conf, - lineno, q); + if (l < 0 || l >= INT_MAX) { + warnx("%s:%d: interval out of range: %s --> skipping", + conf, lineno, q); + ret = 1; + goto nextline; + } working->hours = (int)l; switch (*ep) { case '\0': break; case '@': working->trim_at = parse8601(ep + 1); - if (working->trim_at == (time_t) - 1) - errx(1, "%s:%d: bad time: %s", conf, lineno, q); + if (working->trim_at == (time_t) - 1) { + warnx("%s:%d: bad time: %s --> skipping", conf, + lineno, q); + ret = 1; + goto nextline; + } working->flags |= CE_TRIMAT; break; case '$': working->trim_at = parseDWM(ep + 1); - if (working->trim_at == (time_t) - 1) - errx(1, "%s:%d: bad time: %s", conf, lineno, q); + if (working->trim_at == (time_t) - 1) { + warnx("%s:%d: bad time: %s --> skipping", conf, + lineno, q); + ret = 1; + goto nextline; + } working->flags |= CE_TRIMAT; break; case '*': @@ -584,8 +615,10 @@ parse_file(struct entrylist *list, int *nentries) break; /* FALLTHROUGH */ default: - errx(1, "%s:%d: bad interval/at: %s", conf, lineno, q); - break; + warnx("%s:%d: bad interval/at: %s --> skipping", conf, + lineno, q); + ret = 1; + goto nextline; } q = sob(++parse); /* Optional field */ @@ -611,9 +644,11 @@ parse_file(struct entrylist *list, int *nentries) working->flags |= CE_FOLLOW; break; default: - errx(1, "%s:%d: illegal flag: `%c'", + warnx("%s:%d: illegal flag: `%c'" + " --> skipping", conf, lineno, *q); - break; + ret = 1; + goto nextline; } q++; } @@ -630,9 +665,13 @@ parse_file(struct entrylist *list, int *nentries) break; if (*q == '/') { *(parse = son(parse)) = '\0'; - if (strlen(q) >= PATH_MAX) - errx(1, "%s:%d: pathname too long: %s", + if (strlen(q) >= PATH_MAX) { + warnx("%s:%d: pathname too long: %s" + " --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } working->pidfile = strdup(q); if (working->pidfile == NULL) err(1, "strdup"); @@ -655,23 +694,35 @@ parse_file(struct entrylist *list, int *nentries) break; } } - if (i == NSIG) - errx(1, "%s:%d: unknown signal: %s", + if (i == NSIG) { + warnx("%s:%d: unknown signal: %s" + " --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } } else if (working->flags & CE_MONITOR) { *(parse = son(parse)) = '\0'; working->whom = strdup(q); if (working->whom == NULL) err(1, "strdup"); - } else - errx(1, "%s:%d: unrecognized field: %s", + } else { + warnx("%s:%d: unrecognized field: %s" + " --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } } free(errline); - if ((working->flags & CE_MONITOR) && working->whom == NULL) - errx(1, "%s:%d: missing monitor notification field", + if ((working->flags & CE_MONITOR) && working->whom == NULL) { + warnx("%s:%d: missing monitor notification field" + " --> skipping", conf, lineno); + ret = 1; + goto nextline; + } /* If there is an arcdir, set working->backdir. */ if (arcdir != NULL && working->logbase != NULL) { @@ -700,20 +751,28 @@ parse_file(struct entrylist *list, int *nentries) if (working->backdir != NULL) { if (snprintf(line, sizeof(line), "%s/%s.%d%s", working->backdir, working->logbase, - working->numlogs, COMPRESS_POSTFIX) >= PATH_MAX) - errx(1, "%s:%d: pathname too long: %s", - conf, lineno, q); + working->numlogs, COMPRESS_POSTFIX) >= PATH_MAX) { + warnx("%s:%d: pathname too long: %s" + " --> skipping", conf, lineno, q); + ret = 1; + goto nextline; + } } else { if (snprintf(line, sizeof(line), "%s.%d%s", working->log, working->numlogs, COMPRESS_POSTFIX) - >= PATH_MAX) - errx(1, "%s:%d: pathname too long: %s", - conf, lineno, working->log); + >= PATH_MAX) { + warnx("%s:%d: pathname too long: %s" + " --> skipping", conf, lineno, + working->log); + ret = 1; + goto nextline; + } } TAILQ_INSERT_TAIL(list, working, next); (*nentries)++; } (void)fclose(f); + return (ret); } char * |