newsyslog(8): make configuration parser more robust.
Currently newsyslog supports <include> directive that is used in our default /etc/newsyslog.conf in the following form: <include> /usr/local/etc/newsyslog.conf.d/* While this is suitable for ports installing their own rules for logs rotation, this also makes newsyslog break entire processing of all files if it encounters single line it cannot parse. This includes lines referring to nonexistent username/group for log ownership, so newsyslog stops calling errx() function in the parser. With this fix, newsyslog uses warnx() instead of errx() in such cases to print a warning, recover gracefully and continue with execution. Among other cases, this unbreaks initial creation of log files having flag "C" at boot time (newsyslog -CN). This is most important for systems having RAM-based /var file system like nanobsd(8)-based that rely on newsyslog to bring system log files into existence. MFC after: 1 month
This commit is contained in:
parent
a9c7e6bd61
commit
01cf0a1724
@ -1078,9 +1078,11 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
|
||||
q = parse = missing_field(sob(line), errline);
|
||||
parse = son(line);
|
||||
if (!*parse)
|
||||
errx(1, "malformed line (missing fields):\n%s",
|
||||
if (!*parse) {
|
||||
warnx("malformed line (missing fields):\n%s",
|
||||
errline);
|
||||
continue;
|
||||
}
|
||||
*parse = '\0';
|
||||
|
||||
/*
|
||||
@ -1132,22 +1134,24 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
continue;
|
||||
}
|
||||
|
||||
#define badline(msg, ...) do { \
|
||||
warnx(msg, __VA_ARGS__); \
|
||||
goto cleanup; \
|
||||
} while (0)
|
||||
|
||||
special = 0;
|
||||
working = init_entry(q, NULL);
|
||||
if (strcasecmp(DEFAULT_MARKER, q) == 0) {
|
||||
special = 1;
|
||||
if (*defconf_p != NULL) {
|
||||
warnx("Ignoring duplicate entry for %s!", q);
|
||||
free_entry(working);
|
||||
continue;
|
||||
}
|
||||
if (*defconf_p != NULL)
|
||||
badline("Ignoring duplicate entry for %s!", q);
|
||||
*defconf_p = working;
|
||||
}
|
||||
|
||||
q = parse = missing_field(sob(parse + 1), errline);
|
||||
parse = son(parse);
|
||||
if (!*parse)
|
||||
errx(1, "malformed line (missing fields):\n%s",
|
||||
badline("malformed line (missing fields):\n%s",
|
||||
errline);
|
||||
*parse = '\0';
|
||||
if ((group = strchr(q, ':')) != NULL ||
|
||||
@ -1156,7 +1160,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
if (*q) {
|
||||
if (!(isnumberstr(q))) {
|
||||
if ((pwd = getpwnam(q)) == NULL)
|
||||
errx(1,
|
||||
badline(
|
||||
"error in config file; unknown user:\n%s",
|
||||
errline);
|
||||
working->uid = pwd->pw_uid;
|
||||
@ -1169,7 +1173,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
if (*q) {
|
||||
if (!(isnumberstr(q))) {
|
||||
if ((grp = getgrnam(q)) == NULL)
|
||||
errx(1,
|
||||
badline(
|
||||
"error in config file; unknown group:\n%s",
|
||||
errline);
|
||||
working->gid = grp->gr_gid;
|
||||
@ -1181,7 +1185,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
q = parse = missing_field(sob(parse + 1), errline);
|
||||
parse = son(parse);
|
||||
if (!*parse)
|
||||
errx(1, "malformed line (missing fields):\n%s",
|
||||
badline("malformed line (missing fields):\n%s",
|
||||
errline);
|
||||
*parse = '\0';
|
||||
} else {
|
||||
@ -1190,7 +1194,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
}
|
||||
|
||||
if (!sscanf(q, "%o", &working->permissions))
|
||||
errx(1, "error in config file; bad permissions:\n%s",
|
||||
badline("error in config file; bad permissions:\n%s",
|
||||
errline);
|
||||
if ((working->permissions & ~DEFFILEMODE) != 0) {
|
||||
warnx("File mode bits 0%o changed to 0%o in line:\n%s",
|
||||
@ -1202,17 +1206,17 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
q = parse = missing_field(sob(parse + 1), errline);
|
||||
parse = son(parse);
|
||||
if (!*parse)
|
||||
errx(1, "malformed line (missing fields):\n%s",
|
||||
badline("malformed line (missing fields):\n%s",
|
||||
errline);
|
||||
*parse = '\0';
|
||||
if (!sscanf(q, "%d", &working->numlogs) || working->numlogs < 0)
|
||||
errx(1, "error in config file; bad value for count of logs to save:\n%s",
|
||||
badline("error in config file; bad value for count of logs to save:\n%s",
|
||||
errline);
|
||||
|
||||
q = parse = missing_field(sob(parse + 1), errline);
|
||||
parse = son(parse);
|
||||
if (!*parse)
|
||||
errx(1, "malformed line (missing fields):\n%s",
|
||||
badline("malformed line (missing fields):\n%s",
|
||||
errline);
|
||||
*parse = '\0';
|
||||
if (isdigitch(*q))
|
||||
@ -1241,14 +1245,14 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
else if (*ep == '*')
|
||||
working->hours = -1;
|
||||
else if (ul > INT_MAX)
|
||||
errx(1, "interval is too large:\n%s", errline);
|
||||
badline("interval is too large:\n%s", errline);
|
||||
else
|
||||
working->hours = ul;
|
||||
|
||||
if (*ep == '\0' || strcmp(ep, "*") == 0)
|
||||
goto no_trimat;
|
||||
if (*ep != '@' && *ep != '$')
|
||||
errx(1, "malformed interval/at:\n%s", errline);
|
||||
badline("malformed interval/at:\n%s", errline);
|
||||
|
||||
working->flags |= CE_TRIMAT;
|
||||
working->trim_at = ptime_init(NULL);
|
||||
@ -1259,10 +1263,10 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
res = ptime_relparse(working->trim_at, ptm_opts,
|
||||
ptimeget_secs(timenow), ep + 1);
|
||||
if (res == -2)
|
||||
errx(1, "nonexistent time for 'at' value:\n%s",
|
||||
badline("nonexistent time for 'at' value:\n%s",
|
||||
errline);
|
||||
else if (res < 0)
|
||||
errx(1, "malformed 'at' value:\n%s", errline);
|
||||
badline("malformed 'at' value:\n%s", errline);
|
||||
}
|
||||
no_trimat:
|
||||
|
||||
@ -1325,7 +1329,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
case 'f': /* Used by OpenBSD for "CE_FOLLOW" */
|
||||
case 'm': /* Used by OpenBSD for "CE_MONITOR" */
|
||||
default:
|
||||
errx(1, "illegal flag in config file -- %c",
|
||||
badline("illegal flag in config file -- %c",
|
||||
*q);
|
||||
}
|
||||
}
|
||||
@ -1347,7 +1351,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
else if (isalnum(*q))
|
||||
goto got_sig;
|
||||
else {
|
||||
errx(1,
|
||||
badline(
|
||||
"illegal pid file or signal in config file:\n%s",
|
||||
errline);
|
||||
}
|
||||
@ -1365,7 +1369,7 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
got_sig:
|
||||
working->sig = parse_signal(q);
|
||||
if (working->sig < 1 || working->sig >= sys_nsig) {
|
||||
errx(1,
|
||||
badline(
|
||||
"illegal signal in config file:\n%s",
|
||||
errline);
|
||||
}
|
||||
@ -1416,7 +1420,11 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
|
||||
} else {
|
||||
STAILQ_INSERT_TAIL(work_p, working, cf_nextp);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
cleanup:
|
||||
free_entry(working);
|
||||
#undef badline
|
||||
} /* while (fgets(line, BUFSIZ, cf)) */
|
||||
if (errline != NULL)
|
||||
free(errline);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user