X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=miscutils%2Fcrond.c;h=12560fa367a846254f43d0cf792bede510ad3ed2;hb=76ddc2e3e4837d0557fb6626394f87648e5f8c3b;hp=51b09ece03770efb49ca850b7b6e3ce412e3ea69;hpb=c94d3564c2b0584804fd4bab0a03f9160aa39720;p=oweals%2Fbusybox.git diff --git a/miscutils/crond.c b/miscutils/crond.c index 51b09ece0..12560fa36 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -80,9 +80,9 @@ enum { OPT_b = (1 << 3), OPT_S = (1 << 4), OPT_c = (1 << 5), - OPT_d = (1 << 6) * ENABLE_DEBUG_CROND_OPTION, + OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D, }; -#if ENABLE_DEBUG_CROND_OPTION +#if ENABLE_FEATURE_CROND_D #define DebugOpt (option_mask32 & OPT_d) #else #define DebugOpt 0 @@ -159,18 +159,18 @@ static void crondlog(const char *ctl, ...) } int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int crond_main(int argc ATTRIBUTE_UNUSED, char **argv) +int crond_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; INIT_G(); /* "-b after -f is ignored", and so on for every pair a-b */ - opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l") + opt_complementary = "f-b:b-f:S-L:L-S" USE_FEATURE_CROND_D(":d-l") ":l+:d+"; /* -l and -d have numeric param */ - opt = getopt32(argv, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"), + opt = getopt32(argv, "l:L:fbSc:" USE_FEATURE_CROND_D("d:"), &LogLevel, &LogFile, &CDir - USE_DEBUG_CROND_OPTION(,&LogLevel)); + USE_FEATURE_CROND_D(,&LogLevel)); /* both -d N and -l N set the same variable: LogLevel */ if (!(opt & OPT_f)) { @@ -187,7 +187,7 @@ int crond_main(int argc ATTRIBUTE_UNUSED, char **argv) xchdir(CDir); //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ - setenv("SHELL", DEFAULT_SHELL, 1); /* once, for all future children */ + xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ crondlog(LVL9 "crond (busybox "BB_VER") started, log level %d", LogLevel); SynchronizeDir(); @@ -252,14 +252,12 @@ int crond_main(int argc ATTRIBUTE_UNUSED, char **argv) /* We set environment *before* vfork (because we want to use vfork), * so we cannot use setenv() - repeated calls to setenv() may leak memory! * Using putenv(), and freeing memory after unsetenv() won't leak */ -static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, int len*/) +static void safe_setenv(char **pvar_val, const char *var, const char *val) { - const int len = 4; /* both var names are 4 char long */ char *var_val = *pvar_val; if (var_val) { - var_val[len] = '\0'; /* nuke '=' */ - unsetenv(var_val); + bb_unsetenv(var_val); free(var_val); } *pvar_val = xasprintf("%s=%s", var, val); @@ -270,13 +268,13 @@ static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, i static void SetEnv(struct passwd *pas) { #if SETENV_LEAKS - safe_setenv4(&env_var_user, "USER", pas->pw_name); - safe_setenv4(&env_var_home, "HOME", pas->pw_dir); + safe_setenv(&env_var_user, "USER", pas->pw_name); + safe_setenv(&env_var_home, "HOME", pas->pw_dir); /* if we want to set user's shell instead: */ - /*safe_setenv(env_var_user, "SHELL", pas->pw_shell, 5);*/ + /*safe_setenv(env_var_user, "SHELL", pas->pw_shell);*/ #else - setenv("USER", pas->pw_name, 1); - setenv("HOME", pas->pw_dir, 1); + xsetenv("USER", pas->pw_name); + xsetenv("HOME", pas->pw_dir); #endif /* currently, we use constant one: */ /*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */ @@ -304,7 +302,7 @@ static const char MonAry[] ALIGN1 = /* "Jan""Feb""Mar""Apr""May""Jun""Jul""Aug""Sep""Oct""Nov""Dec" */ ; -static char *ParseField(char *user, char *ary, int modvalue, int off, +static void ParseField(char *user, char *ary, int modvalue, int off, const char *names, char *ptr) /* 'names' is a pointer to a set of 3-char abbreviations */ { @@ -312,11 +310,11 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, int n1 = -1; int n2 = -1; - if (base == NULL) { - return NULL; - } + // this can't happen due to config_read() + /*if (base == NULL) + return;*/ - while (!isspace(*ptr)) { + while (1) { int skip = 0; /* Handle numeric digit or symbol or '*' */ @@ -352,8 +350,7 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, /* handle optional range '-' */ if (skip == 0) { - crondlog(WARN9 "user %s: parse error at %s", user, base); - return NULL; + goto err; } if (*ptr == '-' && n2 < 0) { ++ptr; @@ -388,8 +385,7 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, s0 = skip; } if (--failsafe == 0) { - crondlog(WARN9 "user %s: parse error at %s", user, base); - return NULL; + goto err; } } while (n1 != n2); @@ -402,9 +398,10 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, n2 = -1; } - if (!isspace(*ptr)) { + if (*ptr) { + err: crondlog(WARN9 "user %s: parse error at %s", user, base); - return NULL; + return; } if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */ @@ -414,7 +411,6 @@ static char *ParseField(char *user, char *ary, int modvalue, int off, fprintf(stderr, "%d", (unsigned char)ary[i]); fputc('\n', stderr); } - return skip_whitespace(ptr); } static void FixDayDow(CronLine *line) @@ -445,11 +441,10 @@ static void FixDayDow(CronLine *line) static void SynchronizeFile(const char *fileName) { - FILE *fi; + struct parser_t *parser; struct stat sbuf; - int maxEntries; int maxLines; - char buf[1024]; + char *tokens[6]; #if ENABLE_FEATURE_CROND_CALL_SENDMAIL char *mailTo = NULL; #endif @@ -458,57 +453,50 @@ static void SynchronizeFile(const char *fileName) return; DeleteFile(fileName); - fi = fopen(fileName, "r"); - if (!fi) + parser = config_open(fileName); + if (!parser) return; - maxEntries = MAXLINES; - if (strcmp(fileName, "root") == 0) { - maxEntries = 65535; - } - maxLines = maxEntries * 10; + maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; - if (fstat(fileno(fi), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { + if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DaemonUid) { CronFile *file = xzalloc(sizeof(CronFile)); CronLine **pline; + int n; file->cf_User = xstrdup(fileName); pline = &file->cf_LineBase; - while (fgets(buf, sizeof(buf), fi) != NULL && --maxLines) { + while (1) { CronLine *line; - char *ptr; - trim(buf); - if (buf[0] == '\0' || buf[0] == '#') { - continue; - } - if (--maxEntries == 0) { + if (!--maxLines) break; - } - if (DebugOpt) { - crondlog(LVL5 "user:%s entry:%s", fileName, buf); - } + n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY); + if (!n) + break; + + if (DebugOpt) + crondlog(LVL5 "user:%s entry:%s", fileName, parser->data); + /* check if line is setting MAILTO= */ - if (0 == strncmp("MAILTO=", buf, 7)) { + if (0 == strncmp(tokens[0], "MAILTO=", 7)) { #if ENABLE_FEATURE_CROND_CALL_SENDMAIL free(mailTo); - mailTo = (buf[7]) ? xstrdup(buf+7) : NULL; + mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; #endif /* otherwise just ignore such lines */ continue; } - *pline = line = xzalloc(sizeof(CronLine)); - /* parse date ranges */ - ptr = ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, buf); - ptr = ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, ptr); - ptr = ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, ptr); - ptr = ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, ptr); - ptr = ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, ptr); - /* check failure */ - if (ptr == NULL) { - free(line); + /* check if a minimum of tokens is specified */ + if (n < 6) continue; - } + *pline = line = xzalloc(sizeof(*line)); + /* parse date ranges */ + ParseField(file->cf_User, line->cl_Mins, 60, 0, NULL, tokens[0]); + ParseField(file->cf_User, line->cl_Hrs, 24, 0, NULL, tokens[1]); + ParseField(file->cf_User, line->cl_Days, 32, 0, NULL, tokens[2]); + ParseField(file->cf_User, line->cl_Mons, 12, -1, MonAry, tokens[3]); + ParseField(file->cf_User, line->cl_Dow, 7, 0, DowAry, tokens[4]); /* * fix days and dow - if one is not "*" and the other * is "*", the other is set to 0, and vise-versa @@ -519,22 +507,23 @@ static void SynchronizeFile(const char *fileName) line->cl_MailTo = xstrdup(mailTo); #endif /* copy command */ - line->cl_Shell = xstrdup(ptr); + line->cl_Shell = xstrdup(tokens[5]); if (DebugOpt) { - crondlog(LVL5 " command:%s", ptr); + crondlog(LVL5 " command:%s", tokens[5]); } pline = &line->cl_Next; +//bb_error_msg("M[%s]F[%s][%s][%s][%s][%s][%s]", mailTo, tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]); } *pline = NULL; file->cf_Next = FileBase; FileBase = file; - if (maxLines == 0 || maxEntries == 0) { + if (maxLines == 0) { crondlog(WARN9 "user %s: too many lines", fileName); } } - fclose(fi); + config_close(parser); } static void CheckUpdates(void) @@ -542,7 +531,7 @@ static void CheckUpdates(void) FILE *fi; char buf[256]; - fi = fopen(CRONUPDATE, "r"); + fi = fopen_for_read(CRONUPDATE); if (fi != NULL) { unlink(CRONUPDATE); while (fgets(buf, sizeof(buf), fi) != NULL) { @@ -788,7 +777,9 @@ ForkJob(const char *user, CronLine *line, int mailFd, xmove_fd(mailFd, mail_filename ? 1 : 0); dup2(1, 2); } - execl(prog, prog, cmd, arg, NULL); + /* crond 3.0pl1-100 puts tasks in separate process groups */ + bb_setpgrp(); + execlp(prog, prog, cmd, arg, NULL); crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user, prog, cmd, arg); if (mail_filename) { fdprintf(1, "Exec failed: %s -c %s\n", prog, arg); @@ -923,6 +914,8 @@ static void RunJob(const char *user, CronLine *line) if (DebugOpt) { crondlog(LVL5 "child running %s", DEFAULT_SHELL); } + /* crond 3.0pl1-100 puts tasks in separate process groups */ + bb_setpgrp(); execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL); crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user, DEFAULT_SHELL, "-c", line->cl_Shell);