void quit (int err) { if (err >= -1) { buf[0] = DLP_LOGOUT; sendto (0, buf, 1, 0, (struct sockaddr*) &peerfrom, sizeof peerfrom); } log7 ("%s total %lu seconds %lu ibytes %lu obytes %lu ipackets %lu opackets", err ? "abort" : "logout", time (0) - t0, ibytes, obytes, ipackets, opackets); exit (err); }
static void load_crontab(const char *fileName) { struct parser_t *parser; struct stat sbuf; int maxLines; char *tokens[6]; #if ENABLE_FEATURE_CROND_CALL_SENDMAIL char *mailTo = NULL; #endif char *shell = NULL; delete_cronfile(fileName); if (!getpwnam(fileName)) { log7("ignoring file '%s' (no such user)", fileName); return; } parser = config_open(fileName); if (!parser) return; maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DAEMON_UID) { CronFile *file = xzalloc(sizeof(CronFile)); CronLine **pline; int n; file->cf_username = xstrdup(fileName); pline = &file->cf_lines; while (1) { CronLine *line; if (!--maxLines) { bb_error_msg("user %s: too many lines", fileName); break; } n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY); if (!n) break; log5("user:%s entry:%s", fileName, parser->data); /* check if line is setting MAILTO= */ if (is_prefixed_with(tokens[0], "MAILTO=")) { #if ENABLE_FEATURE_CROND_CALL_SENDMAIL free(mailTo); mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; #endif /* otherwise just ignore such lines */ continue; } if (is_prefixed_with(tokens[0], "SHELL=")) { free(shell); shell = xstrdup(&tokens[0][6]); continue; } //TODO: handle HOME= too? "man crontab" says: //name = value // //where the spaces around the equal-sign (=) are optional, and any subsequent //non-leading spaces in value will be part of the value assigned to name. //The value string may be placed in quotes (single or double, but matching) //to preserve leading or trailing blanks. // //Several environment variables are set up automatically by the cron(8) daemon. //SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd //line of the crontab's owner. HOME and SHELL may be overridden by settings //in the crontab; LOGNAME may not. /* check if a minimum of tokens is specified */ if (n < 6) continue; *pline = line = xzalloc(sizeof(*line)); /* parse date ranges */ ParseField(file->cf_username, line->cl_Mins, 60, 0, NULL, tokens[0]); ParseField(file->cf_username, line->cl_Hrs, 24, 0, NULL, tokens[1]); ParseField(file->cf_username, line->cl_Days, 32, 0, NULL, tokens[2]); ParseField(file->cf_username, line->cl_Mons, 12, -1, MonAry, tokens[3]); ParseField(file->cf_username, 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 */ FixDayDow(line); #if ENABLE_FEATURE_CROND_CALL_SENDMAIL /* copy mailto (can be NULL) */ line->cl_mailto = xstrdup(mailTo); #endif line->cl_shell = xstrdup(shell); /* copy command */ line->cl_cmd = xstrdup(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 = G.cron_files; G.cron_files = file; } config_close(parser); #if ENABLE_FEATURE_CROND_CALL_SENDMAIL free(mailTo); #endif free(shell); }
static void load_crontab(const char *fileName) { struct parser_t *parser; struct stat sbuf; int maxLines; char *tokens[6]; #if ENABLE_FEATURE_CROND_CALL_SENDMAIL char *mailTo = NULL; #endif char *shell = NULL; delete_cronfile(fileName); if (!getpwnam(fileName)) { log7("ignoring file '%s' (no such user)", fileName); return; } parser = config_open(fileName); if (!parser) return; maxLines = (strcmp(fileName, "root") == 0) ? 65535 : MAXLINES; if (fstat(fileno(parser->fp), &sbuf) == 0 && sbuf.st_uid == DAEMON_UID) { CronFile *file = xzalloc(sizeof(CronFile)); CronLine **pline; int n; file->cf_username = xstrdup(fileName); pline = &file->cf_lines; while (1) { CronLine *line; if (!--maxLines) { bb_error_msg("user %s: too many lines", fileName); break; } n = config_read(parser, tokens, 6, 1, "# \t", PARSE_NORMAL | PARSE_KEEP_COPY); if (!n) break; log5("user:%s entry:%s", fileName, parser->data); /* check if line is setting MAILTO= */ if (is_prefixed_with(tokens[0], "MAILTO=")) { #if ENABLE_FEATURE_CROND_CALL_SENDMAIL free(mailTo); mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; #endif /* otherwise just ignore such lines */ continue; } if (is_prefixed_with(tokens[0], "SHELL=")) { free(shell); shell = xstrdup(&tokens[0][6]); continue; } //TODO: handle HOME= too? "man crontab" says: //name = value // //where the spaces around the equal-sign (=) are optional, and any subsequent //non-leading spaces in value will be part of the value assigned to name. //The value string may be placed in quotes (single or double, but matching) //to preserve leading or trailing blanks. // //Several environment variables are set up automatically by the cron(8) daemon. //SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd //line of the crontab's owner. HOME and SHELL may be overridden by settings //in the crontab; LOGNAME may not. #if ENABLE_FEATURE_CROND_SPECIAL_TIMES if (tokens[0][0] == '@') { /* * "@daily /a/script/to/run PARAM1 PARAM2..." */ typedef struct SpecialEntry { const char *name; const char tokens[8]; } SpecialEntry; static const SpecialEntry SpecAry[] = { /* hour day month weekday */ { "yearly", "0\0" "1\0" "1\0" "*" }, { "annually", "0\0" "1\0" "1\0" "*" }, { "monthly", "0\0" "1\0" "*\0" "*" }, { "weekly", "0\0" "*\0" "*\0" "0" }, { "daily", "0\0" "*\0" "*\0" "*" }, { "midnight", "0\0" "*\0" "*\0" "*" }, { "hourly", "*\0" "*\0" "*\0" "*" }, { "reboot", "" }, }; const SpecialEntry *e = SpecAry; if (n < 2) continue; for (;;) { if (strcmp(e->name, tokens[0] + 1) == 0) { /* * tokens[1] is only the first word of command, * can'r use it. * find the entire command in unmodified string: */ tokens[5] = skip_whitespace( skip_non_whitespace( skip_whitespace(parser->data))); if (e->tokens[0]) { char *et = (char*)e->tokens; /* minute is "0" for all specials */ tokens[0] = (char*)"0"; tokens[1] = et; tokens[2] = et + 2; tokens[3] = et + 4; tokens[4] = et + 6; } goto got_it; } if (!e->tokens[0]) break; e++; } continue; /* bad line (unrecognized '@foo') */ } #endif /* check if a minimum of tokens is specified */ if (n < 6) continue; IF_FEATURE_CROND_SPECIAL_TIMES( got_it: ) *pline = line = xzalloc(sizeof(*line)); #if ENABLE_FEATURE_CROND_SPECIAL_TIMES if (tokens[0][0] == '@') { /* "@reboot" line */ file->cf_wants_starting = 1; line->cl_pid = START_ME_REBOOT; /* wants to start */ /* line->cl_Mins/Hrs/etc stay zero: never match any time */ } else #endif { /* parse date ranges */ ParseField(file->cf_username, line->cl_Mins, 60, 0, NULL, tokens[0]); ParseField(file->cf_username, line->cl_Hrs, 24, 0, NULL, tokens[1]); ParseField(file->cf_username, line->cl_Days, 32, 0, NULL, tokens[2]); ParseField(file->cf_username, line->cl_Mons, 12, -1, MonAry, tokens[3]); ParseField(file->cf_username, 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 */ FixDayDow(line); } #if ENABLE_FEATURE_CROND_CALL_SENDMAIL /* copy mailto (can be NULL) */ line->cl_mailto = xstrdup(mailTo); #endif line->cl_shell = xstrdup(shell); /* copy command */ line->cl_cmd = xstrdup(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 = G.cron_files; G.cron_files = file; }