diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-08 04:07:54 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-08 04:07:54 +0200 |
| commit | dfc870fab711b3ee85341f8cd8e7c8e0799d2da7 (patch) | |
| tree | c5c3241d76a5c759c009324bd025f5da2bb09d87 /miscutils | |
| parent | 4a09aefae2523bf242039e45c9f85bd1f35b72ad (diff) | |
| download | busybox-w32-dfc870fab711b3ee85341f8cd8e7c8e0799d2da7.tar.gz busybox-w32-dfc870fab711b3ee85341f8cd8e7c8e0799d2da7.tar.bz2 busybox-w32-dfc870fab711b3ee85341f8cd8e7c8e0799d2da7.zip | |
crond: check mtime on crontab dir every minute, and reread if changed
function old new delta
crond_main 1417 1460 +43
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/crond.c | 75 |
1 files changed, 36 insertions, 39 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c index 06d72ced9..481830f4d 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
| @@ -87,6 +87,7 @@ enum { | |||
| 87 | 87 | ||
| 88 | struct globals { | 88 | struct globals { |
| 89 | unsigned LogLevel; /* = 8; */ | 89 | unsigned LogLevel; /* = 8; */ |
| 90 | time_t CDir_mtime; | ||
| 90 | const char *LogFile; | 91 | const char *LogFile; |
| 91 | const char *CDir; /* = CRONTABS; */ | 92 | const char *CDir; /* = CRONTABS; */ |
| 92 | CronFile *FileBase; | 93 | CronFile *FileBase; |
| @@ -96,15 +97,9 @@ struct globals { | |||
| 96 | #endif | 97 | #endif |
| 97 | } FIX_ALIASING; | 98 | } FIX_ALIASING; |
| 98 | #define G (*(struct globals*)&bb_common_bufsiz1) | 99 | #define G (*(struct globals*)&bb_common_bufsiz1) |
| 99 | #define LogLevel (G.LogLevel ) | ||
| 100 | #define LogFile (G.LogFile ) | ||
| 101 | #define CDir (G.CDir ) | ||
| 102 | #define FileBase (G.FileBase ) | ||
| 103 | #define env_var_user (G.env_var_user ) | ||
| 104 | #define env_var_home (G.env_var_home ) | ||
| 105 | #define INIT_G() do { \ | 100 | #define INIT_G() do { \ |
| 106 | LogLevel = 8; \ | 101 | G.LogLevel = 8; \ |
| 107 | CDir = CRONTABS; \ | 102 | G.CDir = CRONTABS; \ |
| 108 | } while (0) | 103 | } while (0) |
| 109 | 104 | ||
| 110 | 105 | ||
| @@ -124,12 +119,12 @@ static void crondlog(const char *ctl, ...) | |||
| 124 | int level = (ctl[0] & 0x1f); | 119 | int level = (ctl[0] & 0x1f); |
| 125 | 120 | ||
| 126 | va_start(va, ctl); | 121 | va_start(va, ctl); |
| 127 | if (level >= (int)LogLevel) { | 122 | if (level >= (int)G.LogLevel) { |
| 128 | /* Debug mode: all to (non-redirected) stderr, */ | 123 | /* Debug mode: all to (non-redirected) stderr, */ |
| 129 | /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */ | 124 | /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */ |
| 130 | if (!DebugOpt && LogFile) { | 125 | if (!DebugOpt && G.LogFile) { |
| 131 | /* Otherwise (log to file): we reopen log file at every write: */ | 126 | /* Otherwise (log to file): we reopen log file at every write: */ |
| 132 | int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0666); | 127 | int logfd = open3_or_warn(G.LogFile, O_WRONLY | O_CREAT | O_APPEND, 0666); |
| 133 | if (logfd >= 0) | 128 | if (logfd >= 0) |
| 134 | xmove_fd(logfd, STDERR_FILENO); | 129 | xmove_fd(logfd, STDERR_FILENO); |
| 135 | } | 130 | } |
| @@ -168,10 +163,10 @@ static void safe_setenv(char **pvar_val, const char *var, const char *val) | |||
| 168 | static void SetEnv(struct passwd *pas) | 163 | static void SetEnv(struct passwd *pas) |
| 169 | { | 164 | { |
| 170 | #if SETENV_LEAKS | 165 | #if SETENV_LEAKS |
| 171 | safe_setenv(&env_var_user, "USER", pas->pw_name); | 166 | safe_setenv(&G.env_var_user, "USER", pas->pw_name); |
| 172 | safe_setenv(&env_var_home, "HOME", pas->pw_dir); | 167 | safe_setenv(&G.env_var_home, "HOME", pas->pw_dir); |
| 173 | /* if we want to set user's shell instead: */ | 168 | /* if we want to set user's shell instead: */ |
| 174 | /*safe_setenv(env_var_shell, "SHELL", pas->pw_shell);*/ | 169 | /*safe_setenv(G.env_var_shell, "SHELL", pas->pw_shell);*/ |
| 175 | #else | 170 | #else |
| 176 | xsetenv("USER", pas->pw_name); | 171 | xsetenv("USER", pas->pw_name); |
| 177 | xsetenv("HOME", pas->pw_dir); | 172 | xsetenv("HOME", pas->pw_dir); |
| @@ -308,7 +303,7 @@ static void ParseField(char *user, char *ary, int modvalue, int off, | |||
| 308 | return; | 303 | return; |
| 309 | } | 304 | } |
| 310 | 305 | ||
| 311 | if (DebugOpt && (LogLevel <= 5)) { /* like LVL5 */ | 306 | if (DebugOpt && (G.LogLevel <= 5)) { /* like LVL5 */ |
| 312 | /* can't use crondlog, it inserts '\n' */ | 307 | /* can't use crondlog, it inserts '\n' */ |
| 313 | int i; | 308 | int i; |
| 314 | for (i = 0; i < modvalue; ++i) | 309 | for (i = 0; i < modvalue; ++i) |
| @@ -351,7 +346,7 @@ static void FixDayDow(CronLine *line) | |||
| 351 | */ | 346 | */ |
| 352 | static void DeleteFile(const char *userName) | 347 | static void DeleteFile(const char *userName) |
| 353 | { | 348 | { |
| 354 | CronFile **pfile = &FileBase; | 349 | CronFile **pfile = &G.FileBase; |
| 355 | CronFile *file; | 350 | CronFile *file; |
| 356 | 351 | ||
| 357 | while ((file = *pfile) != NULL) { | 352 | while ((file = *pfile) != NULL) { |
| @@ -462,8 +457,8 @@ static void SynchronizeFile(const char *fileName) | |||
| 462 | } | 457 | } |
| 463 | *pline = NULL; | 458 | *pline = NULL; |
| 464 | 459 | ||
| 465 | file->cf_Next = FileBase; | 460 | file->cf_Next = G.FileBase; |
| 466 | FileBase = file; | 461 | G.FileBase = file; |
| 467 | 462 | ||
| 468 | if (maxLines == 0) { | 463 | if (maxLines == 0) { |
| 469 | crondlog(WARN9 "user %s: too many lines", fileName); | 464 | crondlog(WARN9 "user %s: too many lines", fileName); |
| @@ -493,7 +488,7 @@ static void SynchronizeDir(void) | |||
| 493 | CronFile *file; | 488 | CronFile *file; |
| 494 | /* Attempt to delete the database. */ | 489 | /* Attempt to delete the database. */ |
| 495 | again: | 490 | again: |
| 496 | for (file = FileBase; file; file = file->cf_Next) { | 491 | for (file = G.FileBase; file; file = file->cf_Next) { |
| 497 | if (!file->cf_Deleted) { | 492 | if (!file->cf_Deleted) { |
| 498 | DeleteFile(file->cf_User); | 493 | DeleteFile(file->cf_User); |
| 499 | goto again; | 494 | goto again; |
| @@ -509,8 +504,8 @@ static void SynchronizeDir(void) | |||
| 509 | * scan directory and add associated users | 504 | * scan directory and add associated users |
| 510 | */ | 505 | */ |
| 511 | unlink(CRONUPDATE); | 506 | unlink(CRONUPDATE); |
| 512 | if (chdir(CDir) < 0) { | 507 | if (chdir(G.CDir) < 0) { |
| 513 | crondlog(DIE9 "chdir(%s)", CDir); | 508 | crondlog(DIE9 "chdir(%s)", G.CDir); |
| 514 | } | 509 | } |
| 515 | { | 510 | { |
| 516 | DIR *dir = opendir("."); | 511 | DIR *dir = opendir("."); |
| @@ -537,9 +532,8 @@ static void SynchronizeDir(void) | |||
| 537 | * period is about a minute (one scan). Worst case it will be one | 532 | * period is about a minute (one scan). Worst case it will be one |
| 538 | * hour (60 scans). | 533 | * hour (60 scans). |
| 539 | */ | 534 | */ |
| 540 | static int TestJobs(time_t t1, time_t t2) | 535 | static void TestJobs(time_t t1, time_t t2) |
| 541 | { | 536 | { |
| 542 | int nJobs = 0; | ||
| 543 | time_t t; | 537 | time_t t; |
| 544 | 538 | ||
| 545 | /* Find jobs > t1 and <= t2 */ | 539 | /* Find jobs > t1 and <= t2 */ |
| @@ -553,7 +547,7 @@ static int TestJobs(time_t t1, time_t t2) | |||
| 553 | continue; | 547 | continue; |
| 554 | 548 | ||
| 555 | ptm = localtime(&t); | 549 | ptm = localtime(&t); |
| 556 | for (file = FileBase; file; file = file->cf_Next) { | 550 | for (file = G.FileBase; file; file = file->cf_Next) { |
| 557 | if (DebugOpt) | 551 | if (DebugOpt) |
| 558 | crondlog(LVL5 "file %s:", file->cf_User); | 552 | crondlog(LVL5 "file %s:", file->cf_User); |
| 559 | if (file->cf_Deleted) | 553 | if (file->cf_Deleted) |
| @@ -575,13 +569,11 @@ static int TestJobs(time_t t1, time_t t2) | |||
| 575 | } else if (line->cl_Pid == 0) { | 569 | } else if (line->cl_Pid == 0) { |
| 576 | line->cl_Pid = -1; | 570 | line->cl_Pid = -1; |
| 577 | file->cf_Ready = 1; | 571 | file->cf_Ready = 1; |
| 578 | ++nJobs; | ||
| 579 | } | 572 | } |
| 580 | } | 573 | } |
| 581 | } | 574 | } |
| 582 | } | 575 | } |
| 583 | } | 576 | } |
| 584 | return nJobs; | ||
| 585 | } | 577 | } |
| 586 | 578 | ||
| 587 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | 579 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
| @@ -650,7 +642,7 @@ static int CheckJobs(void) | |||
| 650 | CronLine *line; | 642 | CronLine *line; |
| 651 | int nStillRunning = 0; | 643 | int nStillRunning = 0; |
| 652 | 644 | ||
| 653 | for (file = FileBase; file; file = file->cf_Next) { | 645 | for (file = G.FileBase; file; file = file->cf_Next) { |
| 654 | if (file->cf_Running) { | 646 | if (file->cf_Running) { |
| 655 | file->cf_Running = 0; | 647 | file->cf_Running = 0; |
| 656 | 648 | ||
| @@ -819,7 +811,7 @@ static void RunJobs(void) | |||
| 819 | CronFile *file; | 811 | CronFile *file; |
| 820 | CronLine *line; | 812 | CronLine *line; |
| 821 | 813 | ||
| 822 | for (file = FileBase; file; file = file->cf_Next) { | 814 | for (file = G.FileBase; file; file = file->cf_Next) { |
| 823 | if (!file->cf_Ready) | 815 | if (!file->cf_Ready) |
| 824 | continue; | 816 | continue; |
| 825 | 817 | ||
| @@ -854,9 +846,9 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 854 | opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l") | 846 | opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l") |
| 855 | ":l+:d+"; /* -l and -d have numeric param */ | 847 | ":l+:d+"; /* -l and -d have numeric param */ |
| 856 | opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"), | 848 | opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"), |
| 857 | &LogLevel, &LogFile, &CDir | 849 | &G.LogLevel, &G.LogFile, &G.CDir |
| 858 | IF_FEATURE_CROND_D(,&LogLevel)); | 850 | IF_FEATURE_CROND_D(,&G.LogLevel)); |
| 859 | /* both -d N and -l N set the same variable: LogLevel */ | 851 | /* both -d N and -l N set the same variable: G.LogLevel */ |
| 860 | 852 | ||
| 861 | if (!(opts & OPT_f)) { | 853 | if (!(opts & OPT_f)) { |
| 862 | /* close stdin, stdout, stderr. | 854 | /* close stdin, stdout, stderr. |
| @@ -864,30 +856,32 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 864 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | 856 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); |
| 865 | } | 857 | } |
| 866 | 858 | ||
| 867 | if (!(opts & OPT_d) && LogFile == NULL) { | 859 | if (!(opts & OPT_d) && G.LogFile == NULL) { |
| 868 | /* logging to syslog */ | 860 | /* logging to syslog */ |
| 869 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); | 861 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); |
| 870 | logmode = LOGMODE_SYSLOG; | 862 | logmode = LOGMODE_SYSLOG; |
| 871 | } | 863 | } |
| 872 | 864 | ||
| 873 | xchdir(CDir); | 865 | xchdir(G.CDir); |
| 874 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ | 866 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ |
| 875 | xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ | 867 | xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ |
| 876 | crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", LogLevel); | 868 | crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", G.LogLevel); |
| 877 | SynchronizeDir(); | 869 | SynchronizeDir(); |
| 878 | write_pidfile("/var/run/crond.pid"); | 870 | write_pidfile("/var/run/crond.pid"); |
| 879 | 871 | ||
| 880 | /* main loop - synchronize to 1 second after the minute, minimum sleep | 872 | /* Main loop */ |
| 881 | * of 1 second. */ | ||
| 882 | t2 = time(NULL); | 873 | t2 = time(NULL); |
| 883 | rescan = 60; | 874 | rescan = 60; |
| 884 | sleep_time = 60; | 875 | sleep_time = 60; |
| 885 | for (;;) { | 876 | for (;;) { |
| 877 | struct stat sbuf; | ||
| 886 | time_t t1; | 878 | time_t t1; |
| 887 | long dt; | 879 | long dt; |
| 888 | 880 | ||
| 889 | t1 = t2; | 881 | t1 = t2; |
| 890 | sleep((sleep_time + 1) - (time(NULL) % sleep_time)); | 882 | |
| 883 | /* Synchronize to 1 minute, minimum 1 second */ | ||
| 884 | sleep(sleep_time - (time(NULL) % sleep_time) + 1); | ||
| 891 | 885 | ||
| 892 | t2 = time(NULL); | 886 | t2 = time(NULL); |
| 893 | dt = (long)t2 - (long)t1; | 887 | dt = (long)t2 - (long)t1; |
| @@ -908,6 +902,10 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 908 | * When running jobs, the inequality used is greater but not | 902 | * When running jobs, the inequality used is greater but not |
| 909 | * equal to t1, and less then or equal to t2. | 903 | * equal to t1, and less then or equal to t2. |
| 910 | */ | 904 | */ |
| 905 | if (stat(G.CDir, &sbuf) == 0 && G.CDir_mtime != sbuf.st_mtime) { | ||
| 906 | G.CDir_mtime = sbuf.st_mtime; | ||
| 907 | rescan = 1; | ||
| 908 | } | ||
| 911 | if (--rescan == 0) { | 909 | if (--rescan == 0) { |
| 912 | rescan = 60; | 910 | rescan = 60; |
| 913 | SynchronizeDir(); | 911 | SynchronizeDir(); |
| @@ -919,10 +917,9 @@ int crond_main(int argc UNUSED_PARAM, char **argv) | |||
| 919 | crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); | 917 | crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); |
| 920 | /* and we do not run any jobs in this case */ | 918 | /* and we do not run any jobs in this case */ |
| 921 | } else if (dt > 0) { | 919 | } else if (dt > 0) { |
| 922 | /* Usual case: time advances forwad, as expected */ | 920 | /* Usual case: time advances forward, as expected */ |
| 923 | TestJobs(t1, t2); | 921 | TestJobs(t1, t2); |
| 924 | RunJobs(); | 922 | RunJobs(); |
| 925 | sleep(5); | ||
| 926 | if (CheckJobs() > 0) { | 923 | if (CheckJobs() > 0) { |
| 927 | sleep_time = 10; | 924 | sleep_time = 10; |
| 928 | } else { | 925 | } else { |
