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