diff --git a/sbin/adjkerntz/adjkerntz.8 b/sbin/adjkerntz/adjkerntz.8 index 086f12a13731..9cb5c8dccb6e 100644 --- a/sbin/adjkerntz/adjkerntz.8 +++ b/sbin/adjkerntz/adjkerntz.8 @@ -53,18 +53,24 @@ initialization call from .Pa /etc/rc (before any daemons are started). .Nm Adjkerntz -makes the first adjustment and the initial time zone offset is stored into +makes the adjustment of kernel clock (CMOS clock not touched) +and the initial time zone offset is stored into .Pa adjkerntz kernel variable for following subsequent -.Nm adjkerntz -calls. +.Nm "'adjkerntz -a'" +calls. Then it goes to background pause which ends with SIGTERM. +After receiving SIGTERM it acts like +.Nm "'adjkerntz -a'" +to be shure to have proper CMOS clock before reboot. .It Cm Fl a This form is needed, when time zone changes occur. .Nm Adjkerntz uses the previously stored time zone offset and the changed time zone rule to -produce the new time zone offset, fix the RTC clock and store the new +produce the new time zone offset, fix the CMOS clock +(kernel clock not touched) +and store the new offset into .Pa adjkerntz kernel variable @@ -73,6 +79,7 @@ It is recommended to use this form in root's .Xr crontab 5 every half of a hour from 0am to 4am since this times matches most modern time zone changes. +.El .Pp .Nm Adjkerntz clears the kernel timezone structure and makes kernel always run at UTC diff --git a/sbin/adjkerntz/adjkerntz.c b/sbin/adjkerntz/adjkerntz.c index 5e7b0b896d56..444a9dff3910 100644 --- a/sbin/adjkerntz/adjkerntz.c +++ b/sbin/adjkerntz/adjkerntz.c @@ -41,6 +41,7 @@ char copyright[] = * */ #include +#include #include #include #include @@ -54,6 +55,8 @@ char copyright[] = #define REPORT_PERIOD (30*60) +void fake() {} + int main(argc, argv) int argc; char **argv; @@ -69,6 +72,7 @@ int main(argc, argv) time_t initial_sec, final_sec; int ch, init = -1; int disrtcset, need_restore = 0; + sigset_t mask, emask; while ((ch = getopt(argc, argv, "ai")) != EOF) switch((char)ch) { @@ -95,10 +99,24 @@ int main(argc, argv) if (access(_PATH_CLOCK, F_OK)) return 0; + sigemptyset(&mask); + sigemptyset(&emask); + sigaddset(&mask, SIGTERM); + openlog("adjkerntz", LOG_PID|LOG_PERROR, LOG_DAEMON); + (void) signal(SIGHUP, SIG_IGN); + + if (init && daemon(0, 1)) { + syslog(LOG_ERR, "daemon: %m"); + return 1; + } + again: + (void) sigprocmask(SIG_BLOCK, &mask, NULL); + (void) signal(SIGTERM, fake); + /****** Critical section, do all things as fast as possible ******/ /* get local CMOS clock and possible kernel offset */ @@ -126,6 +144,8 @@ int main(argc, argv) */ syslog(LOG_WARNING, "Nonexistent local time -- will retry after %d secs", REPORT_PERIOD); + (void) signal(SIGTERM, SIG_DFL); + (void) sigprocmask(SIG_UNBLOCK, &mask, NULL); (void) sleep(REPORT_PERIOD); goto again; } @@ -165,6 +185,8 @@ int main(argc, argv) */ syslog(LOG_WARNING, "Nonexistent (final) local time -- will retry after %d secs", REPORT_PERIOD); + (void) signal(SIGTERM, SIG_DFL); + (void) sigprocmask(SIG_UNBLOCK, &mask, NULL); (void) sleep(REPORT_PERIOD); goto again; } @@ -241,5 +263,12 @@ int main(argc, argv) /****** End of critical section ******/ + if (init) { + init = 0; + /* wait for signals and acts like -a */ + (void) sigsuspend(&emask); + goto again; + } + return 0; }