Fix error with multiply 'adjkerntz -a' copies running.

Manage adjkerntz kernel variable even for UTC clocks.
Code cleanup.
This commit is contained in:
Andrey A. Chernov 1996-04-05 03:40:55 +00:00
parent fe0d5f43c5
commit 9243a8f346
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=15046

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 1993, 1994, 1995 by Andrey A. Chernov, Moscow, Russia. * Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -26,7 +26,7 @@
#ifndef lint #ifndef lint
char copyright[] = char copyright[] =
"@(#)Copyright (C) 1993, 1994, 1995 by Andrey A. Chernov, Moscow, Russia.\n\ "@(#)Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.\n\
All rights reserved.\n"; All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
@ -54,6 +54,11 @@ char copyright[] =
#include "pathnames.h" #include "pathnames.h"
/*#define DEBUG*/ /*#define DEBUG*/
#define True (1)
#define False (0)
#define Unknown (-1)
#define REPORT_PERIOD (30*60) #define REPORT_PERIOD (30*60)
void fake() {} void fake() {}
@ -65,41 +70,44 @@ int main(argc, argv)
struct tm local, utc; struct tm local, utc;
struct timeval tv, *stv; struct timeval tv, *stv;
struct timezone tz, *stz; struct timezone tz, *stz;
int kern_offset; int kern_offset, wall_clock, disrtcset;
size_t len; size_t len;
int mib[2]; int mib[2];
/* Avoid time_t here, can be unsigned long or worse */ /* Avoid time_t here, can be unsigned long or worse */
long offset, utcsec, localsec, diff; long offset, utcsec, localsec, diff;
time_t initial_sec, final_sec; time_t initial_sec, final_sec;
int ch, init = -1; int ch;
int initial_isdst = -1, final_isdst, looping; int initial_isdst = -1, final_isdst;
int disrtcset, need_restore = 0; int need_restore = False, sleep_mode = False, looping,
init = Unknown;
sigset_t mask, emask; sigset_t mask, emask;
while ((ch = getopt(argc, argv, "ai")) != EOF) while ((ch = getopt(argc, argv, "ais")) != EOF)
switch((char)ch) { switch((char)ch) {
case 'i': /* initial call, save offset */ case 'i': /* initial call, save offset */
if (init != -1) if (init != Unknown)
goto usage; goto usage;
init = 1; init = True;
break; break;
case 'a': /* adjustment call, use saved offset */ case 'a': /* adjustment call, use saved offset */
if (init != -1) if (init != Unknown)
goto usage; goto usage;
init = 0; init = False;
break;
case 's':
sleep_mode = True;
break; break;
default: default:
usage: usage:
fprintf(stderr, "Usage:\n\ fprintf(stderr, "Usage:\n\
\tadjkerntz -i\t(initial call from /etc/rc)\n\ \tadjkerntz -i\t\t(initial call from /etc/rc)\n\
\tadjkerntz -a\t(adjustment call from crontab)\n"); \tadjkerntz -a [-s]\t(adjustment call, -s for sleep/retry mode)\n");
return 2; return 2;
} }
if (init == -1) if (init == Unknown)
goto usage; goto usage;
if (init)
if (access(_PATH_CLOCK, F_OK)) sleep_mode = True;
return 0;
sigemptyset(&mask); sigemptyset(&mask);
sigemptyset(&emask); sigemptyset(&emask);
@ -114,15 +122,26 @@ int main(argc, argv)
return 1; return 1;
} }
again: if (init)
wall_clock = (access(_PATH_CLOCK, F_OK) == 0);
else {
mib[0] = CTL_MACHDEP;
mib[1] = CPU_WALLCLOCK;
len = sizeof(wall_clock);
if (sysctl(mib, 2, &wall_clock, &len, NULL, 0) == -1) {
syslog(LOG_ERR, "sysctl(get_wallclock): %m");
return 1;
}
}
again:
(void) sigprocmask(SIG_BLOCK, &mask, NULL); (void) sigprocmask(SIG_BLOCK, &mask, NULL);
(void) signal(SIGTERM, fake); (void) signal(SIGTERM, fake);
diff = 0; diff = 0;
stv = NULL; stv = NULL;
stz = NULL; stz = NULL;
looping = 0; looping = False;
mib[0] = CTL_MACHDEP; mib[0] = CTL_MACHDEP;
mib[1] = CPU_ADJKERNTZ; mib[1] = CPU_ADJKERNTZ;
@ -161,7 +180,15 @@ int main(argc, argv)
* middle of the nonexistent hour means 3:30 am. * middle of the nonexistent hour means 3:30 am.
*/ */
syslog(LOG_WARNING, syslog(LOG_WARNING,
"Nonexistent local time -- will retry after %d secs", REPORT_PERIOD); "Warning: nonexistent %s time.",
utcsec == -1 && localsec == -1 ? "UTC time and local" :
utcsec == -1 ? "UTC" : "local");
if (!sleep_mode) {
syslog(LOG_WARNING, "Giving up.");
return 1;
}
syslog(LOG_WARNING, "Will retry after %d minutes.",
REPORT_PERIOD / 60);
(void) signal(SIGTERM, SIG_DFL); (void) signal(SIGTERM, SIG_DFL);
(void) sigprocmask(SIG_UNBLOCK, &mask, NULL); (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
(void) sleep(REPORT_PERIOD); (void) sleep(REPORT_PERIOD);
@ -191,7 +218,7 @@ int main(argc, argv)
if (diff > 0 && initial_isdst != final_isdst) { if (diff > 0 && initial_isdst != final_isdst) {
if (looping) if (looping)
goto bad_final; goto bad_final;
looping++; looping = True;
initial_isdst = final_isdst; initial_isdst = final_isdst;
goto recalculate; goto recalculate;
} }
@ -207,7 +234,15 @@ int main(argc, argv)
* but perhaps we never get here. * but perhaps we never get here.
*/ */
syslog(LOG_WARNING, syslog(LOG_WARNING,
"Nonexistent (final) local time -- will retry after %d secs", REPORT_PERIOD); "Warning: nonexistent final %s time.",
utcsec == -1 && localsec == -1 ? "UTC time and local" :
utcsec == -1 ? "UTC" : "local");
if (!sleep_mode) {
syslog(LOG_WARNING, "Giving up.");
return 1;
}
syslog(LOG_WARNING, "Will retry after %d minutes.",
REPORT_PERIOD / 60);
(void) signal(SIGTERM, SIG_DFL); (void) signal(SIGTERM, SIG_DFL);
(void) sigprocmask(SIG_UNBLOCK, &mask, NULL); (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
(void) sleep(REPORT_PERIOD); (void) sleep(REPORT_PERIOD);
@ -237,9 +272,15 @@ int main(argc, argv)
tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */ tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */
stz = &tz; stz = &tz;
} }
if (!wall_clock && stz == NULL)
stv = NULL;
/* if init and something will be changed, don't touch RTC at all */ /* if init or UTC clock and offset/date will be changed, */
if (init && (stv != NULL || kern_offset != offset)) { /* disable RTC modification for a while. */
if ( (init && stv != NULL)
|| ((init || !wall_clock) && kern_offset != offset)
) {
mib[0] = CTL_MACHDEP; mib[0] = CTL_MACHDEP;
mib[1] = CPU_DISRTCSET; mib[1] = CPU_DISRTCSET;
len = sizeof(disrtcset); len = sizeof(disrtcset);
@ -249,7 +290,7 @@ int main(argc, argv)
} }
if (disrtcset == 0) { if (disrtcset == 0) {
disrtcset = 1; disrtcset = 1;
need_restore = 1; need_restore = True;
if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) { if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
syslog(LOG_ERR, "sysctl(set_disrtcset): %m"); syslog(LOG_ERR, "sysctl(set_disrtcset): %m");
return 1; return 1;
@ -257,16 +298,19 @@ int main(argc, argv)
} }
} }
if (( (init && (stv != NULL || stz != NULL)) if ( ( (init && (stv != NULL || stz != NULL))
|| (stz != NULL && stv == NULL) || (stz != NULL && stv == NULL)
) )
&& settimeofday(stv, stz) && settimeofday(stv, stz)
) { ) {
syslog(LOG_ERR, "settimeofday: %m"); syslog(LOG_ERR, "settimeofday: %m");
return 1; return 1;
} }
/* init: don't write RTC, !init: write RTC */ /* setting CPU_ADJKERNTZ have a side effect: resettodr(), which */
/* can be disabled by CPU_DISRTCSET, so if init or UTC clock */
/* -- don't write RTC, else write RTC. */
if (kern_offset != offset) { if (kern_offset != offset) {
kern_offset = offset; kern_offset = offset;
mib[0] = CTL_MACHDEP; mib[0] = CTL_MACHDEP;
@ -278,8 +322,18 @@ int main(argc, argv)
} }
} }
if (init) {
mib[0] = CTL_MACHDEP;
mib[1] = CPU_WALLCLOCK;
len = sizeof(wall_clock);
if (sysctl(mib, 2, NULL, NULL, &wall_clock, len) == -1) {
syslog(LOG_ERR, "sysctl(put_wallclock): %m");
return 1;
}
}
if (need_restore) { if (need_restore) {
need_restore = 0; need_restore = False;
mib[0] = CTL_MACHDEP; mib[0] = CTL_MACHDEP;
mib[1] = CPU_DISRTCSET; mib[1] = CPU_DISRTCSET;
disrtcset = 0; disrtcset = 0;
@ -292,8 +346,8 @@ int main(argc, argv)
/****** End of critical section ******/ /****** End of critical section ******/
if (init) { if (init && wall_clock) {
init = 0; init = False;
/* wait for signals and acts like -a */ /* wait for signals and acts like -a */
(void) sigsuspend(&emask); (void) sigsuspend(&emask);
goto again; goto again;