xref: /dflybsd-src/sbin/adjkerntz/adjkerntz.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * Copyright (C) 1993-1998 by Andrey A. Chernov, Moscow, Russia.
386d7f5d3SJohn Marino  * All rights reserved.
486d7f5d3SJohn Marino  *
586d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
686d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
786d7f5d3SJohn Marino  * are met:
886d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
986d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1086d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1186d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1286d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
1386d7f5d3SJohn Marino  *
1486d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
1586d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1686d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1786d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1886d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1986d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2086d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2186d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2286d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2386d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2486d7f5d3SJohn Marino  * SUCH DAMAGE.
2586d7f5d3SJohn Marino  *
2686d7f5d3SJohn Marino  * @(#)Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia. All rights reserved.
2786d7f5d3SJohn Marino  * $FreeBSD: src/sbin/adjkerntz/adjkerntz.c,v 1.25.2.1 2001/07/30 10:38:04 dd Exp $
2886d7f5d3SJohn Marino  * $DragonFly: src/sbin/adjkerntz/adjkerntz.c,v 1.6 2005/11/06 12:03:15 swildner Exp $
2986d7f5d3SJohn Marino  */
3086d7f5d3SJohn Marino 
3186d7f5d3SJohn Marino /*
3286d7f5d3SJohn Marino  * Andrey A. Chernov   <ache@astral.msk.su>    Dec 20 1993
3386d7f5d3SJohn Marino  *
3486d7f5d3SJohn Marino  * Fix kernel time value if machine run wall CMOS clock
3586d7f5d3SJohn Marino  * (and /etc/wall_cmos_clock file present)
3686d7f5d3SJohn Marino  * using zoneinfo rules or direct TZ environment variable set.
3786d7f5d3SJohn Marino  * Use Joerg Wunsch idea for seconds accurate offset calculation
3886d7f5d3SJohn Marino  * with Garrett Wollman and Bruce Evans fixes.
3986d7f5d3SJohn Marino  *
4086d7f5d3SJohn Marino  */
4186d7f5d3SJohn Marino #include <stdio.h>
4286d7f5d3SJohn Marino #include <signal.h>
4386d7f5d3SJohn Marino #include <stdlib.h>
4486d7f5d3SJohn Marino #include <unistd.h>
4586d7f5d3SJohn Marino #include <syslog.h>
4686d7f5d3SJohn Marino #include <sys/time.h>
4786d7f5d3SJohn Marino #include <sys/param.h>
4886d7f5d3SJohn Marino #include <machine/cpu.h>
4986d7f5d3SJohn Marino #include <sys/sysctl.h>
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino #include "pathnames.h"
5286d7f5d3SJohn Marino 
5386d7f5d3SJohn Marino /*#define DEBUG*/
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino #define True (1)
5686d7f5d3SJohn Marino #define False (0)
5786d7f5d3SJohn Marino #define Unknown (-1)
5886d7f5d3SJohn Marino 
5986d7f5d3SJohn Marino #define REPORT_PERIOD (30*60)
6086d7f5d3SJohn Marino 
6186d7f5d3SJohn Marino static void fake(int);
6286d7f5d3SJohn Marino static void usage(void);
6386d7f5d3SJohn Marino 
6486d7f5d3SJohn Marino static void
fake(int unused __unused)6586d7f5d3SJohn Marino fake(int unused __unused)
6686d7f5d3SJohn Marino {
6786d7f5d3SJohn Marino 
6886d7f5d3SJohn Marino 	/* Do nothing. */
6986d7f5d3SJohn Marino }
7086d7f5d3SJohn Marino 
7186d7f5d3SJohn Marino int
main(int argc,char ** argv)7286d7f5d3SJohn Marino main(int argc, char **argv)
7386d7f5d3SJohn Marino {
7486d7f5d3SJohn Marino 	struct tm local;
7586d7f5d3SJohn Marino 	struct timeval tv, *stv;
7686d7f5d3SJohn Marino 	struct timezone tz, *stz;
7786d7f5d3SJohn Marino 	int kern_offset, wall_clock, disrtcset;
7886d7f5d3SJohn Marino 	size_t len;
7986d7f5d3SJohn Marino 	int mib[2];
8086d7f5d3SJohn Marino 	/* Avoid time_t here, can be unsigned long or worse */
8186d7f5d3SJohn Marino 	long offset, localsec, diff;
8286d7f5d3SJohn Marino 	time_t initial_sec, final_sec;
8386d7f5d3SJohn Marino 	int ch;
8486d7f5d3SJohn Marino 	int initial_isdst = -1, final_isdst;
8586d7f5d3SJohn Marino 	int need_restore = False, sleep_mode = False, looping,
8686d7f5d3SJohn Marino 	    init = Unknown;
8786d7f5d3SJohn Marino 	sigset_t mask, emask;
8886d7f5d3SJohn Marino 
8986d7f5d3SJohn Marino 	while ((ch = getopt(argc, argv, "ais")) != -1)
9086d7f5d3SJohn Marino 		switch((char)ch) {
9186d7f5d3SJohn Marino 		case 'i':               /* initial call, save offset */
9286d7f5d3SJohn Marino 			if (init != Unknown)
9386d7f5d3SJohn Marino 				usage();
9486d7f5d3SJohn Marino 			init = True;
9586d7f5d3SJohn Marino 			break;
9686d7f5d3SJohn Marino 		case 'a':               /* adjustment call, use saved offset */
9786d7f5d3SJohn Marino 			if (init != Unknown)
9886d7f5d3SJohn Marino 				usage();
9986d7f5d3SJohn Marino 			init = False;
10086d7f5d3SJohn Marino 			break;
10186d7f5d3SJohn Marino 		case 's':
10286d7f5d3SJohn Marino 			sleep_mode = True;
10386d7f5d3SJohn Marino 			break;
10486d7f5d3SJohn Marino 		default:
10586d7f5d3SJohn Marino 			usage();
10686d7f5d3SJohn Marino 		}
10786d7f5d3SJohn Marino 	if (init == Unknown)
10886d7f5d3SJohn Marino 		usage();
10986d7f5d3SJohn Marino 
11086d7f5d3SJohn Marino 	if (access(_PATH_CLOCK, F_OK) != 0)
11186d7f5d3SJohn Marino 		return 0;
11286d7f5d3SJohn Marino 
11386d7f5d3SJohn Marino 	if (init)
11486d7f5d3SJohn Marino 		sleep_mode = True;
11586d7f5d3SJohn Marino 
11686d7f5d3SJohn Marino 	sigemptyset(&mask);
11786d7f5d3SJohn Marino 	sigemptyset(&emask);
11886d7f5d3SJohn Marino 	sigaddset(&mask, SIGTERM);
11986d7f5d3SJohn Marino 
12086d7f5d3SJohn Marino 	openlog("adjkerntz", LOG_PID|LOG_PERROR, LOG_DAEMON);
12186d7f5d3SJohn Marino 
12286d7f5d3SJohn Marino 	signal(SIGHUP, SIG_IGN);
12386d7f5d3SJohn Marino 
12486d7f5d3SJohn Marino 	if (init && daemon(0, 1)) {
12586d7f5d3SJohn Marino 		syslog(LOG_ERR, "daemon: %m");
12686d7f5d3SJohn Marino 		return 1;
12786d7f5d3SJohn Marino 	}
12886d7f5d3SJohn Marino 
12986d7f5d3SJohn Marino again:
13086d7f5d3SJohn Marino 	sigprocmask(SIG_BLOCK, &mask, NULL);
13186d7f5d3SJohn Marino 	signal(SIGTERM, fake);
13286d7f5d3SJohn Marino 
13386d7f5d3SJohn Marino 	diff = 0;
13486d7f5d3SJohn Marino 	stv = NULL;
13586d7f5d3SJohn Marino 	stz = NULL;
13686d7f5d3SJohn Marino 	looping = False;
13786d7f5d3SJohn Marino 
13886d7f5d3SJohn Marino 	wall_clock = (access(_PATH_CLOCK, F_OK) == 0);
13986d7f5d3SJohn Marino 	if (init && !sleep_mode) {
14086d7f5d3SJohn Marino 		init = False;
14186d7f5d3SJohn Marino 		if (!wall_clock)
14286d7f5d3SJohn Marino 			return 0;
14386d7f5d3SJohn Marino 	}
14486d7f5d3SJohn Marino 
14586d7f5d3SJohn Marino 	mib[0] = CTL_MACHDEP;
14686d7f5d3SJohn Marino 	mib[1] = CPU_ADJKERNTZ;
14786d7f5d3SJohn Marino 	len = sizeof(kern_offset);
14886d7f5d3SJohn Marino 	if (sysctl(mib, 2, &kern_offset, &len, NULL, 0) == -1) {
14986d7f5d3SJohn Marino 		syslog(LOG_ERR, "sysctl(get_offset): %m");
15086d7f5d3SJohn Marino 		return 1;
15186d7f5d3SJohn Marino 	}
15286d7f5d3SJohn Marino 
15386d7f5d3SJohn Marino /****** Critical section, do all things as fast as possible ******/
15486d7f5d3SJohn Marino 
15586d7f5d3SJohn Marino 	/* get local CMOS clock and possible kernel offset */
15686d7f5d3SJohn Marino 	if (gettimeofday(&tv, &tz)) {
15786d7f5d3SJohn Marino 		syslog(LOG_ERR, "gettimeofday: %m");
15886d7f5d3SJohn Marino 		return 1;
15986d7f5d3SJohn Marino 	}
16086d7f5d3SJohn Marino 
16186d7f5d3SJohn Marino 	/* get the actual local timezone difference */
16286d7f5d3SJohn Marino 	initial_sec = tv.tv_sec;
16386d7f5d3SJohn Marino 
16486d7f5d3SJohn Marino recalculate:
16586d7f5d3SJohn Marino 	local = *localtime(&initial_sec);
16686d7f5d3SJohn Marino 	if (diff == 0)
16786d7f5d3SJohn Marino 		initial_isdst = local.tm_isdst;
16886d7f5d3SJohn Marino 	local.tm_isdst = initial_isdst;
16986d7f5d3SJohn Marino 
17086d7f5d3SJohn Marino 	/* calculate local CMOS diff from GMT */
17186d7f5d3SJohn Marino 
17286d7f5d3SJohn Marino 	localsec = mktime(&local);
17386d7f5d3SJohn Marino 	if (localsec == -1) {
17486d7f5d3SJohn Marino 		/*
17586d7f5d3SJohn Marino 		 * XXX user can only control local time, and it is
17686d7f5d3SJohn Marino 		 * unacceptable to fail here for init.  2:30 am in the
17786d7f5d3SJohn Marino 		 * middle of the nonexistent hour means 3:30 am.
17886d7f5d3SJohn Marino 		 */
17986d7f5d3SJohn Marino 		if (!sleep_mode) {
18086d7f5d3SJohn Marino 			syslog(LOG_WARNING,
18186d7f5d3SJohn Marino 			"Warning: nonexistent local time, try to run later.");
18286d7f5d3SJohn Marino 			syslog(LOG_WARNING, "Giving up.");
18386d7f5d3SJohn Marino 			return 1;
18486d7f5d3SJohn Marino 		}
18586d7f5d3SJohn Marino 		syslog(LOG_WARNING,
18686d7f5d3SJohn Marino 			"Warning: nonexistent local time.");
18786d7f5d3SJohn Marino 		syslog(LOG_WARNING, "Will retry after %d minutes.",
18886d7f5d3SJohn Marino 			REPORT_PERIOD / 60);
18986d7f5d3SJohn Marino 		signal(SIGTERM, SIG_DFL);
19086d7f5d3SJohn Marino 		sigprocmask(SIG_UNBLOCK, &mask, NULL);
19186d7f5d3SJohn Marino 		sleep(REPORT_PERIOD);
19286d7f5d3SJohn Marino 		goto again;
19386d7f5d3SJohn Marino 	}
19486d7f5d3SJohn Marino 	offset = -local.tm_gmtoff;
19586d7f5d3SJohn Marino #ifdef DEBUG
19686d7f5d3SJohn Marino 	fprintf(stderr, "Initial offset: %ld secs\n", offset);
19786d7f5d3SJohn Marino #endif
19886d7f5d3SJohn Marino 
19986d7f5d3SJohn Marino 	/* correct the kerneltime for this diffs */
20086d7f5d3SJohn Marino 	/* subtract kernel offset, if present, old offset too */
20186d7f5d3SJohn Marino 
20286d7f5d3SJohn Marino 	diff = offset - tz.tz_minuteswest * 60 - kern_offset;
20386d7f5d3SJohn Marino 
20486d7f5d3SJohn Marino 	if (diff != 0) {
20586d7f5d3SJohn Marino #ifdef DEBUG
20686d7f5d3SJohn Marino 		fprintf(stderr, "Initial diff: %ld secs\n", diff);
20786d7f5d3SJohn Marino #endif
20886d7f5d3SJohn Marino 		/* Yet one step for final time */
20986d7f5d3SJohn Marino 
21086d7f5d3SJohn Marino 		final_sec = initial_sec + diff;
21186d7f5d3SJohn Marino 
21286d7f5d3SJohn Marino 		/* get the actual local timezone difference */
21386d7f5d3SJohn Marino 		local = *localtime(&final_sec);
21486d7f5d3SJohn Marino 		final_isdst = diff < 0 ? initial_isdst : local.tm_isdst;
21586d7f5d3SJohn Marino 		if (diff > 0 && initial_isdst != final_isdst) {
21686d7f5d3SJohn Marino 			if (looping)
21786d7f5d3SJohn Marino 				goto bad_final;
21886d7f5d3SJohn Marino 			looping = True;
21986d7f5d3SJohn Marino 			initial_isdst = final_isdst;
22086d7f5d3SJohn Marino 			goto recalculate;
22186d7f5d3SJohn Marino 		}
22286d7f5d3SJohn Marino 		local.tm_isdst =  final_isdst;
22386d7f5d3SJohn Marino 
22486d7f5d3SJohn Marino 		localsec = mktime(&local);
22586d7f5d3SJohn Marino 		if (localsec == -1) {
22686d7f5d3SJohn Marino 		bad_final:
22786d7f5d3SJohn Marino 			/*
22886d7f5d3SJohn Marino 			 * XXX as above.  The user has even less control,
22986d7f5d3SJohn Marino 			 * but perhaps we never get here.
23086d7f5d3SJohn Marino 			 */
23186d7f5d3SJohn Marino 			if (!sleep_mode) {
23286d7f5d3SJohn Marino 				syslog(LOG_WARNING,
23386d7f5d3SJohn Marino 					"Warning: nonexistent final local time, try to run later.");
23486d7f5d3SJohn Marino 				syslog(LOG_WARNING, "Giving up.");
23586d7f5d3SJohn Marino 				return 1;
23686d7f5d3SJohn Marino 			}
23786d7f5d3SJohn Marino 			syslog(LOG_WARNING,
23886d7f5d3SJohn Marino 				"Warning: nonexistent final local time.");
23986d7f5d3SJohn Marino 			syslog(LOG_WARNING, "Will retry after %d minutes.",
24086d7f5d3SJohn Marino 				REPORT_PERIOD / 60);
24186d7f5d3SJohn Marino 			signal(SIGTERM, SIG_DFL);
24286d7f5d3SJohn Marino 			sigprocmask(SIG_UNBLOCK, &mask, NULL);
24386d7f5d3SJohn Marino 			sleep(REPORT_PERIOD);
24486d7f5d3SJohn Marino 			goto again;
24586d7f5d3SJohn Marino 		}
24686d7f5d3SJohn Marino 		offset = -local.tm_gmtoff;
24786d7f5d3SJohn Marino #ifdef DEBUG
24886d7f5d3SJohn Marino 		fprintf(stderr, "Final offset: %ld secs\n", offset);
24986d7f5d3SJohn Marino #endif
25086d7f5d3SJohn Marino 
25186d7f5d3SJohn Marino 		/* correct the kerneltime for this diffs */
25286d7f5d3SJohn Marino 		/* subtract kernel offset, if present, old offset too */
25386d7f5d3SJohn Marino 
25486d7f5d3SJohn Marino 		diff = offset - tz.tz_minuteswest * 60 - kern_offset;
25586d7f5d3SJohn Marino 
25686d7f5d3SJohn Marino 		if (diff != 0) {
25786d7f5d3SJohn Marino #ifdef DEBUG
25886d7f5d3SJohn Marino 			fprintf(stderr, "Final diff: %ld secs\n", diff);
25986d7f5d3SJohn Marino #endif
26086d7f5d3SJohn Marino 			/*
26186d7f5d3SJohn Marino 			 * stv is abused as a flag.  The important value
26286d7f5d3SJohn Marino 			 * is in `diff'.
26386d7f5d3SJohn Marino 			 */
26486d7f5d3SJohn Marino 			stv = &tv;
26586d7f5d3SJohn Marino 		}
26686d7f5d3SJohn Marino 	}
26786d7f5d3SJohn Marino 
26886d7f5d3SJohn Marino 	if (tz.tz_dsttime != 0 || tz.tz_minuteswest != 0) {
26986d7f5d3SJohn Marino 		tz.tz_dsttime = tz.tz_minuteswest = 0;  /* zone info is garbage */
27086d7f5d3SJohn Marino 		stz = &tz;
27186d7f5d3SJohn Marino 	}
27286d7f5d3SJohn Marino 	if (!wall_clock && stz == NULL)
27386d7f5d3SJohn Marino 		stv = NULL;
27486d7f5d3SJohn Marino 
27586d7f5d3SJohn Marino 	/* if init or UTC clock and offset/date will be changed, */
27686d7f5d3SJohn Marino 	/* disable RTC modification for a while.                      */
27786d7f5d3SJohn Marino 
27886d7f5d3SJohn Marino 	if (   (init && stv != NULL)
27986d7f5d3SJohn Marino 	    || ((init || !wall_clock) && kern_offset != offset)
28086d7f5d3SJohn Marino 	   ) {
28186d7f5d3SJohn Marino 		mib[0] = CTL_MACHDEP;
28286d7f5d3SJohn Marino 		mib[1] = CPU_DISRTCSET;
28386d7f5d3SJohn Marino 		len = sizeof(disrtcset);
28486d7f5d3SJohn Marino 		if (sysctl(mib, 2, &disrtcset, &len, NULL, 0) == -1) {
28586d7f5d3SJohn Marino 			syslog(LOG_ERR, "sysctl(get_disrtcset): %m");
28686d7f5d3SJohn Marino 			return 1;
28786d7f5d3SJohn Marino 		}
28886d7f5d3SJohn Marino 		if (disrtcset == 0) {
28986d7f5d3SJohn Marino 			disrtcset = 1;
29086d7f5d3SJohn Marino 			need_restore = True;
29186d7f5d3SJohn Marino 			if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
29286d7f5d3SJohn Marino 				syslog(LOG_ERR, "sysctl(set_disrtcset): %m");
29386d7f5d3SJohn Marino 				return 1;
29486d7f5d3SJohn Marino 			}
29586d7f5d3SJohn Marino 		}
29686d7f5d3SJohn Marino 	}
29786d7f5d3SJohn Marino 
29886d7f5d3SJohn Marino 	if (   (init && (stv != NULL || stz != NULL))
29986d7f5d3SJohn Marino 	    || (stz != NULL && stv == NULL)
30086d7f5d3SJohn Marino 	   ) {
30186d7f5d3SJohn Marino 		if (stv != NULL) {
30286d7f5d3SJohn Marino 			/*
30386d7f5d3SJohn Marino 			 * Get the time again, as close as possible to
30486d7f5d3SJohn Marino 			 * adjusting it, to minimise drift.
30586d7f5d3SJohn Marino 			 * XXX we'd better not fail between here and
30686d7f5d3SJohn Marino 			 * restoring disrtcset, since we don't clean up
30786d7f5d3SJohn Marino 			 * anything.
30886d7f5d3SJohn Marino 			 */
30986d7f5d3SJohn Marino 			if (gettimeofday(&tv, NULL)) {
31086d7f5d3SJohn Marino 				syslog(LOG_ERR, "gettimeofday: %m");
31186d7f5d3SJohn Marino 				return 1;
31286d7f5d3SJohn Marino 			}
31386d7f5d3SJohn Marino 			tv.tv_sec += diff;
31486d7f5d3SJohn Marino 			stv = &tv;
31586d7f5d3SJohn Marino 		}
31686d7f5d3SJohn Marino 		if (settimeofday(stv, stz)) {
31786d7f5d3SJohn Marino 			syslog(LOG_ERR, "settimeofday: %m");
31886d7f5d3SJohn Marino 			return 1;
31986d7f5d3SJohn Marino 		}
32086d7f5d3SJohn Marino 	}
32186d7f5d3SJohn Marino 
32286d7f5d3SJohn Marino 	/* setting CPU_ADJKERNTZ have a side effect: resettodr(), which */
32386d7f5d3SJohn Marino 	/* can be disabled by CPU_DISRTCSET, so if init or UTC clock    */
32486d7f5d3SJohn Marino 	/* -- don't write RTC, else write RTC.                          */
32586d7f5d3SJohn Marino 
32686d7f5d3SJohn Marino 	if (kern_offset != offset) {
32786d7f5d3SJohn Marino 		kern_offset = offset;
32886d7f5d3SJohn Marino 		mib[0] = CTL_MACHDEP;
32986d7f5d3SJohn Marino 		mib[1] = CPU_ADJKERNTZ;
33086d7f5d3SJohn Marino 		len = sizeof(kern_offset);
33186d7f5d3SJohn Marino 		if (sysctl(mib, 2, NULL, NULL, &kern_offset, len) == -1) {
33286d7f5d3SJohn Marino 			syslog(LOG_ERR, "sysctl(update_offset): %m");
33386d7f5d3SJohn Marino 			return 1;
33486d7f5d3SJohn Marino 		}
33586d7f5d3SJohn Marino 	}
33686d7f5d3SJohn Marino 
33786d7f5d3SJohn Marino 	mib[0] = CTL_MACHDEP;
33886d7f5d3SJohn Marino 	mib[1] = CPU_WALLCLOCK;
33986d7f5d3SJohn Marino 	len = sizeof(wall_clock);
34086d7f5d3SJohn Marino 	if (sysctl(mib, 2, NULL, NULL, &wall_clock, len) == -1) {
34186d7f5d3SJohn Marino 		syslog(LOG_ERR, "sysctl(put_wallclock): %m");
34286d7f5d3SJohn Marino 		return 1;
34386d7f5d3SJohn Marino 	}
34486d7f5d3SJohn Marino 
34586d7f5d3SJohn Marino 	if (need_restore) {
34686d7f5d3SJohn Marino 		need_restore = False;
34786d7f5d3SJohn Marino 		mib[0] = CTL_MACHDEP;
34886d7f5d3SJohn Marino 		mib[1] = CPU_DISRTCSET;
34986d7f5d3SJohn Marino 		disrtcset = 0;
35086d7f5d3SJohn Marino 		len = sizeof(disrtcset);
35186d7f5d3SJohn Marino 		if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
35286d7f5d3SJohn Marino 			syslog(LOG_ERR, "sysctl(restore_disrtcset): %m");
35386d7f5d3SJohn Marino 			return 1;
35486d7f5d3SJohn Marino 		}
35586d7f5d3SJohn Marino 	}
35686d7f5d3SJohn Marino 
35786d7f5d3SJohn Marino /****** End of critical section ******/
35886d7f5d3SJohn Marino 
35986d7f5d3SJohn Marino 	if (init && wall_clock) {
36086d7f5d3SJohn Marino 		sleep_mode = False;
36186d7f5d3SJohn Marino 		/* wait for signals and acts like -a */
36286d7f5d3SJohn Marino 		sigsuspend(&emask);
36386d7f5d3SJohn Marino 		goto again;
36486d7f5d3SJohn Marino 	}
36586d7f5d3SJohn Marino 
36686d7f5d3SJohn Marino 	return 0;
36786d7f5d3SJohn Marino }
36886d7f5d3SJohn Marino 
36986d7f5d3SJohn Marino static void
usage(void)37086d7f5d3SJohn Marino usage(void)
37186d7f5d3SJohn Marino {
37286d7f5d3SJohn Marino 	fprintf(stderr, "%s\n%s\n%s\n%s\n",
37386d7f5d3SJohn Marino 		"usage: adjkerntz -i",
37486d7f5d3SJohn Marino 		"\t\t(initial call from /etc/rc)",
37586d7f5d3SJohn Marino 		"       adjkerntz -a [-s]",
37686d7f5d3SJohn Marino 		"\t\t(adjustment call, -s for sleep/retry mode)");
37786d7f5d3SJohn Marino 	exit(2);
37886d7f5d3SJohn Marino }
379