version 1.104, 2017/07/14 22:17:16 |
version 1.105, 2017/07/20 18:39:16 |
|
|
int stat_suffix(char *, size_t, char *, struct stat *, |
int stat_suffix(char *, size_t, char *, struct stat *, |
int (*)(const char *, struct stat *)); |
int (*)(const char *, struct stat *)); |
off_t sizefile(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 parse8601(char *); |
time_t parseDWM(char *); |
time_t parseDWM(char *); |
void child_killer(int); |
void child_killer(int); |
|
|
struct entrylist config, runlist; |
struct entrylist config, runlist; |
struct conf_entry *p, *q, *tmp; |
struct conf_entry *p, *q, *tmp; |
struct pidinfo *pidlist, *pl; |
struct pidinfo *pidlist, *pl; |
int status, listlen; |
int status, listlen, ret; |
char **av; |
char **av; |
|
|
parse_args(argc, argv); |
parse_args(argc, argv); |
|
|
TAILQ_INIT(&config); |
TAILQ_INIT(&config); |
TAILQ_INIT(&runlist); |
TAILQ_INIT(&runlist); |
|
|
parse_file(&config, &listlen); |
ret = parse_file(&config, &listlen); |
if (argc == 0) |
if (argc == 0) |
TAILQ_CONCAT(&runlist, &config, next); |
TAILQ_CONCAT(&runlist, &config, next); |
else { |
else { |
|
|
/* Wait for children to finish, then exit */ |
/* Wait for children to finish, then exit */ |
while (waitpid(-1, &status, 0) != -1) |
while (waitpid(-1, &status, 0) != -1) |
; |
; |
exit(0); |
return (ret); |
} |
} |
|
|
void |
void |
|
|
* Parse a configuration file and build a linked list of all the logs |
* Parse a configuration file and build a linked list of all the logs |
* to process |
* to process |
*/ |
*/ |
void |
int |
parse_file(struct entrylist *list, int *nentries) |
parse_file(struct entrylist *list, int *nentries) |
{ |
{ |
char line[BUFSIZ], *parse, *q, *errline, *group, *tmp, *ep; |
char line[BUFSIZ], *parse, *q, *errline, *group, *tmp, *ep; |
|
|
struct passwd *pwd; |
struct passwd *pwd; |
struct group *grp; |
struct group *grp; |
struct stat sb; |
struct stat sb; |
int lineno; |
int lineno = 0; |
|
int ret = 0; |
FILE *f; |
FILE *f; |
long l; |
long l; |
|
|
|
|
err(1, "can't open %s", conf); |
err(1, "can't open %s", conf); |
|
|
*nentries = 0; |
*nentries = 0; |
for (lineno = 1; fgets(line, sizeof(line), f); lineno++) { |
|
|
nextline: |
|
while (fgets(line, sizeof(line), f) != NULL) { |
|
lineno++; |
tmp = sob(line); |
tmp = sob(line); |
if (*tmp == '\0' || *tmp == '#') |
if (*tmp == '\0' || *tmp == '#') |
continue; |
continue; |
|
|
*group++ = '\0'; |
*group++ = '\0'; |
if (*q) { |
if (*q) { |
if (!(isnumberstr(q))) { |
if (!(isnumberstr(q))) { |
if ((pwd = getpwnam(q)) == NULL) |
if ((pwd = getpwnam(q)) == NULL) { |
errx(1, "%s:%d: unknown user: %s", |
warnx("%s:%d: unknown user" |
|
" %s --> skipping", |
conf, lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->uid = pwd->pw_uid; |
working->uid = pwd->pw_uid; |
} else |
} else |
working->uid = atoi(q); |
working->uid = atoi(q); |
|
|
q = group; |
q = group; |
if (*q) { |
if (*q) { |
if (!(isnumberstr(q))) { |
if (!(isnumberstr(q))) { |
if ((grp = getgrnam(q)) == NULL) |
if ((grp = getgrnam(q)) == NULL) { |
errx(1, "%s:%d: unknown group: %s", |
warnx("%s:%d: unknown group" |
|
" %s --> skipping", |
conf, lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->gid = grp->gr_gid; |
working->gid = grp->gr_gid; |
} else |
} else |
working->gid = atoi(q); |
working->gid = atoi(q); |
|
|
} |
} |
|
|
l = strtol(q, &ep, 8); |
l = strtol(q, &ep, 8); |
if (*ep != '\0' || l < 0 || l > ALLPERMS) |
if (*ep != '\0' || l < 0 || l > ALLPERMS) { |
errx(1, "%s:%d: bad permissions: %s", conf, lineno, q); |
warnx("%s:%d: bad permissions: %s --> skipping", conf, |
|
lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->permissions = (mode_t)l; |
working->permissions = (mode_t)l; |
|
|
q = parse = missing_field(sob(++parse), errline, lineno); |
q = parse = missing_field(sob(++parse), errline, lineno); |
*(parse = son(parse)) = '\0'; |
*(parse = son(parse)) = '\0'; |
l = strtol(q, &ep, 10); |
l = strtol(q, &ep, 10); |
if (*ep != '\0' || l < 0 || l >= INT_MAX) |
if (*ep != '\0' || l < 0 || l >= INT_MAX) { |
errx(1, "%s:%d: bad number: %s", conf, lineno, q); |
warnx("%s:%d: bad number: %s --> skipping", conf, |
|
lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->numlogs = (int)l; |
working->numlogs = (int)l; |
|
|
q = parse = missing_field(sob(++parse), errline, lineno); |
q = parse = missing_field(sob(++parse), errline, lineno); |
|
|
q = parse = missing_field(sob(++parse), errline, lineno); |
q = parse = missing_field(sob(++parse), errline, lineno); |
*(parse = son(parse)) = '\0'; |
*(parse = son(parse)) = '\0'; |
l = strtol(q, &ep, 10); |
l = strtol(q, &ep, 10); |
if (l < 0 || l >= INT_MAX) |
if (l < 0 || l >= INT_MAX) { |
errx(1, "%s:%d: interval out of range: %s", conf, |
warnx("%s:%d: interval out of range: %s --> skipping", |
lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->hours = (int)l; |
working->hours = (int)l; |
switch (*ep) { |
switch (*ep) { |
case '\0': |
case '\0': |
break; |
break; |
case '@': |
case '@': |
working->trim_at = parse8601(ep + 1); |
working->trim_at = parse8601(ep + 1); |
if (working->trim_at == (time_t) - 1) |
if (working->trim_at == (time_t) - 1) { |
errx(1, "%s:%d: bad time: %s", conf, lineno, q); |
warnx("%s:%d: bad time: %s --> skipping", conf, |
|
lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->flags |= CE_TRIMAT; |
working->flags |= CE_TRIMAT; |
break; |
break; |
case '$': |
case '$': |
working->trim_at = parseDWM(ep + 1); |
working->trim_at = parseDWM(ep + 1); |
if (working->trim_at == (time_t) - 1) |
if (working->trim_at == (time_t) - 1) { |
errx(1, "%s:%d: bad time: %s", conf, lineno, q); |
warnx("%s:%d: bad time: %s --> skipping", conf, |
|
lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->flags |= CE_TRIMAT; |
working->flags |= CE_TRIMAT; |
break; |
break; |
case '*': |
case '*': |
|
|
break; |
break; |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
default: |
default: |
errx(1, "%s:%d: bad interval/at: %s", conf, lineno, q); |
warnx("%s:%d: bad interval/at: %s --> skipping", conf, |
break; |
lineno, q); |
|
ret = 1; |
|
goto nextline; |
} |
} |
|
|
q = sob(++parse); /* Optional field */ |
q = sob(++parse); /* Optional field */ |
|
|
working->flags |= CE_FOLLOW; |
working->flags |= CE_FOLLOW; |
break; |
break; |
default: |
default: |
errx(1, "%s:%d: illegal flag: `%c'", |
warnx("%s:%d: illegal flag: `%c'" |
|
" --> skipping", |
conf, lineno, *q); |
conf, lineno, *q); |
break; |
ret = 1; |
|
goto nextline; |
} |
} |
q++; |
q++; |
} |
} |
|
|
break; |
break; |
if (*q == '/') { |
if (*q == '/') { |
*(parse = son(parse)) = '\0'; |
*(parse = son(parse)) = '\0'; |
if (strlen(q) >= PATH_MAX) |
if (strlen(q) >= PATH_MAX) { |
errx(1, "%s:%d: pathname too long: %s", |
warnx("%s:%d: pathname too long: %s" |
|
" --> skipping", |
conf, lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
working->pidfile = strdup(q); |
working->pidfile = strdup(q); |
if (working->pidfile == NULL) |
if (working->pidfile == NULL) |
err(1, "strdup"); |
err(1, "strdup"); |
|
|
break; |
break; |
} |
} |
} |
} |
if (i == NSIG) |
if (i == NSIG) { |
errx(1, "%s:%d: unknown signal: %s", |
warnx("%s:%d: unknown signal: %s" |
|
" --> skipping", |
conf, lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
} else if (working->flags & CE_MONITOR) { |
} else if (working->flags & CE_MONITOR) { |
*(parse = son(parse)) = '\0'; |
*(parse = son(parse)) = '\0'; |
working->whom = strdup(q); |
working->whom = strdup(q); |
if (working->whom == NULL) |
if (working->whom == NULL) |
err(1, "strdup"); |
err(1, "strdup"); |
} else |
} else { |
errx(1, "%s:%d: unrecognized field: %s", |
warnx("%s:%d: unrecognized field: %s" |
|
" --> skipping", |
conf, lineno, q); |
conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
} |
} |
free(errline); |
free(errline); |
|
|
if ((working->flags & CE_MONITOR) && working->whom == NULL) |
if ((working->flags & CE_MONITOR) && working->whom == NULL) { |
errx(1, "%s:%d: missing monitor notification field", |
warnx("%s:%d: missing monitor notification field" |
|
" --> skipping", |
conf, lineno); |
conf, lineno); |
|
ret = 1; |
|
goto nextline; |
|
} |
|
|
/* If there is an arcdir, set working->backdir. */ |
/* If there is an arcdir, set working->backdir. */ |
if (arcdir != NULL && working->logbase != NULL) { |
if (arcdir != NULL && working->logbase != NULL) { |
|
|
if (working->backdir != NULL) { |
if (working->backdir != NULL) { |
if (snprintf(line, sizeof(line), "%s/%s.%d%s", |
if (snprintf(line, sizeof(line), "%s/%s.%d%s", |
working->backdir, working->logbase, |
working->backdir, working->logbase, |
working->numlogs, COMPRESS_POSTFIX) >= PATH_MAX) |
working->numlogs, COMPRESS_POSTFIX) >= PATH_MAX) { |
errx(1, "%s:%d: pathname too long: %s", |
warnx("%s:%d: pathname too long: %s" |
conf, lineno, q); |
" --> skipping", conf, lineno, q); |
|
ret = 1; |
|
goto nextline; |
|
} |
} else { |
} else { |
if (snprintf(line, sizeof(line), "%s.%d%s", |
if (snprintf(line, sizeof(line), "%s.%d%s", |
working->log, working->numlogs, COMPRESS_POSTFIX) |
working->log, working->numlogs, COMPRESS_POSTFIX) |
>= PATH_MAX) |
>= PATH_MAX) { |
errx(1, "%s:%d: pathname too long: %s", |
warnx("%s:%d: pathname too long: %s" |
conf, lineno, working->log); |
" --> skipping", conf, lineno, |
|
working->log); |
|
ret = 1; |
|
goto nextline; |
|
} |
} |
} |
TAILQ_INSERT_TAIL(list, working, next); |
TAILQ_INSERT_TAIL(list, working, next); |
(*nentries)++; |
(*nentries)++; |
} |
} |
(void)fclose(f); |
(void)fclose(f); |
|
return (ret); |
} |
} |
|
|
char * |
char * |