Deleted Added
full compact
adjkerntz.c (8871) adjkerntz.c (15046)
1/*
1/*
2 * Copyright (C) 1993, 1994, 1995 by Andrey A. Chernov, Moscow, Russia.
2 * Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 10 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#ifndef lint
28char copyright[] =
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright

--- 10 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#ifndef lint
28char copyright[] =
29"@(#)Copyright (C) 1993, 1994, 1995 by Andrey A. Chernov, Moscow, Russia.\n\
29"@(#)Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.\n\
30 All rights reserved.\n";
31#endif /* not lint */
32
33/*
34 * Andrey A. Chernov <ache@astral.msk.su> Dec 20 1993
35 *
36 * Fix kernel time value if machine run wall CMOS clock
37 * (and /etc/wall_cmos_clock file present)

--- 11 unchanged lines hidden (view full) ---

49#include <sys/time.h>
50#include <sys/param.h>
51#include <machine/cpu.h>
52#include <sys/sysctl.h>
53
54#include "pathnames.h"
55
56/*#define DEBUG*/
30 All rights reserved.\n";
31#endif /* not lint */
32
33/*
34 * Andrey A. Chernov <ache@astral.msk.su> Dec 20 1993
35 *
36 * Fix kernel time value if machine run wall CMOS clock
37 * (and /etc/wall_cmos_clock file present)

--- 11 unchanged lines hidden (view full) ---

49#include <sys/time.h>
50#include <sys/param.h>
51#include <machine/cpu.h>
52#include <sys/sysctl.h>
53
54#include "pathnames.h"
55
56/*#define DEBUG*/
57
58#define True (1)
59#define False (0)
60#define Unknown (-1)
61
57#define REPORT_PERIOD (30*60)
58
59void fake() {}
60
61int main(argc, argv)
62 int argc;
63 char **argv;
64{
65 struct tm local, utc;
66 struct timeval tv, *stv;
67 struct timezone tz, *stz;
62#define REPORT_PERIOD (30*60)
63
64void fake() {}
65
66int main(argc, argv)
67 int argc;
68 char **argv;
69{
70 struct tm local, utc;
71 struct timeval tv, *stv;
72 struct timezone tz, *stz;
68 int kern_offset;
73 int kern_offset, wall_clock, disrtcset;
69 size_t len;
70 int mib[2];
71 /* Avoid time_t here, can be unsigned long or worse */
72 long offset, utcsec, localsec, diff;
73 time_t initial_sec, final_sec;
74 size_t len;
75 int mib[2];
76 /* Avoid time_t here, can be unsigned long or worse */
77 long offset, utcsec, localsec, diff;
78 time_t initial_sec, final_sec;
74 int ch, init = -1;
75 int initial_isdst = -1, final_isdst, looping;
76 int disrtcset, need_restore = 0;
79 int ch;
80 int initial_isdst = -1, final_isdst;
81 int need_restore = False, sleep_mode = False, looping,
82 init = Unknown;
77 sigset_t mask, emask;
78
83 sigset_t mask, emask;
84
79 while ((ch = getopt(argc, argv, "ai")) != EOF)
85 while ((ch = getopt(argc, argv, "ais")) != EOF)
80 switch((char)ch) {
81 case 'i': /* initial call, save offset */
86 switch((char)ch) {
87 case 'i': /* initial call, save offset */
82 if (init != -1)
88 if (init != Unknown)
83 goto usage;
89 goto usage;
84 init = 1;
90 init = True;
85 break;
86 case 'a': /* adjustment call, use saved offset */
91 break;
92 case 'a': /* adjustment call, use saved offset */
87 if (init != -1)
93 if (init != Unknown)
88 goto usage;
94 goto usage;
89 init = 0;
95 init = False;
90 break;
96 break;
97 case 's':
98 sleep_mode = True;
99 break;
91 default:
92 usage:
93 fprintf(stderr, "Usage:\n\
100 default:
101 usage:
102 fprintf(stderr, "Usage:\n\
94\tadjkerntz -i\t(initial call from /etc/rc)\n\
95\tadjkerntz -a\t(adjustment call from crontab)\n");
103\tadjkerntz -i\t\t(initial call from /etc/rc)\n\
104\tadjkerntz -a [-s]\t(adjustment call, -s for sleep/retry mode)\n");
96 return 2;
97 }
105 return 2;
106 }
98 if (init == -1)
107 if (init == Unknown)
99 goto usage;
108 goto usage;
109 if (init)
110 sleep_mode = True;
100
111
101 if (access(_PATH_CLOCK, F_OK))
102 return 0;
103
104 sigemptyset(&mask);
105 sigemptyset(&emask);
106 sigaddset(&mask, SIGTERM);
107
108 openlog("adjkerntz", LOG_PID|LOG_PERROR, LOG_DAEMON);
109
110 (void) signal(SIGHUP, SIG_IGN);
111
112 if (init && daemon(0, 1)) {
113 syslog(LOG_ERR, "daemon: %m");
114 return 1;
115 }
116
112 sigemptyset(&mask);
113 sigemptyset(&emask);
114 sigaddset(&mask, SIGTERM);
115
116 openlog("adjkerntz", LOG_PID|LOG_PERROR, LOG_DAEMON);
117
118 (void) signal(SIGHUP, SIG_IGN);
119
120 if (init && daemon(0, 1)) {
121 syslog(LOG_ERR, "daemon: %m");
122 return 1;
123 }
124
117again:
125 if (init)
126 wall_clock = (access(_PATH_CLOCK, F_OK) == 0);
127 else {
128 mib[0] = CTL_MACHDEP;
129 mib[1] = CPU_WALLCLOCK;
130 len = sizeof(wall_clock);
131 if (sysctl(mib, 2, &wall_clock, &len, NULL, 0) == -1) {
132 syslog(LOG_ERR, "sysctl(get_wallclock): %m");
133 return 1;
134 }
135 }
118
136
137again:
119 (void) sigprocmask(SIG_BLOCK, &mask, NULL);
120 (void) signal(SIGTERM, fake);
121
122 diff = 0;
123 stv = NULL;
124 stz = NULL;
138 (void) sigprocmask(SIG_BLOCK, &mask, NULL);
139 (void) signal(SIGTERM, fake);
140
141 diff = 0;
142 stv = NULL;
143 stz = NULL;
125 looping = 0;
144 looping = False;
126
127 mib[0] = CTL_MACHDEP;
128 mib[1] = CPU_ADJKERNTZ;
129 len = sizeof(kern_offset);
130 if (sysctl(mib, 2, &kern_offset, &len, NULL, 0) == -1) {
131 syslog(LOG_ERR, "sysctl(get_offset): %m");
132 return 1;
133 }

--- 22 unchanged lines hidden (view full) ---

156 localsec = mktime(&local);
157 if (utcsec == -1 || localsec == -1) {
158 /*
159 * XXX user can only control local time, and it is
160 * unacceptable to fail here for init. 2:30 am in the
161 * middle of the nonexistent hour means 3:30 am.
162 */
163 syslog(LOG_WARNING,
145
146 mib[0] = CTL_MACHDEP;
147 mib[1] = CPU_ADJKERNTZ;
148 len = sizeof(kern_offset);
149 if (sysctl(mib, 2, &kern_offset, &len, NULL, 0) == -1) {
150 syslog(LOG_ERR, "sysctl(get_offset): %m");
151 return 1;
152 }

--- 22 unchanged lines hidden (view full) ---

175 localsec = mktime(&local);
176 if (utcsec == -1 || localsec == -1) {
177 /*
178 * XXX user can only control local time, and it is
179 * unacceptable to fail here for init. 2:30 am in the
180 * middle of the nonexistent hour means 3:30 am.
181 */
182 syslog(LOG_WARNING,
164 "Nonexistent local time -- will retry after %d secs", REPORT_PERIOD);
183 "Warning: nonexistent %s time.",
184 utcsec == -1 && localsec == -1 ? "UTC time and local" :
185 utcsec == -1 ? "UTC" : "local");
186 if (!sleep_mode) {
187 syslog(LOG_WARNING, "Giving up.");
188 return 1;
189 }
190 syslog(LOG_WARNING, "Will retry after %d minutes.",
191 REPORT_PERIOD / 60);
165 (void) signal(SIGTERM, SIG_DFL);
166 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
167 (void) sleep(REPORT_PERIOD);
168 goto again;
169 }
170 offset = utcsec - localsec;
171#ifdef DEBUG
172 fprintf(stderr, "Initial offset: %ld secs\n", offset);

--- 13 unchanged lines hidden (view full) ---

186 final_sec = initial_sec + diff;
187
188 /* get the actual local timezone difference */
189 local = *localtime(&final_sec);
190 final_isdst = diff < 0 ? initial_isdst : local.tm_isdst;
191 if (diff > 0 && initial_isdst != final_isdst) {
192 if (looping)
193 goto bad_final;
192 (void) signal(SIGTERM, SIG_DFL);
193 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
194 (void) sleep(REPORT_PERIOD);
195 goto again;
196 }
197 offset = utcsec - localsec;
198#ifdef DEBUG
199 fprintf(stderr, "Initial offset: %ld secs\n", offset);

--- 13 unchanged lines hidden (view full) ---

213 final_sec = initial_sec + diff;
214
215 /* get the actual local timezone difference */
216 local = *localtime(&final_sec);
217 final_isdst = diff < 0 ? initial_isdst : local.tm_isdst;
218 if (diff > 0 && initial_isdst != final_isdst) {
219 if (looping)
220 goto bad_final;
194 looping++;
221 looping = True;
195 initial_isdst = final_isdst;
196 goto recalculate;
197 }
198 utc = *gmtime(&final_sec);
199 local.tm_isdst = utc.tm_isdst = final_isdst;
200
201 utcsec = mktime(&utc);
202 localsec = mktime(&local);
203 if (utcsec == -1 || localsec == -1) {
204 bad_final:
205 /*
206 * XXX as above. The user has even less control,
207 * but perhaps we never get here.
208 */
209 syslog(LOG_WARNING,
222 initial_isdst = final_isdst;
223 goto recalculate;
224 }
225 utc = *gmtime(&final_sec);
226 local.tm_isdst = utc.tm_isdst = final_isdst;
227
228 utcsec = mktime(&utc);
229 localsec = mktime(&local);
230 if (utcsec == -1 || localsec == -1) {
231 bad_final:
232 /*
233 * XXX as above. The user has even less control,
234 * but perhaps we never get here.
235 */
236 syslog(LOG_WARNING,
210 "Nonexistent (final) local time -- will retry after %d secs", REPORT_PERIOD);
237 "Warning: nonexistent final %s time.",
238 utcsec == -1 && localsec == -1 ? "UTC time and local" :
239 utcsec == -1 ? "UTC" : "local");
240 if (!sleep_mode) {
241 syslog(LOG_WARNING, "Giving up.");
242 return 1;
243 }
244 syslog(LOG_WARNING, "Will retry after %d minutes.",
245 REPORT_PERIOD / 60);
211 (void) signal(SIGTERM, SIG_DFL);
212 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
213 (void) sleep(REPORT_PERIOD);
214 goto again;
215 }
216 offset = utcsec - localsec;
217#ifdef DEBUG
218 fprintf(stderr, "Final offset: %ld secs\n", offset);

--- 13 unchanged lines hidden (view full) ---

232 stv = &tv;
233 }
234 }
235
236 if (tz.tz_dsttime != 0 || tz.tz_minuteswest != 0) {
237 tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */
238 stz = &tz;
239 }
246 (void) signal(SIGTERM, SIG_DFL);
247 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
248 (void) sleep(REPORT_PERIOD);
249 goto again;
250 }
251 offset = utcsec - localsec;
252#ifdef DEBUG
253 fprintf(stderr, "Final offset: %ld secs\n", offset);

--- 13 unchanged lines hidden (view full) ---

267 stv = &tv;
268 }
269 }
270
271 if (tz.tz_dsttime != 0 || tz.tz_minuteswest != 0) {
272 tz.tz_dsttime = tz.tz_minuteswest = 0; /* zone info is garbage */
273 stz = &tz;
274 }
275 if (!wall_clock && stz == NULL)
276 stv = NULL;
240
277
241 /* if init and something will be changed, don't touch RTC at all */
242 if (init && (stv != NULL || kern_offset != offset)) {
278 /* if init or UTC clock and offset/date will be changed, */
279 /* disable RTC modification for a while. */
280
281 if ( (init && stv != NULL)
282 || ((init || !wall_clock) && kern_offset != offset)
283 ) {
243 mib[0] = CTL_MACHDEP;
244 mib[1] = CPU_DISRTCSET;
245 len = sizeof(disrtcset);
246 if (sysctl(mib, 2, &disrtcset, &len, NULL, 0) == -1) {
247 syslog(LOG_ERR, "sysctl(get_disrtcset): %m");
248 return 1;
249 }
250 if (disrtcset == 0) {
251 disrtcset = 1;
284 mib[0] = CTL_MACHDEP;
285 mib[1] = CPU_DISRTCSET;
286 len = sizeof(disrtcset);
287 if (sysctl(mib, 2, &disrtcset, &len, NULL, 0) == -1) {
288 syslog(LOG_ERR, "sysctl(get_disrtcset): %m");
289 return 1;
290 }
291 if (disrtcset == 0) {
292 disrtcset = 1;
252 need_restore = 1;
293 need_restore = True;
253 if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
254 syslog(LOG_ERR, "sysctl(set_disrtcset): %m");
255 return 1;
256 }
257 }
258 }
259
294 if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
295 syslog(LOG_ERR, "sysctl(set_disrtcset): %m");
296 return 1;
297 }
298 }
299 }
300
260 if (( (init && (stv != NULL || stz != NULL))
261 || (stz != NULL && stv == NULL)
262 )
301 if ( ( (init && (stv != NULL || stz != NULL))
302 || (stz != NULL && stv == NULL)
303 )
263 && settimeofday(stv, stz)
264 ) {
265 syslog(LOG_ERR, "settimeofday: %m");
266 return 1;
267 }
268
304 && settimeofday(stv, stz)
305 ) {
306 syslog(LOG_ERR, "settimeofday: %m");
307 return 1;
308 }
309
269 /* init: don't write RTC, !init: write RTC */
310 /* setting CPU_ADJKERNTZ have a side effect: resettodr(), which */
311 /* can be disabled by CPU_DISRTCSET, so if init or UTC clock */
312 /* -- don't write RTC, else write RTC. */
313
270 if (kern_offset != offset) {
271 kern_offset = offset;
272 mib[0] = CTL_MACHDEP;
273 mib[1] = CPU_ADJKERNTZ;
274 len = sizeof(kern_offset);
275 if (sysctl(mib, 2, NULL, NULL, &kern_offset, len) == -1) {
276 syslog(LOG_ERR, "sysctl(update_offset): %m");
277 return 1;
278 }
279 }
280
314 if (kern_offset != offset) {
315 kern_offset = offset;
316 mib[0] = CTL_MACHDEP;
317 mib[1] = CPU_ADJKERNTZ;
318 len = sizeof(kern_offset);
319 if (sysctl(mib, 2, NULL, NULL, &kern_offset, len) == -1) {
320 syslog(LOG_ERR, "sysctl(update_offset): %m");
321 return 1;
322 }
323 }
324
325 if (init) {
326 mib[0] = CTL_MACHDEP;
327 mib[1] = CPU_WALLCLOCK;
328 len = sizeof(wall_clock);
329 if (sysctl(mib, 2, NULL, NULL, &wall_clock, len) == -1) {
330 syslog(LOG_ERR, "sysctl(put_wallclock): %m");
331 return 1;
332 }
333 }
334
281 if (need_restore) {
335 if (need_restore) {
282 need_restore = 0;
336 need_restore = False;
283 mib[0] = CTL_MACHDEP;
284 mib[1] = CPU_DISRTCSET;
285 disrtcset = 0;
286 len = sizeof(disrtcset);
287 if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
288 syslog(LOG_ERR, "sysctl(restore_disrtcset): %m");
289 return 1;
290 }
291 }
292
293/****** End of critical section ******/
294
337 mib[0] = CTL_MACHDEP;
338 mib[1] = CPU_DISRTCSET;
339 disrtcset = 0;
340 len = sizeof(disrtcset);
341 if (sysctl(mib, 2, NULL, NULL, &disrtcset, len) == -1) {
342 syslog(LOG_ERR, "sysctl(restore_disrtcset): %m");
343 return 1;
344 }
345 }
346
347/****** End of critical section ******/
348
295 if (init) {
296 init = 0;
349 if (init && wall_clock) {
350 init = False;
297 /* wait for signals and acts like -a */
298 (void) sigsuspend(&emask);
299 goto again;
300 }
301
302 return 0;
303}
351 /* wait for signals and acts like -a */
352 (void) sigsuspend(&emask);
353 goto again;
354 }
355
356 return 0;
357}