aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey A. Chernov <ache@FreeBSD.org>1994-11-01 16:22:22 +0000
committerAndrey A. Chernov <ache@FreeBSD.org>1994-11-01 16:22:22 +0000
commit7ac030ad078406eaab66e34f2dd92d49a4cad2b8 (patch)
tree486336c0d1a1d70f1dcb5efae4eac5d1eb154d53
parent9c354a29e74ac9c35487faaa372cf6d136f1e9c1 (diff)
downloadsrc-7ac030ad078406eaab66e34f2dd92d49a4cad2b8.tar.gz
src-7ac030ad078406eaab66e34f2dd92d49a4cad2b8.zip
Remove options, run adjkerntz as daemon now
Notes
Notes: svn path=/head/; revision=4048
-rw-r--r--sbin/adjkerntz/adjkerntz.851
-rw-r--r--sbin/adjkerntz/adjkerntz.c259
2 files changed, 149 insertions, 161 deletions
diff --git a/sbin/adjkerntz/adjkerntz.8 b/sbin/adjkerntz/adjkerntz.8
index 9678bf26750f..1ddd72b071d8 100644
--- a/sbin/adjkerntz/adjkerntz.8
+++ b/sbin/adjkerntz/adjkerntz.8
@@ -30,28 +30,21 @@
.Nd "adjusts the kernel time if the machine runs wall CMOS clock"
.Sh SYNOPSIS
.Nm adjkerntz
-.Fl i
-.Op Fl v
-.Nm adjkerntz
-.Fl a
-.Op Fl v
.Sh DESCRIPTION
.Nm Adjkerntz
+daemon
fixes kernel time (makes it UTC) using the current wall CMOS clock value,
the current time zone rule and the kernel timezone value. The adjustment is
enabled only if the file
.Pa /etc/wall_cmos_clock
exists, in other cases it is assumed that the machine runs UTC CMOS clock and
.Nm adjkerntz
-does nothing.
+does nothing and exits immediately.
.Pp
-The adjustment is needed at boot stage and when a time zone
-change occurs, so
-.Nm adjkerntz
-can be called in two forms:
-.Bl -tag -width 4n
-.It Cm Fl i
-initialization call from
+The adjustment is usually needed at boot stage and when a time zone
+change occurs.
+.Nm Adjkerntz
+started in
.Pa /etc/rc
(before any daemons are started).
.Nm Adjkerntz
@@ -60,27 +53,16 @@ makes the first adjustment and the initial time zone offset is stored into
kernel variable
for following subsequent
.Nm adjkerntz
-calls.
-.It Cm Fl a
-This form is needed, when time zone changes occur.
+time zone change spying.
+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 kernel time and store the new
+produce the new time zone offset, fix RTC clock and store the new
offset into
.Pa adjkerntz
kernel variable
too.
-It is recommended to use this form in root's
-.Xr crontab 5
-near 3am,
-since this time matches most modern time zone changes.
-.It Cm Fl v
-This option is for diagnostic purposes. It causes
-.Nm adjkerntz
-to print differences between the old and new time zone offsets
-to stdout.
-.El
.Pp
.Nm Adjkerntz
clears the kernel timezone structure and makes kernel always run at UTC
@@ -92,12 +74,16 @@ Super-user privilege is required for all operations.
Time zone change rule, see
.Xr tzset 3 ;
not needed when
+.Xr /usr/sbin/tzsetup
+or
.Xr zic 8
is used.
.Sh FILES
.Bl -tag -width /etc/wall_cmos_clock -compact
.It Pa /etc/localtime
-Link to the current zone info file, see
+current zoneinfo file, see
+.Xr /usr/sbin/tzsetup
+and
.Xr zic 8 .
.It Pa /etc/wall_cmos_clock
Empty file.
@@ -107,10 +93,13 @@ absence indicates UTC CMOS clock.
.Xr tzset 3 ,
.Xr zic 8 ,
.Xr rc 8 ,
-.Xr crontab 5
+.Xr sysctl 8 ,
+.Xr /usr/sbin/tzsetup
.Sh DIAGNOSTICS
-No diagnostics, unless \-v option is specified.
-If any error occurs, an error message printed to stderr and
+No diagnostics.
+If any error occurs, an error message printed via
+.Xr syslog 3
+and
.Nm adjkerntz
exits with return code greater than zero.
.Sh AUTHOR
diff --git a/sbin/adjkerntz/adjkerntz.c b/sbin/adjkerntz/adjkerntz.c
index 0e19badd382d..8c50ccede137 100644
--- a/sbin/adjkerntz/adjkerntz.c
+++ b/sbin/adjkerntz/adjkerntz.c
@@ -43,6 +43,7 @@ char copyright[] =
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <syslog.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/param.h>
@@ -51,6 +52,8 @@ char copyright[] =
#include "pathnames.h"
+#define REPORT_PERIOD (30*60)
+
int main(argc, argv)
int argc;
char **argv;
@@ -64,180 +67,176 @@ int main(argc, argv)
/* Avoid time_t here, can be unsigned long or worse */
long offset, utcsec, localsec, diff;
time_t initial_sec, final_sec;
- int ch, init = -1, verbose = 0;
+ int init = 1, nonex1 = 0, nonex2 = 0;
int disrtcset, need_restore = 0;
- while ((ch = getopt(argc, argv, "aiv")) != EOF)
- switch((char)ch) {
- case 'i': /* initial call, save offset */
- if (init != -1)
- goto usage;
- init = 1;
- break;
- case 'a': /* adjustment call, use saved offset */
- if (init != -1)
- goto usage;
- init = 0;
- break;
- case 'v': /* verbose */
- verbose = 1;
- break;
- default:
- usage:
- fprintf(stderr, "Usage:\n\
-\tadjkerntz -i [-v]\t(initial call from /etc/rc)\n\
-\tadjkerntz -a [-v]\t(adjustment call from crontab)\n");
- return 2;
- }
- if (init == -1)
- goto usage;
+ if (argc != 1) {
+ fprintf(stderr, "Usage:\tadjkerntz\n");
+ return 2;
+ }
if (access(_PATH_CLOCK, F_OK))
return 0;
- /* Restore saved offset */
-
- mib[0] = CTL_MACHDEP;
- mib[1] = CPU_ADJKERNTZ;
- len = sizeof(kern_offset);
- if (sysctl(mib, 2, &kern_offset, &len, NULL, 0) == -1) {
- perror("sysctl(get_offset)");
- return 1;
- }
-
-/****** Critical section, do all things as fast as possible ******/
-
- /* get local CMOS clock and possible kernel offset */
- if (gettimeofday(&tv, &tz)) {
- perror("gettimeofday");
- return 1;
- }
-
- /* get the actual local timezone difference */
- initial_sec = tv.tv_sec;
- local = *localtime(&initial_sec);
- utc = *gmtime(&initial_sec);
- utc.tm_isdst = local.tm_isdst; /* Use current timezone for mktime(), */
- /* because it assumed local time */
-
- /* calculate local CMOS diff from GMT */
-
- utcsec = mktime(&utc);
- localsec = mktime(&local);
- if (utcsec == -1 || localsec == -1) {
- /*
- * XXX user can only control local time, and it is
- * unacceptable to fail here for -i. 2:30 am in the
- * middle of the nonexistent hour means 3:30 am.
- */
- fprintf(stderr,
- "Nonexistent local time - try again in an hour\n");
+ if (daemon(0, 0)) {
+ perror("daemon");
return 1;
}
- offset = utcsec - localsec;
- /* correct the kerneltime for this diffs */
- /* subtract kernel offset, if present, old offset too */
+ openlog("adjkerntz", LOG_PID, LOG_DAEMON);
- diff = offset - tz.tz_minuteswest * 60 - kern_offset;
+ /* Spy on timezone changes with 1sec accurancy */
+ for (;;sleep(1)) {
- if (diff != 0) {
-
- /* Yet one step for final time */
+/****** Critical section, do all things as fast as possible ******/
- final_sec = tv.tv_sec + diff;
+ /* get local CMOS clock and possible kernel offset */
+ if (gettimeofday(&tv, &tz)) {
+ syslog(LOG_ERR, "gettimeofday: %m");
+ return 1;
+ }
/* get the actual local timezone difference */
- local = *localtime(&final_sec);
- utc = *gmtime(&final_sec);
+ initial_sec = tv.tv_sec;
+ local = *localtime(&initial_sec);
+ utc = *gmtime(&initial_sec);
utc.tm_isdst = local.tm_isdst; /* Use current timezone for mktime(), */
/* because it assumed local time */
+ /* calculate local CMOS diff from GMT */
+
utcsec = mktime(&utc);
localsec = mktime(&local);
if (utcsec == -1 || localsec == -1) {
/*
- * XXX as above. The user has even less control,
- * but perhaps we never get here.
+ * XXX user can only control local time, and it is
+ * unacceptable to fail here for init. 2:30 am in the
+ * middle of the nonexistent hour means 3:30 am.
*/
- fprintf(stderr,
- "Nonexistent (final) local time - try again in an hour\n");
- return 1;
+ if (!(nonex1++ % REPORT_PERIOD)) {
+ if (nonex1 > 1)
+ nonex1 = 0;
+ syslog(LOG_WARNING,
+ "Nonexistent local time -- retry each second");
+ }
+ continue;
}
offset = utcsec - localsec;
+ mib[0] = CTL_MACHDEP;
+ mib[1] = CPU_ADJKERNTZ;
+ len = sizeof(kern_offset);
+ if (sysctl(mib, 2, &kern_offset, &len, NULL, 0) == -1) {
+ syslog(LOG_ERR, "sysctl(get_offset): %m");
+ return 1;
+ }
+
/* correct the kerneltime for this diffs */
/* subtract kernel offset, if present, old offset too */
diff = offset - tz.tz_minuteswest * 60 - kern_offset;
if (diff != 0) {
- tv.tv_sec += diff;
- tv.tv_usec = 0; /* we are restarting here... */
- stv = &tv;
+
+ /* Yet one step for final time */
+
+ final_sec = tv.tv_sec + diff;
+
+ /* get the actual local timezone difference */
+ local = *localtime(&final_sec);
+ utc = *gmtime(&final_sec);
+ utc.tm_isdst = local.tm_isdst; /* Use current timezone for mktime(), */
+ /* because it assumed local time */
+
+ utcsec = mktime(&utc);
+ localsec = mktime(&local);
+ if (utcsec == -1 || localsec == -1) {
+ /*
+ * XXX as above. The user has even less control,
+ * but perhaps we never get here.
+ */
+ if (!(nonex2++ % REPORT_PERIOD)) {
+ if (nonex2 > 1)
+ nonex2 = 0;
+ syslog(LOG_WARNING,
+ "Nonexistent (final) local time -- retry each second");
+ }
+ continue;
+ }
+ offset = utcsec - localsec;
+
+ /* correct the kerneltime for this diffs */
+ /* subtract kernel offset, if present, old offset too */
+
+ diff = offset - tz.tz_minuteswest * 60 - kern_offset;
+
+ if (diff != 0) {
+ tv.tv_sec += diff;
+ tv.tv_usec = 0; /* we are restarting here... */
+ stv = &tv;
+ }
+ else
+ stv = NULL;
}
else
stv = NULL;
- }
- else
- stv = NULL;
-
- if (tz.tz_dsttime != 0 || tz.tz_minuteswest != 0) {
- tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */
- stz = &tz;
- }
- else
- stz = NULL;
- if (stz != NULL || stv != NULL) {
- if (init && stv != NULL) {
- mib[0] = CTL_MACHDEP;
- mib[1] = CPU_DISRTCSET;
- len = sizeof(disrtcset);
- if (sysctl(mib, 2, &disrtcset, &len, NULL, 0) == -1) {
- perror("sysctl(get_disrtcset)");
- return 1;
- }
- if (disrtcset == 0) {
- disrtcset = 1;
- need_restore = 1;
- if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
- perror("sysctl(set_disrtcset)");
+ if (tz.tz_dsttime != 0 || tz.tz_minuteswest != 0) {
+ tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */
+ stz = &tz;
+ }
+ else
+ stz = NULL;
+
+ if (stz != NULL || stv != NULL) {
+ if (init && stv != NULL) {
+ mib[0] = CTL_MACHDEP;
+ mib[1] = CPU_DISRTCSET;
+ len = sizeof(disrtcset);
+ if (sysctl(mib, 2, &disrtcset, &len, NULL, 0) == -1) {
+ syslog(LOG_ERR, "sysctl(get_disrtcset): %m");
return 1;
}
+ if (disrtcset == 0) {
+ disrtcset = 1;
+ need_restore = 1;
+ if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
+ syslog(LOG_ERR, "sysctl(set_disrtcset): %m");
+ return 1;
+ }
+ }
+ }
+ /* stz means that kernel zone shifted */
+ /* clock needs adjustment even if !init */
+ if ((init || stz != NULL) && settimeofday(stv, stz)) {
+ syslog(LOG_ERR, "settimeofday: %m");
+ return 1;
}
}
- if ((init || stv == NULL) && settimeofday(stv, stz)) {
- perror("settimeofday");
- return 1;
- }
- }
- if (kern_offset != offset) {
- kern_offset = offset;
- mib[0] = CTL_MACHDEP;
- mib[1] = CPU_ADJKERNTZ;
- len = sizeof(kern_offset);
- if (sysctl(mib, 2, NULL, NULL, &kern_offset, len) == -1) {
- perror("sysctl(update_offset)");
- return 1;
+ if (kern_offset != offset) {
+ kern_offset = offset;
+ mib[0] = CTL_MACHDEP;
+ mib[1] = CPU_ADJKERNTZ;
+ len = sizeof(kern_offset);
+ if (sysctl(mib, 2, NULL, NULL, &kern_offset, len) == -1) {
+ syslog(LOG_ERR, "sysctl(update_offset): %m");
+ return 1;
+ }
}
- }
- if (need_restore) {
- disrtcset = 0;
- if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
- perror("sysctl(restore_disrtcset)");
- return 1;
+ if (need_restore) {
+ need_restore = 0;
+ disrtcset = 0;
+ if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
+ syslog(LOG_ERR, "sysctl(restore_disrtcset): %m");
+ return 1;
+ }
}
- }
/****** End of critical section ******/
- if (verbose)
- printf("Calculated zone offset difference: %ld seconds\n",
- diff);
-
- return 0;
+ init = 0;
+ }
+ return 1;
}
-