diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2001-02-19 14:33:34 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2001-02-19 14:33:34 +0000 |
commit | 04609c6ee5fd12235dc5fc6072e88a28c7e843d9 (patch) | |
tree | 9d0a1c4a333c9b4b93de6b6e11a882ab9743a8c0 | |
parent | 3e1b8517b46b8cee2477f082a9a3d883b85ce2fa (diff) |
Normalize the time in minutes to GMT so we can really catch DST changes
(since time() does not change during a DST switch). This makes cron
correctly detect DST changes. It does not fix the problem of wildcard
jobs running multiple times. Also, don't rely on tm_gmtoff since that
is non-standard (but use it when we have it).
-rw-r--r-- | usr.sbin/cron/config.h | 4 | ||||
-rw-r--r-- | usr.sbin/cron/cron.c | 70 | ||||
-rw-r--r-- | usr.sbin/cron/funcs.h | 4 | ||||
-rw-r--r-- | usr.sbin/cron/globals.h | 5 | ||||
-rw-r--r-- | usr.sbin/cron/misc.c | 46 | ||||
-rw-r--r-- | usr.sbin/cron/structs.h | 4 |
6 files changed, 93 insertions, 40 deletions
diff --git a/usr.sbin/cron/config.h b/usr.sbin/cron/config.h index 1fe14732974..a0bd8d994c9 100644 --- a/usr.sbin/cron/config.h +++ b/usr.sbin/cron/config.h @@ -1,4 +1,4 @@ -/* $OpenBSD: config.h,v 1.8 2001/02/18 20:28:45 millert Exp $ */ +/* $OpenBSD: config.h,v 1.9 2001/02/19 14:33:32 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved @@ -86,6 +86,8 @@ #define CAPITALIZE_FOR_PS /*-*/ +#define HAVE_TM_GMTOFF /*-*/ + /* if your OS supports a BSD-style login.conf file */ #define LOGIN_CAP /*-*/ diff --git a/usr.sbin/cron/cron.c b/usr.sbin/cron/cron.c index b9086c8c2c0..b12cb33fc82 100644 --- a/usr.sbin/cron/cron.c +++ b/usr.sbin/cron/cron.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cron.c,v 1.10 2001/02/18 19:48:31 millert Exp $ */ +/* $OpenBSD: cron.c,v 1.11 2001/02/19 14:33:32 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved */ @@ -21,7 +21,7 @@ */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$OpenBSD: cron.c,v 1.10 2001/02/18 19:48:31 millert Exp $"; +static char rcsid[] = "$OpenBSD: cron.c,v 1.11 2001/02/19 14:33:32 millert Exp $"; #endif #define MAIN_PROGRAM @@ -30,15 +30,16 @@ static char rcsid[] = "$OpenBSD: cron.c,v 1.10 2001/02/18 19:48:31 millert Exp $ static void usage(void), run_reboot_jobs(cron_db *), - find_jobs __P((time_min, cron_db *, int, int)), - set_time __P((void)), - cron_sleep __P((time_min)), + find_jobs __P((int, cron_db *, int, int)), + set_time __P((int)), + cron_sleep __P((int)), sigchld_handler(int), sighup_handler(int), sigchld_reaper(void), parse_args(int c, char *v[]); static int got_sighup, got_sigchld; +static int timeRunning, virtualTime, clockTime; static void usage(void) { @@ -115,13 +116,13 @@ main(int argc, char *argv[]) { database.tail = NULL; database.mtime = (time_t) 0; load_database(&database); - set_time(); + set_time(1); run_reboot_jobs(&database); timeRunning = virtualTime = clockTime; /* * Too many clocks, not enough time (Al. Einstein) - * These clocks are in minutes since the epoch (time()/60). + * These clocks are in minutes since the epoch, adjusted for timezone. * virtualTime: is the time it *would* be if we woke up * promptly and nobody ever changed the clock. It is * monotonically increasing... unless a timejump happens. @@ -130,7 +131,7 @@ main(int argc, char *argv[]) { * clockTime: is the time when set_time was last called. */ while (TRUE) { - time_min timeDiff; + int timeDiff; int wakeupKind; if (got_sighup) { @@ -146,7 +147,7 @@ main(int argc, char *argv[]) { /* ... wait for the time (in minutes) to change ... */ do { cron_sleep(timeRunning + 1); - set_time(); + set_time(0); } while (clockTime == timeRunning); timeRunning = clockTime; @@ -179,14 +180,14 @@ main(int argc, char *argv[]) { * minute until caught up. */ Debug(DSCH, ("[%d], normal case %d minutes to go\n", - getpid(), timeRunning - virtualTime)) + getpid(), timeDiff)) do { if (job_runqueue()) sleep(10); virtualTime++; find_jobs(virtualTime, &database, TRUE, TRUE); - } while (virtualTime< timeRunning); + } while (virtualTime < timeRunning); break; case 2: @@ -202,7 +203,7 @@ main(int argc, char *argv[]) { * housekeeping. */ Debug(DSCH, ("[%d], DST begins %d minutes to go\n", - getpid(), timeRunning - virtualTime)) + getpid(), timeDiff)) /* run wildcard jobs for current minute */ find_jobs(timeRunning, &database, TRUE, FALSE); @@ -213,7 +214,7 @@ main(int argc, char *argv[]) { virtualTime++; find_jobs(virtualTime, &database, FALSE, TRUE); - set_time(); + set_time(0); } while (virtualTime< timeRunning && clockTime == timeRunning); break; @@ -221,14 +222,14 @@ main(int argc, char *argv[]) { case 0: /* * case 3: timeDiff is a small or medium-sized - * negative num, eg. because of DST ending just - * run the wildcard jobs. The fixed-time jobs - * probably have already run, and should not be - * repeated. Virtual time does not change until - * we are caught up. + * negative num, eg. because of DST ending. + * Just run the wildcard jobs. The fixed-time + * jobs probably have already run, and should + * not be repeated. Virtual time does not + * change until we are caught up. */ Debug(DSCH, ("[%d], DST ends %d minutes to go\n", - getpid(), virtualTime - timeRunning)) + getpid(), timeDiff)) find_jobs(timeRunning, &database, TRUE, FALSE); break; default: @@ -262,9 +263,9 @@ run_reboot_jobs(cron_db *db) { } static void -find_jobs(time_min vtime, cron_db *db, int doWild, int doNonWild) { +find_jobs(int vtime, cron_db *db, int doWild, int doNonWild) { time_t virtualSecond = vtime * SECONDS_PER_MINUTE; - struct tm *tm = localtime(&virtualSecond); + struct tm *tm = gmtime(&virtualSecond); int minute, hour, dom, month, dow; user *u; entry *e; @@ -311,20 +312,35 @@ find_jobs(time_min vtime, cron_db *db, int doWild, int doNonWild) { * Note that clockTime is a unix wallclock time converted to minutes. */ static void -set_time(void) { - - StartTime = time((time_t *)0); - clockTime = StartTime / (unsigned long)SECONDS_PER_MINUTE; +set_time(int initialize) { + struct tm *tm; + static long gmtoff; + static int isdst; + + StartTime = time(NULL); + + /* We adjust the time to GMT so we can catch DST changes. */ + tm = localtime(&StartTime); + if (initialize || tm->tm_isdst != isdst) { + isdst = tm->tm_isdst; + gmtoff = get_gmtoff(&StartTime); + } + clockTime = (StartTime + gmtoff) / (time_t)SECONDS_PER_MINUTE; } /* * Try to just hit the next minute. */ static void -cron_sleep(time_min target) { +cron_sleep(int target) { + time_t t; + struct tm *tm; int seconds_to_wait; - seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - time(NULL)) + 1; + t = time(NULL); + tm = localtime(&t); + t += tm->tm_gmtoff; + seconds_to_wait = (int)(target * SECONDS_PER_MINUTE - t) + 1; Debug(DSCH, ("[%ld] Target time=%ld, sec-to-wait=%d\n", (long)getpid(), (long)target*SECONDS_PER_MINUTE, seconds_to_wait)) diff --git a/usr.sbin/cron/funcs.h b/usr.sbin/cron/funcs.h index 4e2e0289b89..20ff142b460 100644 --- a/usr.sbin/cron/funcs.h +++ b/usr.sbin/cron/funcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: funcs.h,v 1.1 2001/02/18 19:48:35 millert Exp $ */ +/* $OpenBSD: funcs.h,v 1.2 2001/02/19 14:33:32 millert Exp $ */ /* * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. @@ -68,3 +68,5 @@ entry *load_entry(FILE *, void (*)(), struct passwd *, char **); FILE *cron_popen(char *, char *, entry *); + +long get_gmtoff(time_t *clock); diff --git a/usr.sbin/cron/globals.h b/usr.sbin/cron/globals.h index fcbc52274b7..dfd1874cc3c 100644 --- a/usr.sbin/cron/globals.h +++ b/usr.sbin/cron/globals.h @@ -1,4 +1,4 @@ -/* $OpenBSD: globals.h,v 1.2 2001/02/18 20:14:01 millert Exp $ */ +/* $OpenBSD: globals.h,v 1.3 2001/02/19 14:33:33 millert Exp $ */ /* * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. @@ -58,9 +58,6 @@ XTRN const char *DowNames[] XTRN char *ProgramName INIT("amnesia"); XTRN int LineNumber INIT(0); XTRN time_t StartTime INIT(0); -XTRN time_min timeRunning INIT(0); -XTRN time_min virtualTime INIT(0); -XTRN time_min clockTime INIT(0); #if DEBUGGING XTRN int DebugFlags INIT(0); diff --git a/usr.sbin/cron/misc.c b/usr.sbin/cron/misc.c index 07ca1452e0c..7764aeb9fd2 100644 --- a/usr.sbin/cron/misc.c +++ b/usr.sbin/cron/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.8 2001/02/18 19:48:35 millert Exp $ */ +/* $OpenBSD: misc.c,v 1.9 2001/02/19 14:33:33 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * All rights reserved */ @@ -21,7 +21,7 @@ */ #if !defined(lint) && !defined(LINT) -static char rcsid[] = "$OpenBSD: misc.c,v 1.8 2001/02/18 19:48:35 millert Exp $"; +static char rcsid[] = "$OpenBSD: misc.c,v 1.9 2001/02/19 14:33:33 millert Exp $"; #endif /* vix 26jan87 [RCS has the rest of the log] @@ -692,8 +692,9 @@ arpadate(clock) static char ret[64]; /* zone name might be >3 chars */ char *qmark; size_t len; - int hours = tm->tm_gmtoff / 3600; - int minutes = (tm->tm_gmtoff - (hours * 3600)) / 60; + long gmtoff = get_gmtoff(&t); + int hours = gmtoff / 3600; + int minutes = (gmtoff - (hours * 3600)) / 60; if (minutes < 0) minutes = -minutes; @@ -722,3 +723,40 @@ int swap_uids_back() { return (seteuid(save_euid)); } int swap_uids() { return (setreuid(geteuid(), getuid())); } int swap_uids_back() { return (swap_uids()); } #endif /*HAVE_SAVED_UIDS*/ + +/* Return the offset from GMT in seconds (algorithm taken from sendmail). */ +#ifdef HAVE_TM_GMTOFF +long get_gmtoff(time_t *clock) +{ + struct tm *tm; + + tm = localtime(clock); + return (tm->tm_gmtoff); +} +#else +long get_gmtoff(time_t *clock) +{ + struct tm local; + struct tm *gmt; + long offset; + + local = *localtime(clock); + gmt = gmtime(clock); + + offset = (local.tm_sec - gmt->tm_sec) + + ((local.tm_min - gmt->tm_min) * 60) + + ((local.tm_hour - gmt->tm_hour) * 3600); + + /* Timezone may cause year rollover to happen on a different day. */ + if (local.tm_year < gmt->tm_year) + offset -= 24 * 3600; + else if (local.tm_year > gmt->tm_year) + offset -= 24 * 3600; + else if (local.tm_yday < gmt->tm_yday) + offset -= 24 * 3600; + else if (local.tm_yday > gmt->tm_yday) + offset += 24 * 3600; + + return (offset); +} +#endif /* HAVE_TM_GMTOFF */ diff --git a/usr.sbin/cron/structs.h b/usr.sbin/cron/structs.h index 7dd49ae87d7..f0a4aee5f10 100644 --- a/usr.sbin/cron/structs.h +++ b/usr.sbin/cron/structs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: structs.h,v 1.1 2001/02/18 19:48:36 millert Exp $ */ +/* $OpenBSD: structs.h,v 1.2 2001/02/19 14:33:33 millert Exp $ */ /* * Copyright (c) 1997,2000 by Internet Software Consortium, Inc. @@ -17,8 +17,6 @@ * SOFTWARE. */ -typedef int time_min; /* time in minutes */ - typedef struct _entry { struct _entry *next; uid_t uid; |