diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-08 04:07:15 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-08 04:07:15 +0200 |
| commit | 4a09aefae2523bf242039e45c9f85bd1f35b72ad (patch) | |
| tree | 16f529eb0b832445c588893fefbacd938d4a8437 /miscutils | |
| parent | 9388b4e72051b031b84a1345cc763757dbd9a699 (diff) | |
| download | busybox-w32-4a09aefae2523bf242039e45c9f85bd1f35b72ad.tar.gz busybox-w32-4a09aefae2523bf242039e45c9f85bd1f35b72ad.tar.bz2 busybox-w32-4a09aefae2523bf242039e45c9f85bd1f35b72ad.zip | |
crond: reorder functions to follow usual order: "main last"
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/crond.c | 452 |
1 files changed, 221 insertions, 231 deletions
diff --git a/miscutils/crond.c b/miscutils/crond.c index 49ecf745e..06d72ced9 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c | |||
| @@ -17,25 +17,25 @@ | |||
| 17 | /* glibc frees previous setenv'ed value when we do next setenv() | 17 | /* glibc frees previous setenv'ed value when we do next setenv() |
| 18 | * of the same variable. uclibc does not do this! */ | 18 | * of the same variable. uclibc does not do this! */ |
| 19 | #if (defined(__GLIBC__) && !defined(__UCLIBC__)) /* || OTHER_SAFE_LIBC... */ | 19 | #if (defined(__GLIBC__) && !defined(__UCLIBC__)) /* || OTHER_SAFE_LIBC... */ |
| 20 | #define SETENV_LEAKS 0 | 20 | # define SETENV_LEAKS 0 |
| 21 | #else | 21 | #else |
| 22 | #define SETENV_LEAKS 1 | 22 | # define SETENV_LEAKS 1 |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | #define TMPDIR CONFIG_FEATURE_CROND_DIR | 26 | #define TMPDIR CONFIG_FEATURE_CROND_DIR |
| 27 | #define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" | 27 | #define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs" |
| 28 | #ifndef SENDMAIL | 28 | #ifndef SENDMAIL |
| 29 | #define SENDMAIL "sendmail" | 29 | # define SENDMAIL "sendmail" |
| 30 | #endif | 30 | #endif |
| 31 | #ifndef SENDMAIL_ARGS | 31 | #ifndef SENDMAIL_ARGS |
| 32 | #define SENDMAIL_ARGS "-ti", NULL | 32 | # define SENDMAIL_ARGS "-ti", NULL |
| 33 | #endif | 33 | #endif |
| 34 | #ifndef CRONUPDATE | 34 | #ifndef CRONUPDATE |
| 35 | #define CRONUPDATE "cron.update" | 35 | # define CRONUPDATE "cron.update" |
| 36 | #endif | 36 | #endif |
| 37 | #ifndef MAXLINES | 37 | #ifndef MAXLINES |
| 38 | #define MAXLINES 256 /* max lines in non-root crontabs */ | 38 | # define MAXLINES 256 /* max lines in non-root crontabs */ |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | 41 | ||
| @@ -108,20 +108,6 @@ struct globals { | |||
| 108 | } while (0) | 108 | } while (0) |
| 109 | 109 | ||
| 110 | 110 | ||
| 111 | static void CheckUpdates(void); | ||
| 112 | static void SynchronizeDir(void); | ||
| 113 | static int TestJobs(time_t t1, time_t t2); | ||
| 114 | static void RunJobs(void); | ||
| 115 | static int CheckJobs(void); | ||
| 116 | static void RunJob(const char *user, CronLine *line); | ||
| 117 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL | ||
| 118 | static void EndJob(const char *user, CronLine *line); | ||
| 119 | #else | ||
| 120 | #define EndJob(user, line) ((line)->cl_Pid = 0) | ||
| 121 | #endif | ||
| 122 | static void DeleteFile(const char *userName); | ||
| 123 | |||
| 124 | |||
| 125 | /* 0 is the most verbose, default 8 */ | 111 | /* 0 is the most verbose, default 8 */ |
| 126 | #define LVL5 "\x05" | 112 | #define LVL5 "\x05" |
| 127 | #define LVL7 "\x07" | 113 | #define LVL7 "\x07" |
| @@ -163,101 +149,6 @@ static void crondlog(const char *ctl, ...) | |||
| 163 | exit(20); | 149 | exit(20); |
| 164 | } | 150 | } |
| 165 | 151 | ||
| 166 | int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
| 167 | int crond_main(int argc UNUSED_PARAM, char **argv) | ||
| 168 | { | ||
| 169 | time_t t2; | ||
| 170 | int rescan; | ||
| 171 | int sleep_time; | ||
| 172 | unsigned opts; | ||
| 173 | |||
| 174 | INIT_G(); | ||
| 175 | |||
| 176 | /* "-b after -f is ignored", and so on for every pair a-b */ | ||
| 177 | opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l") | ||
| 178 | ":l+:d+"; /* -l and -d have numeric param */ | ||
| 179 | opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"), | ||
| 180 | &LogLevel, &LogFile, &CDir | ||
| 181 | IF_FEATURE_CROND_D(,&LogLevel)); | ||
| 182 | /* both -d N and -l N set the same variable: LogLevel */ | ||
| 183 | |||
| 184 | if (!(opts & OPT_f)) { | ||
| 185 | /* close stdin, stdout, stderr. | ||
| 186 | * close unused descriptors - don't need them. */ | ||
| 187 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | ||
| 188 | } | ||
| 189 | |||
| 190 | if (!(opts & OPT_d) && LogFile == NULL) { | ||
| 191 | /* logging to syslog */ | ||
| 192 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); | ||
| 193 | logmode = LOGMODE_SYSLOG; | ||
| 194 | } | ||
| 195 | |||
| 196 | xchdir(CDir); | ||
| 197 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ | ||
| 198 | xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ | ||
| 199 | crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", LogLevel); | ||
| 200 | SynchronizeDir(); | ||
| 201 | write_pidfile("/var/run/crond.pid"); | ||
| 202 | |||
| 203 | /* main loop - synchronize to 1 second after the minute, minimum sleep | ||
| 204 | * of 1 second. */ | ||
| 205 | t2 = time(NULL); | ||
| 206 | rescan = 60; | ||
| 207 | sleep_time = 60; | ||
| 208 | for (;;) { | ||
| 209 | time_t t1; | ||
| 210 | long dt; | ||
| 211 | |||
| 212 | t1 = t2; | ||
| 213 | sleep((sleep_time + 1) - (time(NULL) % sleep_time)); | ||
| 214 | |||
| 215 | t2 = time(NULL); | ||
| 216 | dt = (long)t2 - (long)t1; | ||
| 217 | |||
| 218 | /* | ||
| 219 | * The file 'cron.update' is checked to determine new cron | ||
| 220 | * jobs. The directory is rescanned once an hour to deal | ||
| 221 | * with any screwups. | ||
| 222 | * | ||
| 223 | * Check for time jump. Disparities over an hour either way | ||
| 224 | * result in resynchronization. A negative disparity | ||
| 225 | * less than an hour causes us to effectively sleep until we | ||
| 226 | * match the original time (i.e. no re-execution of jobs that | ||
| 227 | * have just been run). A positive disparity less than | ||
| 228 | * an hour causes intermediate jobs to be run, but only once | ||
| 229 | * in the worst case. | ||
| 230 | * | ||
| 231 | * When running jobs, the inequality used is greater but not | ||
| 232 | * equal to t1, and less then or equal to t2. | ||
| 233 | */ | ||
| 234 | if (--rescan == 0) { | ||
| 235 | rescan = 60; | ||
| 236 | SynchronizeDir(); | ||
| 237 | } | ||
| 238 | CheckUpdates(); | ||
| 239 | if (DebugOpt) | ||
| 240 | crondlog(LVL5 "wakeup dt=%ld", dt); | ||
| 241 | if (dt < -60 * 60 || dt > 60 * 60) { | ||
| 242 | crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); | ||
| 243 | /* and we do not run any jobs in this case */ | ||
| 244 | } else if (dt > 0) { | ||
| 245 | /* Usual case: time advances forwad, as expected */ | ||
| 246 | TestJobs(t1, t2); | ||
| 247 | RunJobs(); | ||
| 248 | sleep(5); | ||
| 249 | if (CheckJobs() > 0) { | ||
| 250 | sleep_time = 10; | ||
| 251 | } else { | ||
| 252 | sleep_time = 60; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | /* else: time jumped back, do not run any jobs */ | ||
| 256 | } /* for (;;) */ | ||
| 257 | |||
| 258 | return 0; /* not reached */ | ||
| 259 | } | ||
| 260 | |||
| 261 | #if SETENV_LEAKS | 152 | #if SETENV_LEAKS |
| 262 | /* We set environment *before* vfork (because we want to use vfork), | 153 | /* We set environment *before* vfork (because we want to use vfork), |
| 263 | * so we cannot use setenv() - repeated calls to setenv() may leak memory! | 154 | * so we cannot use setenv() - repeated calls to setenv() may leak memory! |
| @@ -452,6 +343,48 @@ static void FixDayDow(CronLine *line) | |||
| 452 | } | 343 | } |
| 453 | } | 344 | } |
| 454 | 345 | ||
| 346 | /* | ||
| 347 | * DeleteFile() - delete user database | ||
| 348 | * | ||
| 349 | * Note: multiple entries for same user may exist if we were unable to | ||
| 350 | * completely delete a database due to running processes. | ||
| 351 | */ | ||
| 352 | static void DeleteFile(const char *userName) | ||
| 353 | { | ||
| 354 | CronFile **pfile = &FileBase; | ||
| 355 | CronFile *file; | ||
| 356 | |||
| 357 | while ((file = *pfile) != NULL) { | ||
| 358 | if (strcmp(userName, file->cf_User) == 0) { | ||
| 359 | CronLine **pline = &file->cf_LineBase; | ||
| 360 | CronLine *line; | ||
| 361 | |||
| 362 | file->cf_Running = 0; | ||
| 363 | file->cf_Deleted = 1; | ||
| 364 | |||
| 365 | while ((line = *pline) != NULL) { | ||
| 366 | if (line->cl_Pid > 0) { | ||
| 367 | file->cf_Running = 1; | ||
| 368 | pline = &line->cl_Next; | ||
| 369 | } else { | ||
| 370 | *pline = line->cl_Next; | ||
| 371 | free(line->cl_Shell); | ||
| 372 | free(line); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | if (file->cf_Running == 0) { | ||
| 376 | *pfile = file->cf_Next; | ||
| 377 | free(file->cf_User); | ||
| 378 | free(file); | ||
| 379 | } else { | ||
| 380 | pfile = &file->cf_Next; | ||
| 381 | } | ||
| 382 | } else { | ||
| 383 | pfile = &file->cf_Next; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 455 | static void SynchronizeFile(const char *fileName) | 388 | static void SynchronizeFile(const char *fileName) |
| 456 | { | 389 | { |
| 457 | struct parser_t *parser; | 390 | struct parser_t *parser; |
| @@ -600,51 +533,7 @@ static void SynchronizeDir(void) | |||
| 600 | } | 533 | } |
| 601 | 534 | ||
| 602 | /* | 535 | /* |
| 603 | * DeleteFile() - delete user database | 536 | * Determine which jobs need to be run. Under normal conditions, the |
| 604 | * | ||
| 605 | * Note: multiple entries for same user may exist if we were unable to | ||
| 606 | * completely delete a database due to running processes. | ||
| 607 | */ | ||
| 608 | static void DeleteFile(const char *userName) | ||
| 609 | { | ||
| 610 | CronFile **pfile = &FileBase; | ||
| 611 | CronFile *file; | ||
| 612 | |||
| 613 | while ((file = *pfile) != NULL) { | ||
| 614 | if (strcmp(userName, file->cf_User) == 0) { | ||
| 615 | CronLine **pline = &file->cf_LineBase; | ||
| 616 | CronLine *line; | ||
| 617 | |||
| 618 | file->cf_Running = 0; | ||
| 619 | file->cf_Deleted = 1; | ||
| 620 | |||
| 621 | while ((line = *pline) != NULL) { | ||
| 622 | if (line->cl_Pid > 0) { | ||
| 623 | file->cf_Running = 1; | ||
| 624 | pline = &line->cl_Next; | ||
| 625 | } else { | ||
| 626 | *pline = line->cl_Next; | ||
| 627 | free(line->cl_Shell); | ||
| 628 | free(line); | ||
| 629 | } | ||
| 630 | } | ||
| 631 | if (file->cf_Running == 0) { | ||
| 632 | *pfile = file->cf_Next; | ||
| 633 | free(file->cf_User); | ||
| 634 | free(file); | ||
| 635 | } else { | ||
| 636 | pfile = &file->cf_Next; | ||
| 637 | } | ||
| 638 | } else { | ||
| 639 | pfile = &file->cf_Next; | ||
| 640 | } | ||
| 641 | } | ||
| 642 | } | ||
| 643 | |||
| 644 | /* | ||
| 645 | * TestJobs() | ||
| 646 | * | ||
| 647 | * determine which jobs need to be run. Under normal conditions, the | ||
| 648 | * period is about a minute (one scan). Worst case it will be one | 537 | * period is about a minute (one scan). Worst case it will be one |
| 649 | * hour (60 scans). | 538 | * hour (60 scans). |
| 650 | */ | 539 | */ |
| @@ -695,35 +584,63 @@ static int TestJobs(time_t t1, time_t t2) | |||
| 695 | return nJobs; | 584 | return nJobs; |
| 696 | } | 585 | } |
| 697 | 586 | ||
| 698 | static void RunJobs(void) | 587 | #if ENABLE_FEATURE_CROND_CALL_SENDMAIL |
| 588 | static void | ||
| 589 | ForkJob(const char *user, CronLine *line, int mailFd, | ||
| 590 | const char *prog, const char *cmd, const char *arg, | ||
| 591 | const char *mail_filename); | ||
| 592 | /* | ||
| 593 | * EndJob - called when job terminates and when mail terminates | ||
| 594 | */ | ||
| 595 | static void EndJob(const char *user, CronLine *line) | ||
| 699 | { | 596 | { |
| 700 | CronFile *file; | 597 | int mailFd; |
| 701 | CronLine *line; | 598 | char mailFile[128]; |
| 599 | struct stat sbuf; | ||
| 702 | 600 | ||
| 703 | for (file = FileBase; file; file = file->cf_Next) { | 601 | /* No job */ |
| 704 | if (!file->cf_Ready) | 602 | if (line->cl_Pid <= 0) { |
| 705 | continue; | 603 | line->cl_Pid = 0; |
| 604 | return; | ||
| 605 | } | ||
| 706 | 606 | ||
| 707 | file->cf_Ready = 0; | 607 | /* |
| 708 | for (line = file->cf_LineBase; line; line = line->cl_Next) { | 608 | * End of job and no mail file |
| 709 | if (line->cl_Pid >= 0) | 609 | * End of sendmail job |
| 710 | continue; | 610 | */ |
| 611 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, line->cl_Pid); | ||
| 612 | line->cl_Pid = 0; | ||
| 711 | 613 | ||
| 712 | RunJob(file->cf_User, line); | 614 | if (line->cl_MailFlag == 0) { |
| 713 | crondlog(LVL8 "USER %s pid %3d cmd %s", | 615 | return; |
| 714 | file->cf_User, (int)line->cl_Pid, line->cl_Shell); | ||
| 715 | if (line->cl_Pid < 0) { | ||
| 716 | file->cf_Ready = 1; | ||
| 717 | } else if (line->cl_Pid > 0) { | ||
| 718 | file->cf_Running = 1; | ||
| 719 | } | ||
| 720 | } | ||
| 721 | } | 616 | } |
| 617 | line->cl_MailFlag = 0; | ||
| 618 | |||
| 619 | /* | ||
| 620 | * End of primary job - check for mail file. If size has increased and | ||
| 621 | * the file is still valid, we sendmail it. | ||
| 622 | */ | ||
| 623 | mailFd = open(mailFile, O_RDONLY); | ||
| 624 | unlink(mailFile); | ||
| 625 | if (mailFd < 0) { | ||
| 626 | return; | ||
| 627 | } | ||
| 628 | |||
| 629 | if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid | ||
| 630 | || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos | ||
| 631 | || !S_ISREG(sbuf.st_mode) | ||
| 632 | ) { | ||
| 633 | close(mailFd); | ||
| 634 | return; | ||
| 635 | } | ||
| 636 | if (line->cl_MailTo) | ||
| 637 | ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); | ||
| 722 | } | 638 | } |
| 639 | #else | ||
| 640 | # define EndJob(user, line) ((line)->cl_Pid = 0) | ||
| 641 | #endif | ||
| 723 | 642 | ||
| 724 | /* | 643 | /* |
| 725 | * CheckJobs() - check for job completion | ||
| 726 | * | ||
| 727 | * Check for job completion, return number of jobs still running after | 644 | * Check for job completion, return number of jobs still running after |
| 728 | * all done. | 645 | * all done. |
| 729 | */ | 646 | */ |
| @@ -855,55 +772,7 @@ static void RunJob(const char *user, CronLine *line) | |||
| 855 | ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile); | 772 | ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile); |
| 856 | } | 773 | } |
| 857 | 774 | ||
| 858 | /* | 775 | #else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ |
| 859 | * EndJob - called when job terminates and when mail terminates | ||
| 860 | */ | ||
| 861 | static void EndJob(const char *user, CronLine *line) | ||
| 862 | { | ||
| 863 | int mailFd; | ||
| 864 | char mailFile[128]; | ||
| 865 | struct stat sbuf; | ||
| 866 | |||
| 867 | /* No job */ | ||
| 868 | if (line->cl_Pid <= 0) { | ||
| 869 | line->cl_Pid = 0; | ||
| 870 | return; | ||
| 871 | } | ||
| 872 | |||
| 873 | /* | ||
| 874 | * End of job and no mail file | ||
| 875 | * End of sendmail job | ||
| 876 | */ | ||
| 877 | snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, line->cl_Pid); | ||
| 878 | line->cl_Pid = 0; | ||
| 879 | |||
| 880 | if (line->cl_MailFlag == 0) { | ||
| 881 | return; | ||
| 882 | } | ||
| 883 | line->cl_MailFlag = 0; | ||
| 884 | |||
| 885 | /* | ||
| 886 | * End of primary job - check for mail file. If size has increased and | ||
| 887 | * the file is still valid, we sendmail it. | ||
| 888 | */ | ||
| 889 | mailFd = open(mailFile, O_RDONLY); | ||
| 890 | unlink(mailFile); | ||
| 891 | if (mailFd < 0) { | ||
| 892 | return; | ||
| 893 | } | ||
| 894 | |||
| 895 | if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid | ||
| 896 | || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos | ||
| 897 | || !S_ISREG(sbuf.st_mode) | ||
| 898 | ) { | ||
| 899 | close(mailFd); | ||
| 900 | return; | ||
| 901 | } | ||
| 902 | if (line->cl_MailTo) | ||
| 903 | ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL); | ||
| 904 | } | ||
| 905 | |||
| 906 | #else /* crond without sendmail */ | ||
| 907 | 776 | ||
| 908 | static void RunJob(const char *user, CronLine *line) | 777 | static void RunJob(const char *user, CronLine *line) |
| 909 | { | 778 | { |
| @@ -943,4 +812,125 @@ static void RunJob(const char *user, CronLine *line) | |||
| 943 | line->cl_Pid = pid; | 812 | line->cl_Pid = pid; |
| 944 | } | 813 | } |
| 945 | 814 | ||
| 946 | #endif /* ENABLE_FEATURE_CROND_CALL_SENDMAIL */ | 815 | #endif /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */ |
| 816 | |||
| 817 | static void RunJobs(void) | ||
| 818 | { | ||
| 819 | CronFile *file; | ||
| 820 | CronLine *line; | ||
| 821 | |||
| 822 | for (file = FileBase; file; file = file->cf_Next) { | ||
| 823 | if (!file->cf_Ready) | ||
| 824 | continue; | ||
| 825 | |||
| 826 | file->cf_Ready = 0; | ||
| 827 | for (line = file->cf_LineBase; line; line = line->cl_Next) { | ||
| 828 | if (line->cl_Pid >= 0) | ||
| 829 | continue; | ||
| 830 | |||
| 831 | RunJob(file->cf_User, line); | ||
| 832 | crondlog(LVL8 "USER %s pid %3d cmd %s", | ||
| 833 | file->cf_User, (int)line->cl_Pid, line->cl_Shell); | ||
| 834 | if (line->cl_Pid < 0) { | ||
| 835 | file->cf_Ready = 1; | ||
| 836 | } else if (line->cl_Pid > 0) { | ||
| 837 | file->cf_Running = 1; | ||
| 838 | } | ||
| 839 | } | ||
| 840 | } | ||
| 841 | } | ||
| 842 | |||
| 843 | int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
| 844 | int crond_main(int argc UNUSED_PARAM, char **argv) | ||
| 845 | { | ||
| 846 | time_t t2; | ||
| 847 | int rescan; | ||
| 848 | int sleep_time; | ||
| 849 | unsigned opts; | ||
| 850 | |||
| 851 | INIT_G(); | ||
| 852 | |||
| 853 | /* "-b after -f is ignored", and so on for every pair a-b */ | ||
| 854 | 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 */ | ||
| 856 | opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"), | ||
| 857 | &LogLevel, &LogFile, &CDir | ||
| 858 | IF_FEATURE_CROND_D(,&LogLevel)); | ||
| 859 | /* both -d N and -l N set the same variable: LogLevel */ | ||
| 860 | |||
| 861 | if (!(opts & OPT_f)) { | ||
| 862 | /* close stdin, stdout, stderr. | ||
| 863 | * close unused descriptors - don't need them. */ | ||
| 864 | bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); | ||
| 865 | } | ||
| 866 | |||
| 867 | if (!(opts & OPT_d) && LogFile == NULL) { | ||
| 868 | /* logging to syslog */ | ||
| 869 | openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON); | ||
| 870 | logmode = LOGMODE_SYSLOG; | ||
| 871 | } | ||
| 872 | |||
| 873 | xchdir(CDir); | ||
| 874 | //signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */ | ||
| 875 | xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */ | ||
| 876 | crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", LogLevel); | ||
| 877 | SynchronizeDir(); | ||
| 878 | write_pidfile("/var/run/crond.pid"); | ||
| 879 | |||
| 880 | /* main loop - synchronize to 1 second after the minute, minimum sleep | ||
| 881 | * of 1 second. */ | ||
| 882 | t2 = time(NULL); | ||
| 883 | rescan = 60; | ||
| 884 | sleep_time = 60; | ||
| 885 | for (;;) { | ||
| 886 | time_t t1; | ||
| 887 | long dt; | ||
| 888 | |||
| 889 | t1 = t2; | ||
| 890 | sleep((sleep_time + 1) - (time(NULL) % sleep_time)); | ||
| 891 | |||
| 892 | t2 = time(NULL); | ||
| 893 | dt = (long)t2 - (long)t1; | ||
| 894 | |||
| 895 | /* | ||
| 896 | * The file 'cron.update' is checked to determine new cron | ||
| 897 | * jobs. The directory is rescanned once an hour to deal | ||
| 898 | * with any screwups. | ||
| 899 | * | ||
| 900 | * Check for time jump. Disparities over an hour either way | ||
| 901 | * result in resynchronization. A negative disparity | ||
| 902 | * less than an hour causes us to effectively sleep until we | ||
| 903 | * match the original time (i.e. no re-execution of jobs that | ||
| 904 | * have just been run). A positive disparity less than | ||
| 905 | * an hour causes intermediate jobs to be run, but only once | ||
| 906 | * in the worst case. | ||
| 907 | * | ||
| 908 | * When running jobs, the inequality used is greater but not | ||
| 909 | * equal to t1, and less then or equal to t2. | ||
| 910 | */ | ||
| 911 | if (--rescan == 0) { | ||
| 912 | rescan = 60; | ||
| 913 | SynchronizeDir(); | ||
| 914 | } | ||
| 915 | CheckUpdates(); | ||
| 916 | if (DebugOpt) | ||
| 917 | crondlog(LVL5 "wakeup dt=%ld", dt); | ||
| 918 | if (dt < -60 * 60 || dt > 60 * 60) { | ||
| 919 | crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60); | ||
| 920 | /* and we do not run any jobs in this case */ | ||
| 921 | } else if (dt > 0) { | ||
| 922 | /* Usual case: time advances forwad, as expected */ | ||
| 923 | TestJobs(t1, t2); | ||
| 924 | RunJobs(); | ||
| 925 | sleep(5); | ||
| 926 | if (CheckJobs() > 0) { | ||
| 927 | sleep_time = 10; | ||
| 928 | } else { | ||
| 929 | sleep_time = 60; | ||
| 930 | } | ||
| 931 | } | ||
| 932 | /* else: time jumped back, do not run any jobs */ | ||
| 933 | } /* for (;;) */ | ||
| 934 | |||
| 935 | return 0; /* not reached */ | ||
| 936 | } | ||
