aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2014-04-30 14:49:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-04-30 14:49:52 +0200
commitd5929d602ee952d2f2468b4957a4ebd219108b2f (patch)
tree2a4599885bc4f84e13e4bec0e6946a4f7511d8ab
parent3dfe0ae5a8c4f3a75f61df157db157ac0e044a51 (diff)
downloadbusybox-w32-d5929d602ee952d2f2468b4957a4ebd219108b2f.tar.gz
busybox-w32-d5929d602ee952d2f2468b4957a4ebd219108b2f.tar.bz2
busybox-w32-d5929d602ee952d2f2468b4957a4ebd219108b2f.zip
crond: simplify logging code
Slight change in behavior: now -l 5 will enable the same messages formerly only enabled for -d 5. (Old behavior was non-sensical). function old new delta reopen_logfile_to_stderr - 34 +34 log8 - 26 +26 log7 - 26 +26 log5 - 26 +26 load_crontab 706 688 -18 rescan_crontab_dir 157 137 -20 crond_main 1486 1456 -30 fork_job 389 343 -46 crondlog 108 38 -70 ------------------------------------------------------------------------------ (add/remove: 4/0 grow/shrink: 0/5 up/down: 112/-184) Total: -72 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/crond.c175
1 files changed, 88 insertions, 87 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 8441b6cc5..210da5f47 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -125,12 +125,6 @@ enum {
125 OPT_c = (1 << 5), 125 OPT_c = (1 << 5),
126 OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D, 126 OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D,
127}; 127};
128#if ENABLE_FEATURE_CROND_D
129# define DebugOpt (option_mask32 & OPT_d)
130#else
131# define DebugOpt 0
132#endif
133
134 128
135struct globals { 129struct globals {
136 unsigned log_level; /* = 8; */ 130 unsigned log_level; /* = 8; */
@@ -149,41 +143,50 @@ struct globals {
149 G.crontab_dir_name = CRONTABS; \ 143 G.crontab_dir_name = CRONTABS; \
150} while (0) 144} while (0)
151 145
146/* Log levels:
147 * 0 is the most verbose, default 8.
148 * For some reason, in fact only 5, 7 and 8 are used.
149 */
150static void crondlog(unsigned level, const char *msg, va_list va)
151{
152 if (level >= G.log_level) {
153 /*
154 * We are called only for info meesages.
155 * Warnings/errors use plain bb_[p]error_msg's, which
156 * need not touch syslog_level
157 * (they are ok with LOG_ERR default).
158 */
159 syslog_level = LOG_INFO;
160 bb_verror_msg(msg, va, /* strerr: */ NULL);
161 syslog_level = LOG_ERR;
162 }
163}
152 164
153/* 0 is the most verbose, default 8 */ 165static void log5(const char *msg, ...)
154#define LVL5 "\x05" 166{
155#define LVL7 "\x07" 167 va_list va;
156#define LVL8 "\x08" 168 va_start(va, msg);
157#define WARN9 "\x49" 169 crondlog(4, msg, va);
158#define DIE9 "\xc9" 170 va_end(va);
159/* level >= 20 is "error" */ 171}
160#define ERR20 "\x14"
161 172
162static void crondlog(const char *ctl, ...) __attribute__ ((format (printf, 1, 2))); 173static void log7(const char *msg, ...)
163static void crondlog(const char *ctl, ...)
164{ 174{
165 va_list va; 175 va_list va;
166 unsigned level = (ctl[0] & 0x1f); 176 va_start(va, msg);
177 crondlog(7, msg, va);
178 va_end(va);
179}
167 180
168 va_start(va, ctl); 181static void log8(const char *msg, ...)
169 if (level >= G.log_level) { 182{
170 if (G.log_filename) { 183 va_list va;
171 /* If log to file, reopen log file at every write: */ 184 va_start(va, msg);
172 int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND); 185 crondlog(8, msg, va);
173 if (logfd >= 0)
174 xmove_fd(logfd, STDERR_FILENO);
175 }
176 /* When we log to syslog, level > 8 is logged at LOG_ERR
177 * syslog level, level <= 8 is logged at LOG_INFO.
178 */
179 syslog_level = (level > 8) ? LOG_ERR : LOG_INFO;
180 bb_verror_msg(ctl + 1, va, /* strerr: */ NULL);
181 }
182 va_end(va); 186 va_end(va);
183 if (ctl[0] & 0x80)
184 exit(20);
185} 187}
186 188
189
187static const char DowAry[] ALIGN1 = 190static const char DowAry[] ALIGN1 =
188 "sun""mon""tue""wed""thu""fri""sat" 191 "sun""mon""tue""wed""thu""fri""sat"
189; 192;
@@ -293,12 +296,12 @@ static void ParseField(char *user, char *ary, int modvalue, int off,
293 296
294 if (*ptr) { 297 if (*ptr) {
295 err: 298 err:
296 crondlog(WARN9 "user %s: parse error at %s", user, base); 299 bb_error_msg("user %s: parse error at %s", user, base);
297 return; 300 return;
298 } 301 }
299 302
300 if (DebugOpt && (G.log_level <= 5)) { /* like LVL5 */ 303 /* can't use log5 (it inserts newlines), open-coding it */
301 /* can't use crondlog, it inserts '\n' */ 304 if (G.log_level <= 5 && logmode != LOGMODE_SYSLOG) {
302 int i; 305 int i;
303 for (i = 0; i < modvalue; ++i) 306 for (i = 0; i < modvalue; ++i)
304 fprintf(stderr, "%d", (unsigned char)ary[i]); 307 fprintf(stderr, "%d", (unsigned char)ary[i]);
@@ -398,7 +401,7 @@ static void load_crontab(const char *fileName)
398 delete_cronfile(fileName); 401 delete_cronfile(fileName);
399 402
400 if (!getpwnam(fileName)) { 403 if (!getpwnam(fileName)) {
401 crondlog(LVL7 "ignoring file '%s' (no such user)", fileName); 404 log7("ignoring file '%s' (no such user)", fileName);
402 return; 405 return;
403 } 406 }
404 407
@@ -420,7 +423,7 @@ static void load_crontab(const char *fileName)
420 CronLine *line; 423 CronLine *line;
421 424
422 if (!--maxLines) { 425 if (!--maxLines) {
423 crondlog(WARN9 "user %s: too many lines", fileName); 426 bb_error_msg("user %s: too many lines", fileName);
424 break; 427 break;
425 } 428 }
426 429
@@ -428,8 +431,7 @@ static void load_crontab(const char *fileName)
428 if (!n) 431 if (!n)
429 break; 432 break;
430 433
431 if (DebugOpt) 434 log5("user:%s entry:%s", fileName, parser->data);
432 crondlog(LVL5 "user:%s entry:%s", fileName, parser->data);
433 435
434 /* check if line is setting MAILTO= */ 436 /* check if line is setting MAILTO= */
435 if (0 == strncmp(tokens[0], "MAILTO=", 7)) { 437 if (0 == strncmp(tokens[0], "MAILTO=", 7)) {
@@ -472,9 +474,7 @@ static void load_crontab(const char *fileName)
472#endif 474#endif
473 /* copy command */ 475 /* copy command */
474 line->cl_cmd = xstrdup(tokens[5]); 476 line->cl_cmd = xstrdup(tokens[5]);
475 if (DebugOpt) { 477 log5(" command:%s", tokens[5]);
476 crondlog(LVL5 " command:%s", tokens[5]);
477 }
478 pline = &line->cl_next; 478 pline = &line->cl_next;
479//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]); 479//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]);
480 } 480 }
@@ -519,17 +519,16 @@ static void rescan_crontab_dir(void)
519 /* Remove cron update file */ 519 /* Remove cron update file */
520 unlink(CRONUPDATE); 520 unlink(CRONUPDATE);
521 /* Re-chdir, in case directory was renamed & deleted */ 521 /* Re-chdir, in case directory was renamed & deleted */
522 if (chdir(G.crontab_dir_name) < 0) { 522 xchdir(G.crontab_dir_name);
523 crondlog(DIE9 "chdir(%s)", G.crontab_dir_name);
524 }
525 523
526 /* Scan directory and add associated users */ 524 /* Scan directory and add associated users */
527 { 525 {
528 DIR *dir = opendir("."); 526 DIR *dir = opendir(".");
529 struct dirent *den; 527 struct dirent *den;
530 528
529 /* xopendir exists, but "can't open '.'" is not informative */
531 if (!dir) 530 if (!dir)
532 crondlog(DIE9 "chdir(%s)", "."); /* exits */ 531 bb_error_msg_and_die("can't open '%s'", G.crontab_dir_name);
533 while ((den = readdir(dir)) != NULL) { 532 while ((den = readdir(dir)) != NULL) {
534 if (strchr(den->d_name, '.') != NULL) { 533 if (strchr(den->d_name, '.') != NULL) {
535 continue; 534 continue;
@@ -576,10 +575,8 @@ static void change_user(struct passwd *pas)
576 /* careful: we're after vfork! */ 575 /* careful: we're after vfork! */
577 change_identity(pas); /* - initgroups, setgid, setuid */ 576 change_identity(pas); /* - initgroups, setgid, setuid */
578 if (chdir(pas->pw_dir) < 0) { 577 if (chdir(pas->pw_dir) < 0) {
579 crondlog(WARN9 "chdir(%s)", pas->pw_dir); 578 bb_error_msg("can't change directory to '%s'", pas->pw_dir);
580 if (chdir(CRON_DIR) < 0) { 579 xchdir(CRON_DIR);
581 crondlog(DIE9 "chdir(%s)", CRON_DIR); /* exits */
582 }
583 } 580 }
584} 581}
585 582
@@ -591,25 +588,25 @@ fork_job(const char *user, int mailFd,
591 const char *prog, 588 const char *prog,
592 const char *shell_cmd /* if NULL, we run sendmail */ 589 const char *shell_cmd /* if NULL, we run sendmail */
593) { 590) {
591 smallint sv_logmode;
594 struct passwd *pas; 592 struct passwd *pas;
595 pid_t pid; 593 pid_t pid;
596 594
597 /* prepare things before vfork */ 595 /* prepare things before vfork */
598 pas = getpwnam(user); 596 pas = getpwnam(user);
599 if (!pas) { 597 if (!pas) {
600 crondlog(WARN9 "can't get uid for %s", user); 598 bb_error_msg("can't get uid for %s", user);
601 goto err; 599 goto err;
602 } 600 }
603 set_env_vars(pas); 601 set_env_vars(pas);
604 602
603 sv_logmode = logmode;
605 pid = vfork(); 604 pid = vfork();
606 if (pid == 0) { 605 if (pid == 0) {
607 /* CHILD */ 606 /* CHILD */
608 /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */ 607 /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
609 change_user(pas); 608 change_user(pas);
610 if (DebugOpt) { 609 log5("child running %s", prog);
611 crondlog(LVL5 "child running %s", prog);
612 }
613 if (mailFd >= 0) { 610 if (mailFd >= 0) {
614 xmove_fd(mailFd, shell_cmd ? 1 : 0); 611 xmove_fd(mailFd, shell_cmd ? 1 : 0);
615 dup2(1, 2); 612 dup2(1, 2);
@@ -617,15 +614,17 @@ fork_job(const char *user, int mailFd,
617 /* crond 3.0pl1-100 puts tasks in separate process groups */ 614 /* crond 3.0pl1-100 puts tasks in separate process groups */
618 bb_setpgrp(); 615 bb_setpgrp();
619 execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL); 616 execlp(prog, prog, (shell_cmd ? "-c" : SENDMAIL_ARGS), shell_cmd, (char *) NULL);
620 crondlog(ERR20 "can't execute '%s' for user %s", prog, user); 617 /*
621 if (shell_cmd) { 618 * I want this error message on stderr too,
622 fdprintf(1, "Exec failed: %s -c %s\n", prog, shell_cmd); 619 * even if other messages go only to syslog:
623 } 620 */
624 _exit(EXIT_SUCCESS); 621 logmode |= LOGMODE_STDIO;
622 bb_error_msg_and_die("can't execute '%s' for user %s", prog, user);
625 } 623 }
624 logmode = sv_logmode;
626 625
627 if (pid < 0) { 626 if (pid < 0) {
628 crondlog(ERR20 "can't vfork"); 627 bb_perror_msg("vfork");
629 err: 628 err:
630 pid = 0; 629 pid = 0;
631 } /* else: PARENT, FORK SUCCESS */ 630 } /* else: PARENT, FORK SUCCESS */
@@ -658,7 +657,7 @@ static void start_one_job(const char *user, CronLine *line)
658 line->cl_cmd); 657 line->cl_cmd);
659 line->cl_empty_mail_size = lseek(mailFd, 0, SEEK_CUR); 658 line->cl_empty_mail_size = lseek(mailFd, 0, SEEK_CUR);
660 } else { 659 } else {
661 crondlog(ERR20 "can't create mail file %s for user %s, " 660 bb_error_msg("can't create mail file %s for user %s, "
662 "discarding output", mailFile, user); 661 "discarding output", mailFile, user);
663 } 662 }
664 } 663 }
@@ -731,7 +730,7 @@ static void start_one_job(const char *user, CronLine *line)
731 730
732 pas = getpwnam(user); 731 pas = getpwnam(user);
733 if (!pas) { 732 if (!pas) {
734 crondlog(WARN9 "can't get uid for %s", user); 733 bb_error_msg("can't get uid for %s", user);
735 goto err; 734 goto err;
736 } 735 }
737 736
@@ -744,18 +743,14 @@ static void start_one_job(const char *user, CronLine *line)
744 /* CHILD */ 743 /* CHILD */
745 /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */ 744 /* initgroups, setgid, setuid, and chdir to home or CRON_DIR */
746 change_user(pas); 745 change_user(pas);
747 if (DebugOpt) { 746 log5("child running %s", DEFAULT_SHELL);
748 crondlog(LVL5 "child running %s", DEFAULT_SHELL);
749 }
750 /* crond 3.0pl1-100 puts tasks in separate process groups */ 747 /* crond 3.0pl1-100 puts tasks in separate process groups */
751 bb_setpgrp(); 748 bb_setpgrp();
752 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL); 749 execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_cmd, (char *) NULL);
753 crondlog(ERR20 "can't execute '%s' for user %s", DEFAULT_SHELL, user); 750 bb_error_msg_and_die("can't execute '%s' for user %s", DEFAULT_SHELL, user);
754 _exit(EXIT_SUCCESS);
755 } 751 }
756 if (pid < 0) { 752 if (pid < 0) {
757 /* FORK FAILED */ 753 bb_perror_msg("vfork");
758 crondlog(ERR20 "can't vfork");
759 err: 754 err:
760 pid = 0; 755 pid = 0;
761 } 756 }
@@ -787,24 +782,20 @@ static void flag_starting_jobs(time_t t1, time_t t2)
787 782
788 ptm = localtime(&t); 783 ptm = localtime(&t);
789 for (file = G.cron_files; file; file = file->cf_next) { 784 for (file = G.cron_files; file; file = file->cf_next) {
790 if (DebugOpt) 785 log5("file %s:", file->cf_username);
791 crondlog(LVL5 "file %s:", file->cf_username);
792 if (file->cf_deleted) 786 if (file->cf_deleted)
793 continue; 787 continue;
794 for (line = file->cf_lines; line; line = line->cl_next) { 788 for (line = file->cf_lines; line; line = line->cl_next) {
795 if (DebugOpt) 789 log5(" line %s", line->cl_cmd);
796 crondlog(LVL5 " line %s", line->cl_cmd);
797 if (line->cl_Mins[ptm->tm_min] 790 if (line->cl_Mins[ptm->tm_min]
798 && line->cl_Hrs[ptm->tm_hour] 791 && line->cl_Hrs[ptm->tm_hour]
799 && (line->cl_Days[ptm->tm_mday] || line->cl_Dow[ptm->tm_wday]) 792 && (line->cl_Days[ptm->tm_mday] || line->cl_Dow[ptm->tm_wday])
800 && line->cl_Mons[ptm->tm_mon] 793 && line->cl_Mons[ptm->tm_mon]
801 ) { 794 ) {
802 if (DebugOpt) { 795 log5(" job: %d %s",
803 crondlog(LVL5 " job: %d %s",
804 (int)line->cl_pid, line->cl_cmd); 796 (int)line->cl_pid, line->cl_cmd);
805 }
806 if (line->cl_pid > 0) { 797 if (line->cl_pid > 0) {
807 crondlog(LVL8 "user %s: process already running: %s", 798 log8("user %s: process already running: %s",
808 file->cf_username, line->cl_cmd); 799 file->cf_username, line->cl_cmd);
809 } else if (line->cl_pid == 0) { 800 } else if (line->cl_pid == 0) {
810 line->cl_pid = -1; 801 line->cl_pid = -1;
@@ -833,7 +824,7 @@ static void start_jobs(void)
833 824
834 start_one_job(file->cf_username, line); 825 start_one_job(file->cf_username, line);
835 pid = line->cl_pid; 826 pid = line->cl_pid;
836 crondlog(LVL8 "USER %s pid %3d cmd %s", 827 log8("USER %s pid %3d cmd %s",
837 file->cf_username, (int)pid, line->cl_cmd); 828 file->cf_username, (int)pid, line->cl_cmd);
838 if (pid < 0) { 829 if (pid < 0) {
839 file->cf_wants_starting = 1; 830 file->cf_wants_starting = 1;
@@ -885,6 +876,15 @@ static int check_completions(void)
885 return num_still_running; 876 return num_still_running;
886} 877}
887 878
879static void reopen_logfile_to_stderr(void)
880{
881 if (G.log_filename) {
882 int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
883 if (logfd >= 0)
884 xmove_fd(logfd, STDERR_FILENO);
885 }
886}
887
888int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 888int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
889int crond_main(int argc UNUSED_PARAM, char **argv) 889int crond_main(int argc UNUSED_PARAM, char **argv)
890{ 890{
@@ -916,10 +916,12 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
916 logmode = LOGMODE_SYSLOG; 916 logmode = LOGMODE_SYSLOG;
917 } 917 }
918 918
919 reopen_logfile_to_stderr();
920
919 xchdir(G.crontab_dir_name); 921 xchdir(G.crontab_dir_name);
920 //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ 922 //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
921 xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ 923 xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
922 crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", G.log_level); 924 log8("crond (busybox "BB_VER") started, log level %d", G.log_level);
923 rescan_crontab_dir(); 925 rescan_crontab_dir();
924 write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid"); 926 write_pidfile(CONFIG_PID_FILE_PATH "/crond.pid");
925 927
@@ -932,14 +934,14 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
932 time_t t1; 934 time_t t1;
933 long dt; 935 long dt;
934 936
935 t1 = t2;
936
937 /* Synchronize to 1 minute, minimum 1 second */ 937 /* Synchronize to 1 minute, minimum 1 second */
938 sleep(sleep_time - (time(NULL) % sleep_time) + 1); 938 t1 = t2;
939 939 sleep(sleep_time - (time(NULL) % sleep_time));
940 t2 = time(NULL); 940 t2 = time(NULL);
941 dt = (long)t2 - (long)t1; 941 dt = (long)t2 - (long)t1;
942 942
943 reopen_logfile_to_stderr();
944
943 /* 945 /*
944 * The file 'cron.update' is checked to determine new cron 946 * The file 'cron.update' is checked to determine new cron
945 * jobs. The directory is rescanned once an hour to deal 947 * jobs. The directory is rescanned once an hour to deal
@@ -967,10 +969,9 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
967 rescan_crontab_dir(); 969 rescan_crontab_dir();
968 } 970 }
969 process_cron_update_file(); 971 process_cron_update_file();
970 if (DebugOpt) 972 log5("wakeup dt=%ld", dt);
971 crondlog(LVL5 "wakeup dt=%ld", dt);
972 if (dt < -60 * 60 || dt > 60 * 60) { 973 if (dt < -60 * 60 || dt > 60 * 60) {
973 crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); 974 bb_error_msg("time disparity of %ld minutes detected", dt / 60);
974 /* and we do not run any jobs in this case */ 975 /* and we do not run any jobs in this case */
975 } else if (dt > 0) { 976 } else if (dt > 0) {
976 /* Usual case: time advances forward, as expected */ 977 /* Usual case: time advances forward, as expected */