1*cdfa2a7eSchristos /* $NetBSD: adjtimed.c,v 1.6 2020/05/25 20:47:19 christos Exp $ */
2abb0f93cSkardel
3abb0f93cSkardel /*************************************************************************/
4abb0f93cSkardel /* (c) Copyright Tai Jin, 1988. All Rights Reserved. */
5abb0f93cSkardel /* Hewlett-Packard Laboratories. */
6abb0f93cSkardel /* */
7abb0f93cSkardel /* Permission is hereby granted for unlimited modification, use, and */
8abb0f93cSkardel /* distribution. This software is made available with no warranty of */
9abb0f93cSkardel /* any kind, express or implied. This copyright notice must remain */
10abb0f93cSkardel /* intact in all versions of this software. */
11abb0f93cSkardel /* */
12abb0f93cSkardel /* The author would appreciate it if any bug fixes and enhancements were */
13abb0f93cSkardel /* to be sent back to him for incorporation into future versions of this */
14abb0f93cSkardel /* software. Please send changes to tai@iag.hp.com or ken@sdd.hp.com. */
15abb0f93cSkardel /*************************************************************************/
16abb0f93cSkardel
17abb0f93cSkardel #ifndef lint
18abb0f93cSkardel static char RCSid[] = "adjtimed.c,v 3.1 1993/07/06 01:04:45 jbj Exp";
19abb0f93cSkardel #endif
20abb0f93cSkardel
21abb0f93cSkardel /*
22abb0f93cSkardel * Adjust time daemon.
23abb0f93cSkardel * This daemon adjusts the rate of the system clock a la BSD's adjtime().
24abb0f93cSkardel * The adjtime() routine uses SYSV messages to communicate with this daemon.
25abb0f93cSkardel *
26abb0f93cSkardel * Caveat: This emulation uses an undocumented kernel variable. As such, it
27abb0f93cSkardel * cannot be guaranteed to work in future HP-UX releases. Fortunately,
28abb0f93cSkardel * it will no longer be needed in HPUX 10.01 and later.
29abb0f93cSkardel */
30abb0f93cSkardel
31abb0f93cSkardel #include <sys/param.h>
32abb0f93cSkardel #include <sys/types.h>
33abb0f93cSkardel #include <sys/ipc.h>
34abb0f93cSkardel #include <sys/msg.h>
35abb0f93cSkardel #include <sys/lock.h>
36abb0f93cSkardel #include <time.h>
37abb0f93cSkardel #include <signal.h>
38abb0f93cSkardel #include <nlist.h>
39abb0f93cSkardel #include <fcntl.h>
40abb0f93cSkardel #include <stdio.h>
41abb0f93cSkardel #include <unistd.h>
42abb0f93cSkardel
43abb0f93cSkardel #include "ntp_syslog.h"
44abb0f93cSkardel #include "ntp_stdlib.h"
45abb0f93cSkardel
46abb0f93cSkardel #include "adjtime.h"
47abb0f93cSkardel
48abb0f93cSkardel double atof (const char *);
49abb0f93cSkardel
50abb0f93cSkardel int InitClockRate (void);
51abb0f93cSkardel int AdjustClockRate (register struct timeval *delta, register struct timeval *olddelta);
52abb0f93cSkardel long GetClockRate (void);
53abb0f93cSkardel int SetClockRate (long);
54abb0f93cSkardel void ResetClockRate (void);
55abb0f93cSkardel void Cleanup (void);
56abb0f93cSkardel void Exit (int);
57abb0f93cSkardel
58abb0f93cSkardel #define MILLION 1000000L
59abb0f93cSkardel
60abb0f93cSkardel /* emacs cc-mode goes nuts if we split the next line... */
61abb0f93cSkardel #define tvtod(tv) ((double)tv.tv_sec + ((double)tv.tv_usec / (double)MILLION))
62abb0f93cSkardel
63af12ab5eSchristos char const *progname = NULL;
64abb0f93cSkardel int verbose = 0;
65abb0f93cSkardel int sysdebug = 0;
66abb0f93cSkardel static int mqid;
67abb0f93cSkardel static double oldrate = 0.0;
68abb0f93cSkardel
69abb0f93cSkardel int
main(int argc,char * argv[])70abb0f93cSkardel main(
71abb0f93cSkardel int argc,
72abb0f93cSkardel char *argv[]
73abb0f93cSkardel )
74abb0f93cSkardel {
75abb0f93cSkardel struct timeval remains;
76abb0f93cSkardel struct sigvec vec;
77abb0f93cSkardel MsgBuf msg;
78abb0f93cSkardel char ch;
79abb0f93cSkardel int nofork = 0;
80abb0f93cSkardel int fd;
81abb0f93cSkardel
82abb0f93cSkardel progname = argv[0];
83abb0f93cSkardel
84abb0f93cSkardel #ifdef LOG_LOCAL6
85abb0f93cSkardel openlog("adjtimed", LOG_PID, LOG_LOCAL6);
86abb0f93cSkardel #else
87abb0f93cSkardel openlog("adjtimed", LOG_PID);
88abb0f93cSkardel #endif
89abb0f93cSkardel
90abb0f93cSkardel while ((ch = ntp_getopt(argc, argv, "hkrvdfp:")) != EOF) {
91abb0f93cSkardel switch (ch) {
92abb0f93cSkardel case 'k':
93abb0f93cSkardel case 'r':
94abb0f93cSkardel if ((mqid = msgget(KEY, 0)) != -1) {
95abb0f93cSkardel if (msgctl(mqid, IPC_RMID, (struct msqid_ds *)0) == -1) {
96abb0f93cSkardel msyslog(LOG_ERR, "remove old message queue: %m");
97abb0f93cSkardel perror("adjtimed: remove old message queue");
98abb0f93cSkardel exit(1);
99abb0f93cSkardel }
100abb0f93cSkardel }
101abb0f93cSkardel
102abb0f93cSkardel if (ch == 'k')
103abb0f93cSkardel exit(0);
104abb0f93cSkardel
105abb0f93cSkardel break;
106abb0f93cSkardel
107abb0f93cSkardel case 'v':
108abb0f93cSkardel ++verbose, nofork = 1;
109abb0f93cSkardel break;
110abb0f93cSkardel
111abb0f93cSkardel case 'd':
112abb0f93cSkardel ++sysdebug;
113abb0f93cSkardel break;
114abb0f93cSkardel
115abb0f93cSkardel case 'f':
116abb0f93cSkardel nofork = 1;
117abb0f93cSkardel break;
118abb0f93cSkardel
119abb0f93cSkardel case 'p':
120abb0f93cSkardel fputs("adjtimed: -p option ignored\n", stderr);
121abb0f93cSkardel break;
122abb0f93cSkardel
123abb0f93cSkardel default:
124abb0f93cSkardel puts("usage: adjtimed -hkrvdf");
125abb0f93cSkardel puts("-h\thelp");
126abb0f93cSkardel puts("-k\tkill existing adjtimed, if any");
127abb0f93cSkardel puts("-r\trestart (kills existing adjtimed, if any)");
128abb0f93cSkardel puts("-v\tdebug output (repeat for more output)");
129abb0f93cSkardel puts("-d\tsyslog output (repeat for more output)");
130abb0f93cSkardel puts("-f\tno fork");
131abb0f93cSkardel msyslog(LOG_ERR, "usage error");
132abb0f93cSkardel exit(1);
133abb0f93cSkardel } /* switch */
134abb0f93cSkardel } /* while */
135abb0f93cSkardel
136abb0f93cSkardel if (!nofork) {
137abb0f93cSkardel switch (fork()) {
138abb0f93cSkardel case 0:
139abb0f93cSkardel close(fileno(stdin));
140abb0f93cSkardel close(fileno(stdout));
141abb0f93cSkardel close(fileno(stderr));
142abb0f93cSkardel
143abb0f93cSkardel #ifdef TIOCNOTTY
144abb0f93cSkardel if ((fd = open("/dev/tty")) != -1) {
145abb0f93cSkardel ioctl(fd, TIOCNOTTY, 0);
146abb0f93cSkardel close(fd);
147abb0f93cSkardel }
148abb0f93cSkardel #else
149abb0f93cSkardel setpgrp();
150abb0f93cSkardel #endif
151abb0f93cSkardel break;
152abb0f93cSkardel
153abb0f93cSkardel case -1:
154abb0f93cSkardel msyslog(LOG_ERR, "fork: %m");
155abb0f93cSkardel perror("adjtimed: fork");
156abb0f93cSkardel exit(1);
157abb0f93cSkardel
158abb0f93cSkardel default:
159abb0f93cSkardel exit(0);
160abb0f93cSkardel } /* switch */
161abb0f93cSkardel } /* if */
162abb0f93cSkardel
163abb0f93cSkardel if (nofork) {
164abb0f93cSkardel setvbuf(stdout, NULL, _IONBF, BUFSIZ);
165abb0f93cSkardel setvbuf(stderr, NULL, _IONBF, BUFSIZ);
166abb0f93cSkardel }
167abb0f93cSkardel
168abb0f93cSkardel msyslog(LOG_INFO, "started");
169abb0f93cSkardel if (verbose) printf("adjtimed: started\n");
170abb0f93cSkardel
171abb0f93cSkardel if (InitClockRate() == -1)
172abb0f93cSkardel Exit(2);
173abb0f93cSkardel
174abb0f93cSkardel (void)signal(SIGHUP, SIG_IGN);
175abb0f93cSkardel (void)signal(SIGINT, SIG_IGN);
176abb0f93cSkardel (void)signal(SIGQUIT, SIG_IGN);
177abb0f93cSkardel (void)signal(SIGTERM, Cleanup);
178abb0f93cSkardel
179abb0f93cSkardel vec.sv_handler = ResetClockRate;
180abb0f93cSkardel vec.sv_flags = 0;
181abb0f93cSkardel vec.sv_mask = ~0;
182abb0f93cSkardel sigvector(SIGALRM, &vec, (struct sigvec *)0);
183abb0f93cSkardel
184abb0f93cSkardel if (msgget(KEY, IPC_CREAT|IPC_EXCL) == -1) {
185abb0f93cSkardel if (errno == EEXIST) {
186abb0f93cSkardel msyslog(LOG_ERR, "message queue already exists, use -r to remove it");
187abb0f93cSkardel fputs("adjtimed: message queue already exists, use -r to remove it\n",
188abb0f93cSkardel stderr);
189abb0f93cSkardel Exit(1);
190abb0f93cSkardel }
191abb0f93cSkardel
192abb0f93cSkardel msyslog(LOG_ERR, "create message queue: %m");
193abb0f93cSkardel perror("adjtimed: create message queue");
194abb0f93cSkardel Exit(1);
195abb0f93cSkardel }
196abb0f93cSkardel
197abb0f93cSkardel if ((mqid = msgget(KEY, 0)) == -1) {
198abb0f93cSkardel msyslog(LOG_ERR, "get message queue id: %m");
199abb0f93cSkardel perror("adjtimed: get message queue id");
200abb0f93cSkardel Exit(1);
201abb0f93cSkardel }
202abb0f93cSkardel
203abb0f93cSkardel /* Lock process in memory to improve response time */
204abb0f93cSkardel if (plock(PROCLOCK)) {
205abb0f93cSkardel msyslog(LOG_ERR, "plock: %m");
206abb0f93cSkardel perror("adjtimed: plock");
207abb0f93cSkardel Cleanup();
208abb0f93cSkardel }
209abb0f93cSkardel
210abb0f93cSkardel /* Also raise process priority.
211abb0f93cSkardel * If we do not get run when we want, this leads to bad timekeeping
212abb0f93cSkardel * and "Previous time adjustment didn't complete" gripes from xntpd.
213abb0f93cSkardel */
214abb0f93cSkardel if (nice(-10) == -1) {
215abb0f93cSkardel msyslog(LOG_ERR, "nice: %m");
216abb0f93cSkardel perror("adjtimed: nice");
217abb0f93cSkardel Cleanup();
218abb0f93cSkardel }
219abb0f93cSkardel
220abb0f93cSkardel for (;;) {
221abb0f93cSkardel if (msgrcv(mqid, &msg.msgp, MSGSIZE, CLIENT, 0) == -1) {
222abb0f93cSkardel if (errno == EINTR) continue;
223abb0f93cSkardel msyslog(LOG_ERR, "read message: %m");
224abb0f93cSkardel perror("adjtimed: read message");
225abb0f93cSkardel Cleanup();
226abb0f93cSkardel }
227abb0f93cSkardel
228abb0f93cSkardel switch (msg.msgb.code) {
229abb0f93cSkardel case DELTA1:
230abb0f93cSkardel case DELTA2:
231abb0f93cSkardel AdjustClockRate(&msg.msgb.tv, &remains);
232abb0f93cSkardel
233abb0f93cSkardel if (msg.msgb.code == DELTA2) {
234abb0f93cSkardel msg.msgb.tv = remains;
235abb0f93cSkardel msg.msgb.mtype = SERVER;
236abb0f93cSkardel
237abb0f93cSkardel while (msgsnd(mqid, &msg.msgp, MSGSIZE, 0) == -1) {
238abb0f93cSkardel if (errno == EINTR) continue;
239abb0f93cSkardel msyslog(LOG_ERR, "send message: %m");
240abb0f93cSkardel perror("adjtimed: send message");
241abb0f93cSkardel Cleanup();
242abb0f93cSkardel }
243abb0f93cSkardel }
244abb0f93cSkardel
245abb0f93cSkardel if (remains.tv_sec + remains.tv_usec != 0L) {
246abb0f93cSkardel if (verbose) {
247abb0f93cSkardel printf("adjtimed: previous correction remaining %.6fs\n",
248abb0f93cSkardel tvtod(remains));
249abb0f93cSkardel }
250abb0f93cSkardel if (sysdebug) {
251abb0f93cSkardel msyslog(LOG_INFO, "previous correction remaining %.6fs",
252abb0f93cSkardel tvtod(remains));
253abb0f93cSkardel }
254abb0f93cSkardel }
255abb0f93cSkardel break;
256abb0f93cSkardel
257abb0f93cSkardel default:
258abb0f93cSkardel fprintf(stderr, "adjtimed: unknown message code %d\n", msg.msgb.code);
259abb0f93cSkardel msyslog(LOG_ERR, "unknown message code %d", msg.msgb.code);
260abb0f93cSkardel } /* switch */
261abb0f93cSkardel } /* loop */
262abb0f93cSkardel } /* main */
263abb0f93cSkardel
264abb0f93cSkardel /*
265abb0f93cSkardel * Default clock rate (old_tick).
266abb0f93cSkardel */
267abb0f93cSkardel #define DEFAULT_RATE (MILLION / HZ)
268abb0f93cSkardel #define UNKNOWN_RATE 0L
269abb0f93cSkardel #define TICK_ADJ 5 /* standard adjustment rate, microsec/tick */
270abb0f93cSkardel
271abb0f93cSkardel static long default_rate = DEFAULT_RATE;
272abb0f93cSkardel static long tick_rate = HZ; /* ticks per sec */
273abb0f93cSkardel static long slew_rate = TICK_ADJ * HZ; /* in microsec/sec */
274abb0f93cSkardel
275abb0f93cSkardel int
AdjustClockRate(register struct timeval * delta,register struct timeval * olddelta)276abb0f93cSkardel AdjustClockRate(
277abb0f93cSkardel register struct timeval *delta,
278abb0f93cSkardel register struct timeval *olddelta
279abb0f93cSkardel )
280abb0f93cSkardel {
281abb0f93cSkardel register long rate, dt, leftover;
282abb0f93cSkardel struct itimerval period, remains;
283abb0f93cSkardel
284abb0f93cSkardel dt = (delta->tv_sec * MILLION) + delta->tv_usec;
285abb0f93cSkardel
286abb0f93cSkardel if (verbose)
287abb0f93cSkardel printf("adjtimed: new correction %.6fs\n", (double)dt / (double)MILLION);
288abb0f93cSkardel if (sysdebug)
289abb0f93cSkardel msyslog(LOG_INFO, "new correction %.6fs", (double)dt / (double)MILLION);
290abb0f93cSkardel if (verbose > 2) printf("adjtimed: leftover %ldus\n", leftover);
291abb0f93cSkardel if (sysdebug > 2) msyslog(LOG_INFO, "leftover %ldus", leftover);
292abb0f93cSkardel rate = dt;
293abb0f93cSkardel
294abb0f93cSkardel /*
295abb0f93cSkardel * Apply a slew rate of slew_rate over a period of dt/slew_rate seconds.
296abb0f93cSkardel */
297abb0f93cSkardel if (dt > 0) {
298abb0f93cSkardel rate = slew_rate;
299abb0f93cSkardel } else {
300abb0f93cSkardel rate = -slew_rate;
301abb0f93cSkardel dt = -dt;
302abb0f93cSkardel }
303abb0f93cSkardel period.it_value.tv_sec = dt / slew_rate;
304abb0f93cSkardel period.it_value.tv_usec = (dt % slew_rate) * (MILLION / slew_rate);
305abb0f93cSkardel /*
306abb0f93cSkardel * Note: we assume the kernel will convert the specified period into ticks
307abb0f93cSkardel * using the modified clock rate rather than an assumed nominal clock rate,
308abb0f93cSkardel * and therefore will generate the timer interrupt after the specified
309abb0f93cSkardel * number of true seconds, not skewed seconds.
310abb0f93cSkardel */
311abb0f93cSkardel
312abb0f93cSkardel if (verbose > 1)
313abb0f93cSkardel printf("adjtimed: will be complete in %lds %ldus\n",
314abb0f93cSkardel period.it_value.tv_sec, period.it_value.tv_usec);
315abb0f93cSkardel if (sysdebug > 1)
316abb0f93cSkardel msyslog(LOG_INFO, "will be complete in %lds %ldus",
317abb0f93cSkardel period.it_value.tv_sec, period.it_value.tv_usec);
318abb0f93cSkardel /*
319abb0f93cSkardel * adjust the clock rate
320abb0f93cSkardel */
321abb0f93cSkardel if (dt) {
322abb0f93cSkardel if (SetClockRate((rate / tick_rate) + default_rate) == -1) {
323abb0f93cSkardel msyslog(LOG_ERR, "set clock rate: %m");
324abb0f93cSkardel perror("adjtimed: set clock rate");
325abb0f93cSkardel }
326abb0f93cSkardel }
327abb0f93cSkardel /*
328abb0f93cSkardel * start the timer
329abb0f93cSkardel * (do this after changing the rate because the period has been rounded down)
330abb0f93cSkardel */
331abb0f93cSkardel period.it_interval.tv_sec = period.it_interval.tv_usec = 0L;
332abb0f93cSkardel setitimer(ITIMER_REAL, &period, &remains);
333abb0f93cSkardel /*
334abb0f93cSkardel * return old delta
335abb0f93cSkardel */
336abb0f93cSkardel if (olddelta) {
337abb0f93cSkardel dt = ((remains.it_value.tv_sec * MILLION) + remains.it_value.tv_usec) *
338abb0f93cSkardel oldrate;
339abb0f93cSkardel olddelta->tv_sec = dt / MILLION;
340abb0f93cSkardel olddelta->tv_usec = dt - (olddelta->tv_sec * MILLION);
341abb0f93cSkardel }
342abb0f93cSkardel
343abb0f93cSkardel oldrate = (double)rate / (double)MILLION;
344abb0f93cSkardel return(0);
345abb0f93cSkardel } /* AdjustClockRate */
346abb0f93cSkardel
347abb0f93cSkardel static struct nlist nl[] = {
348abb0f93cSkardel #ifdef __hp9000s800
349abb0f93cSkardel #ifdef PRE7_0
350abb0f93cSkardel { "tick" },
351abb0f93cSkardel #else
352abb0f93cSkardel { "old_tick" },
353abb0f93cSkardel #endif
354abb0f93cSkardel #else
355abb0f93cSkardel { "_old_tick" },
356abb0f93cSkardel #endif
357abb0f93cSkardel { "" }
358abb0f93cSkardel };
359abb0f93cSkardel
360abb0f93cSkardel static int kmem;
361abb0f93cSkardel
362abb0f93cSkardel /*
363abb0f93cSkardel * The return value is the clock rate in old_tick units or -1 if error.
364abb0f93cSkardel */
365abb0f93cSkardel long
GetClockRate(void)366abb0f93cSkardel GetClockRate(void)
367abb0f93cSkardel {
368abb0f93cSkardel long rate, mask;
369abb0f93cSkardel
370abb0f93cSkardel if (lseek(kmem, (off_t)nl[0].n_value, 0) == -1L)
371abb0f93cSkardel return (-1L);
372abb0f93cSkardel
373abb0f93cSkardel mask = sigblock(sigmask(SIGALRM));
374abb0f93cSkardel
375abb0f93cSkardel if (read(kmem, (caddr_t)&rate, sizeof(rate)) != sizeof(rate))
376abb0f93cSkardel rate = UNKNOWN_RATE;
377abb0f93cSkardel
378abb0f93cSkardel sigsetmask(mask);
379abb0f93cSkardel return (rate);
380abb0f93cSkardel } /* GetClockRate */
381abb0f93cSkardel
382abb0f93cSkardel /*
383abb0f93cSkardel * The argument is the new rate in old_tick units.
384abb0f93cSkardel */
385abb0f93cSkardel int
SetClockRate(long rate)386abb0f93cSkardel SetClockRate(
387abb0f93cSkardel long rate
388abb0f93cSkardel )
389abb0f93cSkardel {
390abb0f93cSkardel long mask;
391abb0f93cSkardel
392abb0f93cSkardel if (lseek(kmem, (off_t)nl[0].n_value, 0) == -1L)
393abb0f93cSkardel return (-1);
394abb0f93cSkardel
395abb0f93cSkardel mask = sigblock(sigmask(SIGALRM));
396abb0f93cSkardel
397abb0f93cSkardel if (write(kmem, (caddr_t)&rate, sizeof(rate)) != sizeof(rate)) {
398abb0f93cSkardel sigsetmask(mask);
399abb0f93cSkardel return (-1);
400abb0f93cSkardel }
401abb0f93cSkardel
402abb0f93cSkardel sigsetmask(mask);
403abb0f93cSkardel
404abb0f93cSkardel if (rate != default_rate) {
405abb0f93cSkardel if (verbose > 3) {
406abb0f93cSkardel printf("adjtimed: clock rate (%lu) %ldus/s\n", rate,
407abb0f93cSkardel (rate - default_rate) * tick_rate);
408abb0f93cSkardel }
409abb0f93cSkardel if (sysdebug > 3) {
410abb0f93cSkardel msyslog(LOG_INFO, "clock rate (%lu) %ldus/s", rate,
411abb0f93cSkardel (rate - default_rate) * tick_rate);
412abb0f93cSkardel }
413abb0f93cSkardel }
414abb0f93cSkardel
415abb0f93cSkardel return (0);
416abb0f93cSkardel } /* SetClockRate */
417abb0f93cSkardel
418abb0f93cSkardel int
InitClockRate(void)419abb0f93cSkardel InitClockRate(void)
420abb0f93cSkardel {
421abb0f93cSkardel if ((kmem = open("/dev/kmem", O_RDWR)) == -1) {
422abb0f93cSkardel msyslog(LOG_ERR, "open(/dev/kmem): %m");
423abb0f93cSkardel perror("adjtimed: open(/dev/kmem)");
424abb0f93cSkardel return (-1);
425abb0f93cSkardel }
426abb0f93cSkardel
427abb0f93cSkardel nlist("/hp-ux", nl);
428abb0f93cSkardel
429abb0f93cSkardel if (nl[0].n_type == 0) {
430abb0f93cSkardel fputs("adjtimed: /hp-ux has no symbol table\n", stderr);
431abb0f93cSkardel msyslog(LOG_ERR, "/hp-ux has no symbol table");
432abb0f93cSkardel return (-1);
433abb0f93cSkardel }
434abb0f93cSkardel /*
435abb0f93cSkardel * Set the default to the system's original value
436abb0f93cSkardel */
437abb0f93cSkardel default_rate = GetClockRate();
438abb0f93cSkardel if (default_rate == UNKNOWN_RATE) default_rate = DEFAULT_RATE;
439abb0f93cSkardel tick_rate = (MILLION / default_rate);
440abb0f93cSkardel slew_rate = TICK_ADJ * tick_rate;
441abb0f93cSkardel fprintf(stderr,"default_rate=%ld, tick_rate=%ld, slew_rate=%ld\n",default_rate,tick_rate,slew_rate);
442abb0f93cSkardel
443abb0f93cSkardel return (0);
444abb0f93cSkardel } /* InitClockRate */
445abb0f93cSkardel
446abb0f93cSkardel /*
447abb0f93cSkardel * Reset the clock rate to the default value.
448abb0f93cSkardel */
449abb0f93cSkardel void
ResetClockRate(void)450abb0f93cSkardel ResetClockRate(void)
451abb0f93cSkardel {
452abb0f93cSkardel struct itimerval it;
453abb0f93cSkardel
454abb0f93cSkardel it.it_value.tv_sec = it.it_value.tv_usec = 0L;
455abb0f93cSkardel setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
456abb0f93cSkardel
457abb0f93cSkardel if (verbose > 2) puts("adjtimed: resetting the clock");
458abb0f93cSkardel if (sysdebug > 2) msyslog(LOG_INFO, "resetting the clock");
459abb0f93cSkardel
460abb0f93cSkardel if (GetClockRate() != default_rate) {
461abb0f93cSkardel if (SetClockRate(default_rate) == -1) {
462abb0f93cSkardel msyslog(LOG_ERR, "set clock rate: %m");
463abb0f93cSkardel perror("adjtimed: set clock rate");
464abb0f93cSkardel }
465abb0f93cSkardel }
466abb0f93cSkardel
467abb0f93cSkardel oldrate = 0.0;
468abb0f93cSkardel } /* ResetClockRate */
469abb0f93cSkardel
470abb0f93cSkardel void
Cleanup(void)471abb0f93cSkardel Cleanup(void)
472abb0f93cSkardel {
473abb0f93cSkardel ResetClockRate();
474abb0f93cSkardel
475abb0f93cSkardel if (msgctl(mqid, IPC_RMID, (struct msqid_ds *)0) == -1) {
476abb0f93cSkardel if (errno != EINVAL) {
477abb0f93cSkardel msyslog(LOG_ERR, "remove message queue: %m");
478abb0f93cSkardel perror("adjtimed: remove message queue");
479abb0f93cSkardel }
480abb0f93cSkardel }
481abb0f93cSkardel
482abb0f93cSkardel Exit(2);
483abb0f93cSkardel } /* Cleanup */
484abb0f93cSkardel
485abb0f93cSkardel void
Exit(status)486abb0f93cSkardel Exit(status)
487abb0f93cSkardel int status;
488abb0f93cSkardel {
489abb0f93cSkardel msyslog(LOG_ERR, "terminated");
490abb0f93cSkardel closelog();
491abb0f93cSkardel if (kmem != -1) close(kmem);
492abb0f93cSkardel exit(status);
493abb0f93cSkardel } /* Exit */
494