]> git.ipfire.org Git - thirdparty/util-linux.git/blame - hwclock/hwclock.c
Imported from util-linux-2.11x tarball.
[thirdparty/util-linux.git] / hwclock / hwclock.c
CommitLineData
7eda085c
KZ
1/*
2 * hwclock.c
3 *
4 * clock.c was written by Charles Hedrick, hedrick@cs.rutgers.edu, Apr 1992
5 * Modified for clock adjustments - Rob Hooft <hooft@chem.ruu.nl>, Nov 1992
6 * Improvements by Harald Koenig <koenig@nova.tat.physik.uni-tuebingen.de>
7 * and Alan Modra <alan@spri.levels.unisa.edu.au>.
8 *
9 * Major rewrite by Bryan Henderson <bryanh@giraffe-data.com>, 96.09.19.
10 * The new program is called hwclock. New features:
11 * - You can set the hardware clock without also modifying the system clock.
12 * - You can read and set the clock with finer than 1 second precision.
13 * - When you set the clock, hwclock automatically refigures the drift
14 * rate, based on how far off the clock was before you set it.
15 *
16 * Reshuffled things, added sparc code, and re-added alpha stuff
17 * by David Mosberger <davidm@azstarnet.com>
18 * and Jay Estabrook <jestabro@amt.tay1.dec.com>
19 * and Martin Ostermann <ost@coments.rwth-aachen.de>, aeb@cwi.nl, 990212.
20 *
21 * Fix for Award 2094 bug, Dave Coffin (dcoffin@shore.net) 11/12/98
22853e4a 22 * Change of local time handling, Stefan Ring <e9725446@stud3.tuwien.ac.at>
63cccae4 23 * Change of adjtime handling, James P. Rutledge <ao112@rgfn.epcc.edu>.
66ee8158
KZ
24 *
25 * Distributed under GPL
7eda085c
KZ
26 */
27
28/*
29 * clock [-u] -r - read hardware clock
30 * clock [-u] -w - write hardware clock from system time
31 * clock [-u] -s - set system time from hardware clock
32 * clock [-u] -a - set system time from hardware clock, adjust the time
33 * to correct for systematic error, and write it back to
34 * the hardware clock
35 * -u indicates cmos clock is kept in universal time
36 * -A indicates cmos clock is kept in Alpha ARC console time (0 == 1980)
37 * -J indicates we're dealing with a Jensen (early DEC Alpha PC)
38 */
39
40/*
41 * Explanation of `adjusting' (Rob Hooft):
42 *
43 * The problem with my machine is that its CMOS clock is 10 seconds
44 * per day slow. With this version of clock.c, and my '/etc/rc.local'
45 * reading '/etc/clock -au' instead of '/etc/clock -u -s', this error
46 * is automatically corrected at every boot.
47 *
48 * To do this job, the program reads and writes the file '/etc/adjtime'
49 * to determine the correction, and to save its data. In this file are
50 * three numbers:
51 *
52 * 1) the correction in seconds per day. (So if your clock runs 5
53 * seconds per day fast, the first number should read -5.0)
54 * 2) the number of seconds since 1/1/1970 the last time the program
55 * was used
56 * 3) the remaining part of a second which was leftover after the last
57 * adjustment
58 *
59 * Installation and use of this program:
60 *
61 * a) create a file '/etc/adjtime' containing as the first and only line:
62 * '0.0 0 0.0'
63 * b) run 'clock -au' or 'clock -a', depending on whether your cmos is in
64 * universal or local time. This updates the second number.
65 * c) set your system time using the 'date' command.
66 * d) update your cmos time using 'clock -wu' or 'clock -w'
67 * e) replace the first number in /etc/adjtime by your correction.
68 * f) put the command 'clock -au' or 'clock -a' in your '/etc/rc.local'
69 */
70
71#include <string.h>
72#include <stdio.h>
73#include <fcntl.h>
74#include <sys/ioctl.h>
75#include <errno.h>
76#include <stdlib.h>
77#include <unistd.h>
78#include <time.h>
79#include <sys/time.h>
80#include <sys/stat.h>
eb63b9b8 81#include <stdarg.h>
63cccae4
KZ
82#include <getopt.h>
83#include <sysexits.h>
7eda085c
KZ
84
85#include "clock.h"
7eda085c
KZ
86#include "nls.h"
87
88#define MYNAME "hwclock"
7eda085c
KZ
89
90char *progname = MYNAME;
91
92/* The struct that holds our hardware access routines */
93struct clock_ops *ur;
94
95#define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1));
96
97/* Here the information for time adjustments is kept. */
98#define ADJPATH "/etc/adjtime"
99
100/* Store the date here when "badyear" flag is set. */
101#define LASTDATE "/var/lib/lastdate"
102
103struct adjtime {
104 /* This is information we keep in the adjtime file that tells us how
105 to do drift corrections. Elements are all straight from the
106 adjtime file, so see documentation of that file for details.
107 Exception is <dirty>, which is an indication that what's in this
108 structure is not what's in the disk file (because it has been
109 updated since read from the disk file).
110 */
eb63b9b8 111 bool dirty;
63cccae4 112
eb63b9b8 113 /* line 1 */
63cccae4 114 double drift_factor;
7eda085c 115 time_t last_adj_time;
63cccae4
KZ
116 double not_adjusted;
117
eb63b9b8 118 /* line 2 */
7eda085c 119 time_t last_calib_time;
eb63b9b8
KZ
120 /* The most recent time that we set the clock from an external
121 authority (as opposed to just doing a drift adjustment) */
63cccae4 122
eb63b9b8
KZ
123 /* line 3 */
124 enum a_local_utc {LOCAL, UTC, UNKNOWN} local_utc;
125 /* To which time zone, local or UTC, we most recently set the
126 hardware clock. */
7eda085c
KZ
127};
128
129bool debug;
130 /* We are running in debug mode, wherein we put a lot of information about
131 what we're doing to standard output. */
132
133bool badyear;
134 /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */
135
22853e4a
KZ
136int epoch_option = -1;
137 /* User-specified epoch, used when rtc fails to return epoch. */
138
7eda085c
KZ
139/*
140 * Almost all Award BIOS's made between 04/26/94 and 05/31/95
141 * have a nasty bug limiting the RTC year byte to the range 94-99.
142 * Any year between 2000 and 2093 gets changed to 2094, every time
143 * you start the system.
144 * With the --badyear option, we write the date to file and hope
145 * that the file is updated at least once a year.
146 * I recommend putting this command "hwclock --badyear" in the monthly
147 * crontab, just to be safe. -- Dave Coffin 11/12/98
148 */
22853e4a 149static void
7eda085c
KZ
150write_date_to_file (struct tm *tm) {
151 FILE *fp;
152
153 if ((fp = fopen(LASTDATE,"w"))) {
154 fprintf(fp,"%02d.%02d.%04d\n", tm->tm_mday, tm->tm_mon+1,
155 tm->tm_year+1900);
156 fclose(fp);
157 } else
158 perror(LASTDATE);
159}
160
22853e4a 161static void
7eda085c
KZ
162read_date_from_file (struct tm *tm) {
163 int last_mday, last_mon, last_year;
164 FILE *fp;
165
166 if ((fp = fopen(LASTDATE,"r"))) {
167 if (fscanf (fp,"%d.%d.%d\n", &last_mday, &last_mon, &last_year) == 3) {
168 tm->tm_year = last_year-1900;
169 if ((tm->tm_mon << 5) + tm->tm_mday < ((last_mon-1) << 5) + last_mday)
170 tm->tm_year ++;
171 }
172 fclose(fp);
173 }
174 write_date_to_file (tm);
175}
176
63cccae4 177static double
7eda085c
KZ
178time_diff(struct timeval subtrahend, struct timeval subtractor) {
179/*---------------------------------------------------------------------------
180 The difference in seconds between two times in "timeval" format.
181----------------------------------------------------------------------------*/
63cccae4
KZ
182 return (subtrahend.tv_sec - subtractor.tv_sec)
183 + (subtrahend.tv_usec - subtractor.tv_usec) / 1E6;
7eda085c
KZ
184}
185
186
187static struct timeval
63cccae4 188time_inc(struct timeval addend, double increment) {
7eda085c
KZ
189/*----------------------------------------------------------------------------
190 The time, in "timeval" format, which is <increment> seconds after
191 the time <addend>. Of course, <increment> may be negative.
192-----------------------------------------------------------------------------*/
193 struct timeval newtime;
194
195 newtime.tv_sec = addend.tv_sec + (int) increment;
196 newtime.tv_usec = addend.tv_usec + (increment - (int) increment) * 1E6;
197
198 /* Now adjust it so that the microsecond value is between 0 and 1 million */
199 if (newtime.tv_usec < 0) {
200 newtime.tv_usec += 1E6;
201 newtime.tv_sec -= 1;
202 } else if (newtime.tv_usec >= 1E6) {
203 newtime.tv_usec -= 1E6;
204 newtime.tv_sec += 1;
205 }
63cccae4 206 return newtime;
7eda085c
KZ
207}
208
209
eb63b9b8
KZ
210static bool
211hw_clock_is_utc(const bool utc, const bool local_opt,
212 const struct adjtime adjtime) {
213 bool ret;
214
215 if (utc)
216 ret = TRUE; /* --utc explicitly given on command line */
217 else if (local_opt)
218 ret = FALSE; /* --localtime explicitly given */
219 else
220 /* get info from adjtime file - default is local */
221 ret = (adjtime.local_utc == UTC);
222 if (debug)
223 printf(_("Assuming hardware clock is kept in %s time.\n"),
224 ret ? _("UTC") : _("local"));
225 return ret;
226}
227
228
7eda085c 229
63cccae4
KZ
230static int
231read_adjtime(struct adjtime *adjtime_p) {
7eda085c
KZ
232/*----------------------------------------------------------------------------
233 Read the adjustment parameters out of the /etc/adjtime file.
234
235 Return them as the adjtime structure <*adjtime_p>.
7eda085c
KZ
236 If there is no /etc/adjtime file, return defaults.
237 If values are missing from the file, return defaults for them.
238
63cccae4 239 return value 0 if all OK, !=0 otherwise.
7eda085c
KZ
240
241-----------------------------------------------------------------------------*/
242 FILE *adjfile;
243 int rc; /* local return code */
244 struct stat statbuf; /* We don't even use the contents of this. */
245
63cccae4
KZ
246 rc = stat(ADJPATH, &statbuf);
247 if (rc < 0 && errno == ENOENT) {
248 /* He doesn't have a adjtime file, so we'll use defaults. */
249 adjtime_p->drift_factor = 0;
250 adjtime_p->last_adj_time = 0;
251 adjtime_p->not_adjusted = 0;
252 adjtime_p->last_calib_time = 0;
253 adjtime_p->local_utc = UNKNOWN;
254
255 return 0;
256 }
7eda085c 257
7eda085c
KZ
258 adjfile = fopen(ADJPATH, "r"); /* open file for reading */
259 if (adjfile == NULL) {
260 outsyserr("cannot open file " ADJPATH);
63cccae4
KZ
261 return EX_OSFILE;
262 }
263
264 {
7eda085c
KZ
265 char line1[81]; /* String: first line of adjtime file */
266 char line2[81]; /* String: second line of adjtime file */
eb63b9b8 267 char line3[81]; /* String: third line of adjtime file */
364cda48 268 long timeval;
7eda085c
KZ
269
270 line1[0] = '\0'; /* In case fgets fails */
271 fgets(line1, sizeof(line1), adjfile);
272 line2[0] = '\0'; /* In case fgets fails */
273 fgets(line2, sizeof(line2), adjfile);
eb63b9b8
KZ
274 line3[0] = '\0'; /* In case fgets fails */
275 fgets(line3, sizeof(line3), adjfile);
7eda085c
KZ
276
277 fclose(adjfile);
278
279 /* Set defaults in case values are missing from file */
280 adjtime_p->drift_factor = 0;
281 adjtime_p->last_adj_time = 0;
282 adjtime_p->not_adjusted = 0;
283 adjtime_p->last_calib_time = 0;
364cda48 284 timeval = 0;
7eda085c 285
63cccae4 286 sscanf(line1, "%lf %ld %lf",
7eda085c 287 &adjtime_p->drift_factor,
364cda48 288 &timeval,
7eda085c 289 &adjtime_p->not_adjusted);
364cda48
KZ
290 adjtime_p->last_adj_time = timeval;
291
292 sscanf(line2, "%ld", &timeval);
293 adjtime_p->last_calib_time = timeval;
eb63b9b8
KZ
294
295 if (!strcmp(line3, "UTC\n"))
296 adjtime_p->local_utc = UTC;
297 else if (!strcmp(line3, "LOCAL\n"))
298 adjtime_p->local_utc = LOCAL;
299 else {
300 adjtime_p->local_utc = UNKNOWN;
301 if (line3[0]) {
e8f26419
KZ
302 fprintf(stderr,
303 _("%s: Warning: unrecognized third line in adjtime file\n"),
eb63b9b8
KZ
304 MYNAME);
305 fprintf(stderr, _("(Expected: `UTC' or `LOCAL' or nothing.)\n"));
306 }
307 }
7eda085c
KZ
308 }
309 adjtime_p->dirty = FALSE;
310
311 if (debug) {
364cda48
KZ
312 printf(_("Last drift adjustment done at %ld seconds after 1969\n"),
313 (long) adjtime_p->last_adj_time);
314 printf(_("Last calibration done at %ld seconds after 1969\n"),
315 (long) adjtime_p->last_calib_time);
eb63b9b8
KZ
316 printf(_("Hardware clock is on %s time\n"),
317 (adjtime_p->local_utc == LOCAL) ? _("local") :
318 (adjtime_p->local_utc == UTC) ? _("UTC") : _("unknown"));
7eda085c 319 }
63cccae4
KZ
320
321 return 0;
7eda085c
KZ
322}
323
324
63cccae4
KZ
325static int
326synchronize_to_clock_tick(void) {
7eda085c
KZ
327/*-----------------------------------------------------------------------------
328 Wait until the falling edge of the Hardware Clock's update flag so
329 that any time that is read from the clock immediately after we
330 return will be exact.
331
332 The clock only has 1 second precision, so it gives the exact time only
333 once per second, right on the falling edge of the update flag.
334
335 We wait (up to one second) either blocked waiting for an rtc device
336 or in a CPU spin loop. The former is probably not very accurate.
337
63cccae4 338 Return 0 if it worked, nonzero if it didn't.
7eda085c 339-----------------------------------------------------------------------------*/
63cccae4 340 int rc;
7eda085c 341
63cccae4 342 if (debug) printf(_("Waiting for clock tick...\n"));
7eda085c 343
63cccae4
KZ
344 rc = ur->synchronize_to_clock_tick();
345
346 if (debug) printf(_("...got clock tick\n"));
347
348 return rc;
7eda085c
KZ
349}
350
351
352
353static void
354mktime_tz(struct tm tm, const bool universal,
355 bool *valid_p, time_t *systime_p) {
356/*-----------------------------------------------------------------------------
357 Convert a time in broken down format (hours, minutes, etc.) into standard
358 unix time (seconds into epoch). Return it as *systime_p.
359
360 The broken down time is argument <tm>. This broken down time is either in
361 local time zone or UTC, depending on value of logical argument "universal".
362 True means it is in UTC.
363
364 If the argument contains values that do not constitute a valid time,
365 and mktime() recognizes this, return *valid_p == false and
366 *systime_p undefined. However, mktime() sometimes goes ahead and
367 computes a fictional time "as if" the input values were valid,
368 e.g. if they indicate the 31st day of April, mktime() may compute
369 the time of May 1. In such a case, we return the same fictional
370 value mktime() does as *systime_p and return *valid_p == true.
371
372-----------------------------------------------------------------------------*/
373 time_t mktime_result; /* The value returned by our mktime() call */
374 char *zone; /* Local time zone name */
375
376 /* We use the C library function mktime(), but since it only works on
377 local time zone input, we may have to fake it out by temporarily
378 changing the local time zone to UTC.
379 */
ffc43748 380 zone = getenv("TZ"); /* remember original time zone */
7eda085c
KZ
381 if (universal) {
382 /* Set timezone to UTC */
383 setenv("TZ", "", TRUE);
384 /* Note: tzset() gets called implicitly by the time code, but only the
385 first time. When changing the environment variable, better call
386 tzset() explicitly.
387 */
388 tzset();
389 }
390 mktime_result = mktime(&tm);
391 if (mktime_result == -1) {
392 /* This apparently (not specified in mktime() documentation) means
393 the 'tm' structure does not contain valid values (however, not
394 containing valid values does _not_ imply mktime() returns -1).
395 */
396 *valid_p = FALSE;
397 *systime_p = 0;
398 if (debug)
399 printf(_("Invalid values in hardware clock: "
22853e4a
KZ
400 "%4d/%.2d/%.2d %.2d:%.2d:%.2d\n"),
401 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
402 tm.tm_hour, tm.tm_min, tm.tm_sec);
7eda085c
KZ
403 } else {
404 *valid_p = TRUE;
405 *systime_p = mktime_result;
406 if (debug)
22853e4a
KZ
407 printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
408 "%ld seconds since 1969\n"),
409 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
410 tm.tm_hour, tm.tm_min, tm.tm_sec, (long) *systime_p);
7eda085c
KZ
411 }
412 /* now put back the original zone. */
413 if (zone) setenv("TZ", zone, TRUE);
414 else unsetenv("TZ");
415 tzset();
416}
417
418
419static void
420read_hardware_clock(const bool universal, bool *valid_p, time_t *systime_p){
421/*----------------------------------------------------------------------------
422 Read the hardware clock and return the current time via <tm> argument.
423
424 Use the method indicated by <method> argument to access the hardware clock.
425-----------------------------------------------------------------------------*/
426 struct tm tm;
427 int err;
428
429 err = ur->read_hardware_clock(&tm);
430
431 if (badyear)
432 read_date_from_file(&tm);
433
434 if (debug)
22853e4a
KZ
435 printf (_("Time read from Hardware Clock: %4d/%.2d/%.2d %02d:%02d:%02d\n"),
436 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
7eda085c
KZ
437 tm.tm_hour, tm.tm_min, tm.tm_sec);
438 mktime_tz(tm, universal, valid_p, systime_p);
439}
440
441
442static void
443set_hardware_clock(const time_t newtime,
444 const bool universal,
445 const bool testing) {
446/*----------------------------------------------------------------------------
447 Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
448 according to <universal>.
449----------------------------------------------------------------------------*/
450 int err;
451 struct tm new_broken_time;
452 /* Time to which we will set Hardware Clock, in broken down format, in
453 the time zone of caller's choice
454 */
455
456 if (universal)
457 new_broken_time = *gmtime(&newtime);
458 else
459 new_broken_time = *localtime(&newtime);
460
461 if (debug)
462 printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
364cda48 463 "= %ld seconds since 1969\n"),
7eda085c 464 new_broken_time.tm_hour, new_broken_time.tm_min,
364cda48 465 new_broken_time.tm_sec, (long) newtime);
7eda085c
KZ
466
467 if (testing)
468 printf(_("Clock not changed - testing only.\n"));
469 else {
470 if (badyear) {
471 /*
472 * Write the real year to a file, then write a fake year
473 * between 1995 and 1998 to the RTC. This way, Award BIOS boots
474 * on 29 Feb 2000 thinking that it's 29 Feb 1996.
475 */
476 write_date_to_file (&new_broken_time);
477 new_broken_time.tm_year = 95 + ((new_broken_time.tm_year+1) & 3);
478 }
479 err = ur->set_hardware_clock(&new_broken_time);
480 }
481}
482
483
484
485static void
95f1bdee
KZ
486set_hardware_clock_exact(const time_t sethwtime,
487 const struct timeval refsystime,
7eda085c
KZ
488 const bool universal,
489 const bool testing) {
490/*----------------------------------------------------------------------------
95f1bdee 491 Set the Hardware Clock to the time "sethwtime", in local time zone or UTC,
7eda085c
KZ
492 according to "universal".
493
95f1bdee
KZ
494 Wait for a fraction of a second so that "sethwtime" is the value of
495 the Hardware Clock as of system time "refsystime", which is in the past.
496 For example, if "sethwtime" is 14:03:05 and "refsystime" is 12:10:04.5
497 and the current system time is 12:10:06.0: Wait .5 seconds (to make
498 exactly 2 seconds since "refsystime") and then set the Hardware Clock
499 to 14:03:07, thus getting a precise and retroactive setting of the clock.
7eda085c
KZ
500
501 (Don't be confused by the fact that the system clock and the Hardware
502 Clock differ by two hours in the above example. That's just to remind
503 you that there are two independent time scales here).
504
505 This function ought to be able to accept set times as fractional times.
506 Idea for future enhancement.
7eda085c 507-----------------------------------------------------------------------------*/
7eda085c 508
95f1bdee
KZ
509 time_t newhwtime;
510 struct timeval beginsystime, nowsystime;
511
512 time_resync:
513 gettimeofday(&beginsystime, NULL);
514 newhwtime = sethwtime + (int) time_diff(beginsystime, refsystime) + 1;
7eda085c
KZ
515 if (debug)
516 printf(_("Time elapsed since reference time has been %.6f seconds.\n"
517 "Delaying further to reach the next full second.\n"),
95f1bdee 518 time_diff(beginsystime, refsystime));
7eda085c 519
95f1bdee
KZ
520 /* Now delay some more until Hardware Clock time newhwtime arrives */
521 do {
522 float tdiff;
523 gettimeofday(&nowsystime, NULL);
524 tdiff = time_diff(nowsystime, beginsystime);
525 if (tdiff < 0)
526 goto time_resync; /* probably time was reset */
527 } while (time_diff(nowsystime, refsystime) < newhwtime - sethwtime);
7eda085c 528
95f1bdee 529 set_hardware_clock(newhwtime, universal, testing);
7eda085c
KZ
530}
531
532
533
534static void
535display_time(const bool hclock_valid, const time_t systime,
63cccae4 536 const double sync_duration) {
7eda085c
KZ
537/*----------------------------------------------------------------------------
538 Put the time "systime" on standard output in display format.
539 Except if hclock_valid == false, just tell standard output that we don't
540 know what time it is.
541
542 Include in the output the adjustment "sync_duration".
543-----------------------------------------------------------------------------*/
544 if (!hclock_valid)
545 fprintf(stderr, _("The Hardware Clock registers contain values that are "
546 "either invalid (e.g. 50th day of month) or beyond the range "
547 "we can handle (e.g. Year 2095).\n"));
548 else {
66ee8158
KZ
549 struct tm *lt;
550 char *format = "%c";
551 char ctime_now[200];
7eda085c 552
66ee8158
KZ
553 lt = localtime(&systime);
554 strftime(ctime_now, sizeof(ctime_now), format, lt);
7eda085c
KZ
555 printf(_("%s %.6f seconds\n"), ctime_now, -(sync_duration));
556 }
557}
558
559
560
561static int
562interpret_date_string(const char *date_opt, time_t * const time_p) {
563/*----------------------------------------------------------------------------
564 Interpret the value of the --date option, which is something like
565 "13:05:01". In fact, it can be any of the myriad ASCII strings that specify
566 a time which the "date" program can understand. The date option value in
567 question is our "dateopt" argument.
568
569 The specified time is in the local time zone.
570
571 Our output, "*time_p", is a seconds-into-epoch time.
572
573 We use the "date" program to interpret the date string. "date" must be
574 runnable by issuing the command "date" to the /bin/sh shell. That means
575 in must be in the current PATH.
576
577 If anything goes wrong (and many things can), we return return code
578 10 and arbitrary *time_p. Otherwise, return code is 0 and *time_p
579 is valid.
580----------------------------------------------------------------------------*/
e8f26419
KZ
581 FILE *date_child_fp;
582 char date_resp[100];
583 const char magic[]="seconds-into-epoch=";
584 char date_command[100];
585 int retcode; /* our eventual return code */
586 int rc; /* local return code */
587
588 if (date_opt == NULL) {
589 fprintf(stderr, _("No --date option specified.\n"));
590 return 14;
591 }
7eda085c 592
e8f26419
KZ
593 /* prevent overflow - a security risk */
594 if (strlen(date_opt) > sizeof(date_command) - 50) {
595 fprintf(stderr, _("--date argument too long\n"));
596 return 13;
597 }
598
599 /* Quotes in date_opt would ruin the date command we construct. */
600 if (strchr(date_opt, '"') != NULL) {
601 fprintf(stderr,
602 _("The value of the --date option is not a valid date.\n"
603 "In particular, it contains quotation marks.\n"));
604 return 12;
605 }
606
607 sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s",
608 date_opt);
609 if (debug)
610 printf(_("Issuing date command: %s\n"), date_command);
611
612 date_child_fp = popen(date_command, "r");
613 if (date_child_fp == NULL) {
614 outsyserr(_("Unable to run 'date' program in /bin/sh shell. "
615 "popen() failed"));
616 return 10;
617 }
618
619 date_resp[0] = '\0'; /* in case fgets fails */
620 fgets(date_resp, sizeof(date_resp), date_child_fp);
621 if (debug)
622 printf(_("response from date command = %s\n"), date_resp);
623 if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) {
624 fprintf(stderr, _("The date command issued by %s returned "
625 "unexpected results.\n"
626 "The command was:\n %s\n"
627 "The response was:\n %s\n"),
628 MYNAME, date_command, date_resp);
629 retcode = 8;
630 } else {
631 long seconds_since_epoch;
632 rc = sscanf(date_resp + sizeof(magic)-1, "%ld",
633 &seconds_since_epoch);
634 if (rc < 1) {
635 fprintf(stderr,
636 _("The date command issued by %s returned "
637 "something other than an integer where the "
638 "converted time value was expected.\n"
639 "The command was:\n %s\n"
640 "The response was:\n %s\n"),
641 MYNAME, date_command, date_resp);
642 retcode = 6;
643 } else {
644 retcode = 0;
645 *time_p = seconds_since_epoch;
646 if (debug)
647 printf(_("date string %s equates to "
648 "%ld seconds since 1969.\n"),
649 date_opt, (long) *time_p);
650 }
651 }
652 fclose(date_child_fp);
653
63cccae4 654 return retcode;
7eda085c
KZ
655}
656
657
658
659static int
660set_system_clock(const bool hclock_valid, const time_t newtime,
661 const bool testing) {
662/*----------------------------------------------------------------------------
663 Set the System Clock to time 'newtime'.
664
665 Also set the kernel time zone value to the value indicated by the
666 TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
eb63b9b8 667 tzset() would interpret them.
7eda085c
KZ
668
669 EXCEPT: if hclock_valid is false, just issue an error message
670 saying there is no valid time in the Hardware Clock to which to set
671 the system time.
672
673 If 'testing' is true, don't actually update anything -- just say we
674 would have.
675-----------------------------------------------------------------------------*/
eb63b9b8 676 int retcode;
7eda085c
KZ
677
678 if (!hclock_valid) {
63cccae4 679 fprintf(stderr, _("The Hardware Clock does not contain a valid time, so "
7eda085c
KZ
680 "we cannot set the System Time from it.\n"));
681 retcode = 1;
682 } else {
683 struct timeval tv;
22853e4a
KZ
684 struct tm *broken;
685 int minuteswest;
eb63b9b8 686 int rc;
7eda085c
KZ
687
688 tv.tv_sec = newtime;
689 tv.tv_usec = 0;
690
22853e4a
KZ
691 broken = localtime(&newtime);
692#ifdef HAVE_tm_gmtoff
693 minuteswest = -broken->tm_gmtoff/60; /* GNU extension */
694#else
695 minuteswest = timezone/60;
696 if (broken->tm_isdst)
697 minuteswest -= 60;
698#endif
7eda085c
KZ
699
700 if (debug) {
63cccae4
KZ
701 printf(_("Calling settimeofday:\n"));
702 printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
703 (long) tv.tv_sec, (long) tv.tv_usec);
704 printf(_("\ttz.tz_minuteswest = %d\n"), minuteswest);
7eda085c
KZ
705 }
706 if (testing) {
707 printf(_("Not setting system clock because running in test mode.\n"));
708 retcode = 0;
709 } else {
22853e4a 710 const struct timezone tz = { minuteswest, 0 };
eb63b9b8 711
7eda085c 712 rc = settimeofday(&tv, &tz);
63cccae4
KZ
713 if (rc) {
714 if (errno == EPERM) {
715 fprintf(stderr,
716 _("Must be superuser to set system clock.\n"));
717 retcode = EX_NOPERM;
718 } else {
719 outsyserr(_("settimeofday() failed"));
720 retcode = 1;
721 }
7eda085c
KZ
722 } else retcode = 0;
723 }
724 }
63cccae4 725 return retcode;
7eda085c
KZ
726}
727
728
729static void
730adjust_drift_factor(struct adjtime *adjtime_p,
731 const time_t nowtime,
63cccae4
KZ
732 const bool hclock_valid,
733 const time_t hclocktime,
734 const double sync_delay) {
735/*------------------------------------------------------------------------
7eda085c
KZ
736 Update the drift factor in <*adjtime_p> to reflect the fact that the
737 Hardware Clock was calibrated to <nowtime> and before that was set
738 to <hclocktime>.
739
7eda085c
KZ
740 We record in the adjtime file the time at which we last calibrated
741 the clock so we can compute the drift rate each time we calibrate.
742
743 EXCEPT: if <hclock_valid> is false, assume Hardware Clock was not set
744 before to anything meaningful and regular adjustments have not been
745 done, so don't adjust the drift factor.
63cccae4
KZ
746 ------------------------------------------------------------------------*/
747 if (!hclock_valid) {
748 if (debug)
749 printf(_("Not adjusting drift factor because the "
750 "Hardware Clock previously contained "
751 "garbage.\n"));
752 } else if (adjtime_p->last_calib_time == 0) {
753 if (debug)
754 printf(_("Not adjusting drift factor because last "
755 "calibration time is zero,\n"
756 "so history is bad and calibration startover "
757 "is necessary.\n"));
758 } else if ((hclocktime - adjtime_p->last_calib_time) < 23 * 60 * 60) {
759 if (debug)
760 printf(_("Not adjusting drift factor because it has "
761 "been less than a day since the last "
762 "calibration.\n"));
763 } else if (adjtime_p->last_calib_time != 0) {
764 /*
765 * At adjustment time we adjust the hardware clock according
766 * to the contents of /etc/adjtime.
767 *
768 * At calibration time we set the hardware clock and
769 * update /etc/adjtime, that is, for each calibration
770 * (except the first) we also do an adjustment.
771 *
772 * We are now at calibration time.
773 *
774 * Let us do computation in doubles. (Floats almost suffice,
775 * but 195 days + 1 second equals 195 days in floats.)
776 */
777 const double sec_per_day = 24.0 * 60.0 * 60.0;
778 double atime_per_htime;
779 double adj_days, cal_days;
780 double exp_drift, unc_drift;
781 double factor_adjust;
782
783 /* Adjusted time units per hardware time unit */
784 atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day;
785
786 /* Days since last adjustment (in hardware clock time) */
787 adj_days = (double)(hclocktime - adjtime_p->last_adj_time)
788 / sec_per_day;
789
790 /* Expected drift (sec) since last adjustment */
791 exp_drift = adj_days * adjtime_p->drift_factor
792 + adjtime_p->not_adjusted;
793
794 /* Uncorrected drift (sec) since last calibration */
795 unc_drift = (double)(nowtime - hclocktime)
796 + sync_delay - exp_drift;
797
798 /* Days since last calibration (in hardware clock time) */
799 cal_days = ((double)(adjtime_p->last_adj_time
800 - adjtime_p->last_calib_time)
801 + adjtime_p->not_adjusted)
802 / (sec_per_day * atime_per_htime) + adj_days;
803
804 /* Amount to add to previous drift factor */
805 factor_adjust = unc_drift / cal_days;
806
807 if (debug)
808 printf(_("Clock drifted %.1f seconds in the past "
809 "%d seconds in spite of a drift factor of "
810 "%f seconds/day.\n"
811 "Adjusting drift factor by %f seconds/day\n"),
812 unc_drift,
813 (int) (nowtime - adjtime_p->last_calib_time),
814 adjtime_p->drift_factor,
815 factor_adjust);
7eda085c 816
63cccae4
KZ
817 adjtime_p->drift_factor += factor_adjust;
818 }
819 adjtime_p->last_calib_time = nowtime;
7eda085c 820
63cccae4 821 adjtime_p->last_adj_time = nowtime;
7eda085c 822
63cccae4 823 adjtime_p->not_adjusted = 0;
7eda085c 824
63cccae4 825 adjtime_p->dirty = TRUE;
7eda085c
KZ
826}
827
828
829
830static void
63cccae4 831calculate_adjustment(const double factor,
7eda085c 832 const time_t last_time,
63cccae4 833 const double not_adjusted,
7eda085c
KZ
834 const time_t systime,
835 int *adjustment_p,
63cccae4 836 double *retro_p,
7eda085c
KZ
837 const int debug ) {
838/*----------------------------------------------------------------------------
839 Do the drift adjustment calculation.
840
841 The way we have to set the clock, we need the adjustment in two parts:
842
843 1) an integer number of seconds (return as *adjustment_p)
844
845 2) a positive fraction of a second (less than 1) (return as *retro_p)
846
847 The sum of these two values is the adjustment needed. Positive means to
848 advance the clock or insert seconds. Negative means to retard the clock
849 or remove seconds.
850----------------------------------------------------------------------------*/
63cccae4 851 double exact_adjustment;
7eda085c 852
63cccae4 853 exact_adjustment = ((double) (systime - last_time)) * factor / (24 * 60 * 60)
7eda085c
KZ
854 + not_adjusted;
855 *adjustment_p = FLOOR(exact_adjustment);
856
63cccae4 857 *retro_p = exact_adjustment - (double) *adjustment_p;
7eda085c
KZ
858 if (debug) {
859 printf (_("Time since last adjustment is %d seconds\n"),
860 (int) (systime - last_time));
861 printf (_("Need to insert %d seconds and refer time back "
862 "%.6f seconds ago\n"),
863 *adjustment_p, *retro_p);
864 }
865}
866
867
868
869static void
870save_adjtime(const struct adjtime adjtime, const bool testing) {
871/*-----------------------------------------------------------------------------
872 Write the contents of the <adjtime> structure to its disk file.
873
874 But if the contents are clean (unchanged since read from disk), don't
875 bother.
876-----------------------------------------------------------------------------*/
eb63b9b8 877 char newfile[412]; /* Stuff to write to disk file */
7eda085c
KZ
878
879 if (adjtime.dirty) {
880 /* snprintf is not always available, but this is safe
881 as long as libc does not use more than 100 positions for %ld or %f */
eb63b9b8 882 sprintf(newfile, "%f %ld %f\n%ld\n%s\n",
7eda085c
KZ
883 adjtime.drift_factor,
884 (long) adjtime.last_adj_time,
885 adjtime.not_adjusted,
eb63b9b8
KZ
886 (long) adjtime.last_calib_time,
887 (adjtime.local_utc == UTC) ? "UTC" : "LOCAL");
7eda085c
KZ
888
889 if (testing) {
890 printf(_("Not updating adjtime file because of testing mode.\n"));
891 printf(_("Would have written the following to %s:\n%s"),
892 ADJPATH, newfile);
893 } else {
894 FILE *adjfile;
895 int err = 0;
896
897 adjfile = fopen(ADJPATH, "w");
898 if (adjfile == NULL) {
899 outsyserr("Could not open file with the clock adjustment parameters "
900 "in it (" ADJPATH ") for writing");
901 err = 1;
902 } else {
66ee8158 903 if (fputs(newfile, adjfile) < 0) {
7eda085c
KZ
904 outsyserr("Could not update file with the clock adjustment "
905 "parameters (" ADJPATH ") in it");
906 err = 1;
907 }
908 if (fclose(adjfile) < 0) {
909 outsyserr("Could not update file with the clock adjustment "
910 "parameters (" ADJPATH ") in it");
911 err = 1;
912 }
913 }
914 if (err)
915 fprintf(stderr, _("Drift adjustment parameters not updated.\n"));
916 }
917 }
918}
919
920
921
922static void
923do_adjustment(struct adjtime *adjtime_p,
924 const bool hclock_valid, const time_t hclocktime,
925 const struct timeval read_time,
926 const bool universal, const bool testing) {
927/*---------------------------------------------------------------------------
928 Do the adjustment requested, by 1) setting the Hardware Clock (if
929 necessary), and 2) updating the last-adjusted time in the adjtime
930 structure.
931
932 Do not update anything if the Hardware Clock does not currently present
933 a valid time.
934
935 arguments <factor> and <last_time> are current values from the adjtime
936 file.
937
938 <hclock_valid> means the Hardware Clock contains a valid time, and that
939 time is <hclocktime>.
940
941 <read_time> is the current system time (to be precise, it is the system
942 time at the time <hclocktime> was read, which due to computational delay
943 could be a short time ago).
944
945 <universal>: the Hardware Clock is kept in UTC.
946
947 <testing>: We are running in test mode (no updating of clock).
948
949 We do not bother to update the clock if the adjustment would be less than
950 one second. This is to avoid cumulative error and needless CPU hogging
951 (remember we use an infinite loop for some timing) if the user runs us
952 frequently.
953
954----------------------------------------------------------------------------*/
955 if (!hclock_valid) {
956 fprintf(stderr, _("The Hardware Clock does not contain a valid time, "
957 "so we cannot adjust it.\n"));
63cccae4
KZ
958 adjtime_p->last_calib_time = 0; /* calibration startover is required */
959 adjtime_p->last_adj_time = 0;
960 adjtime_p->not_adjusted = 0;
961 adjtime_p->dirty = TRUE;
962 } else if (adjtime_p->last_adj_time == 0) {
963 if (debug)
964 printf("Not setting clock because last adjustment time is zero, "
965 "so history is bad.");
7eda085c
KZ
966 } else {
967 int adjustment;
968 /* Number of seconds we must insert in the Hardware Clock */
63cccae4 969 double retro;
7eda085c
KZ
970 /* Fraction of second we have to remove from clock after inserting
971 <adjustment> whole seconds.
972 */
973 calculate_adjustment(adjtime_p->drift_factor,
974 adjtime_p->last_adj_time,
975 adjtime_p->not_adjusted,
976 hclocktime,
977 &adjustment, &retro,
978 debug );
979 if (adjustment > 0 || adjustment < -1) {
980 set_hardware_clock_exact(hclocktime + adjustment,
981 time_inc(read_time, -retro),
982 universal, testing);
983 adjtime_p->last_adj_time = hclocktime + adjustment;
984 adjtime_p->not_adjusted = 0;
985 adjtime_p->dirty = TRUE;
986 } else
987 if (debug)
988 printf(_("Needed adjustment is less than one second, "
989 "so not setting clock.\n"));
990 }
991}
992
993
994
995static void
996determine_clock_access_method(const bool user_requests_ISA) {
997
998 ur = NULL;
999
1000 if (user_requests_ISA)
1001 ur = probe_for_cmos_clock();
1002
1003 if (!ur)
1004 ur = probe_for_rtc_clock();
1005
1006 if (!ur)
1007 ur = probe_for_kd_clock();
1008
1009 if (!ur && !user_requests_ISA)
1010 ur = probe_for_cmos_clock();
1011
1012 if (debug) {
1013 if (ur)
1014 printf(_("Using %s.\n"), ur->interface_name);
1015 else
1016 printf(_("No usable clock interface found.\n"));
1017 }
1018}
1019
63cccae4 1020static int
364cda48 1021manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
7eda085c
KZ
1022 const bool set, const time_t set_time,
1023 const bool hctosys, const bool systohc,
1024 const struct timeval startup_time,
eb63b9b8 1025 const bool utc, const bool local_opt,
63cccae4 1026 const bool testing) {
7eda085c
KZ
1027/*---------------------------------------------------------------------------
1028 Do all the normal work of hwclock - read, set clock, etc.
1029
1030 Issue output to stdout and error message to stderr where appropriate.
1031
1032 Return rc == 0 if everything went OK, rc != 0 if not.
1033----------------------------------------------------------------------------*/
63cccae4
KZ
1034 struct adjtime adjtime;
1035 /* Contents of the adjtime file, or what they should be. */
1036 int rc; /* local return code */
1037 bool no_auth; /* User lacks necessary authorization to access the clock */
1038
1039 no_auth = ur->get_permissions();
1040 if (no_auth)
1041 return EX_NOPERM;
1042
1043 if (!noadjfile && (adjust || set || systohc || (!utc && !local_opt))) {
1044 rc = read_adjtime(&adjtime);
1045 if (rc)
1046 return rc;
1047 } else {
7eda085c
KZ
1048 /* A little trick to avoid reading the file if we don't have to */
1049 adjtime.dirty = FALSE;
1050 rc = 0;
1051 }
63cccae4
KZ
1052
1053 {
eb63b9b8
KZ
1054 const bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
1055
1056 if ((set || systohc || adjust) &&
1057 (adjtime.local_utc == UTC) != universal) {
1058 adjtime.local_utc = universal ? UTC : LOCAL;
1059 adjtime.dirty = TRUE;
1060 }
1061
63cccae4
KZ
1062 rc = synchronize_to_clock_tick(); /* this takes up to 1 second */
1063 if (rc)
1064 return rc;
1065
1066 {
7eda085c
KZ
1067 struct timeval read_time;
1068 /* The time at which we read the Hardware Clock */
1069
1070 bool hclock_valid;
1071 /* The Hardware Clock gives us a valid time, or at least something
1072 close enough to fool mktime().
1073 */
1074
1075 time_t hclocktime;
1076 /* The time the hardware clock had just after we
1077 synchronized to its next clock tick when we started up.
1078 Defined only if hclock_valid is true.
1079 */
1080
1081 gettimeofday(&read_time, NULL);
1082 read_hardware_clock(universal, &hclock_valid, &hclocktime);
1083
1084 if (show) {
1085 display_time(hclock_valid, hclocktime,
1086 time_diff(read_time, startup_time));
7eda085c
KZ
1087 } else if (set) {
1088 set_hardware_clock_exact(set_time, startup_time,
1089 universal, testing);
63cccae4
KZ
1090 adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime,
1091 time_diff(read_time, startup_time));
7eda085c
KZ
1092 } else if (adjust) {
1093 do_adjustment(&adjtime, hclock_valid, hclocktime,
1094 read_time, universal, testing);
7eda085c
KZ
1095 } else if (systohc) {
1096 struct timeval nowtime, reftime;
1097 /* We can only set_hardware_clock_exact to a whole seconds
1098 time, so we set it with reference to the most recent
1099 whole seconds time.
1100 */
1101 gettimeofday(&nowtime, NULL);
1102 reftime.tv_sec = nowtime.tv_sec;
1103 reftime.tv_usec = 0;
1104
1105 set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
1106 universal, testing);
7eda085c 1107 adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
63cccae4 1108 hclocktime, (double) read_time.tv_usec / 1E6);
7eda085c
KZ
1109 } else if (hctosys) {
1110 rc = set_system_clock(hclock_valid, hclocktime, testing);
63cccae4 1111 if (rc) {
7eda085c 1112 printf(_("Unable to set system clock.\n"));
63cccae4
KZ
1113 return rc;
1114 }
7eda085c 1115 }
63cccae4 1116 if (!noadjfile)
364cda48 1117 save_adjtime(adjtime, testing);
7eda085c
KZ
1118 }
1119 }
63cccae4 1120 return 0;
7eda085c
KZ
1121}
1122
1123
1124static void
1125manipulate_epoch(const bool getepoch, const bool setepoch,
1126 const int epoch_opt, const bool testing) {
1127/*----------------------------------------------------------------------------
1128 Get or set the Hardware Clock epoch value in the kernel, as appropriate.
1129 <getepoch>, <setepoch>, and <epoch> are hwclock invocation options.
1130
1131 <epoch> == -1 if the user did not specify an "epoch" option.
1132
1133-----------------------------------------------------------------------------*/
1134 /*
1135 Maintenance note: This should work on non-Alpha machines, but the
1136 evidence today (98.03.04) indicates that the kernel only keeps the
1137 epoch value on Alphas. If that is ever fixed, this function should be
1138 changed.
1139 */
1140
1141#ifndef __alpha__
1142 fprintf(stderr, _("The kernel keeps an epoch value for the Hardware Clock "
1143 "only on an Alpha machine.\nThis copy of hwclock was built for "
1144 "a machine other than Alpha\n(and thus is presumably not running "
1145 "on an Alpha now). No action taken.\n"));
1146#else
1147 if (getepoch) {
1148 unsigned long epoch;
1149
1150 if (get_epoch_rtc(&epoch, 0))
1151 fprintf(stderr, _("Unable to get the epoch value from the kernel.\n"));
1152 else
1153 printf(_("Kernel is assuming an epoch value of %lu\n"), epoch);
1154 } else if (setepoch) {
1155 if (epoch_opt == -1)
1156 fprintf(stderr, _("To set the epoch value, you must use the 'epoch' "
1157 "option to tell to what value to set it.\n"));
1158 else if (testing)
1159 printf(_("Not setting the epoch to %d - testing only.\n"),
1160 epoch_opt);
1161 else if (set_epoch_rtc(epoch_opt))
1162 printf(_("Unable to set the epoch value in the kernel.\n"));
1163 }
1164#endif
1165}
1166
66ee8158
KZ
1167#if __ia64__
1168#define RTC_DEV "/dev/efirtc"
1169#else
1170#define RTC_DEV "/dev/rtc"
1171#endif
1172
63cccae4
KZ
1173static void
1174out_version(void) {
1175 printf(_("%s from %s\n"), MYNAME, util_linux_version);
1176}
1177
eb63b9b8
KZ
1178/*
1179 usage - Output (error and) usage information
1180
1181 This function is called both directly from main to show usage
1182 information and as fatal function from shhopt if some argument is
1183 not understood. In case of normal usage info FMT should be NULL.
1184 In that case the info is printed to stdout. If FMT is given
1185 usage will act like fprintf( stderr, fmt, ... ), show a usage
1186 information and terminate the program afterwards.
1187*/
1188static void
1189usage( const char *fmt, ... ) {
1190 FILE *usageto;
1191 va_list ap;
1192
1193 usageto = fmt ? stderr : stdout;
1194
1195 fprintf( usageto, _(
1196 "hwclock - query and set the hardware clock (RTC)\n\n"
1197 "Usage: hwclock [function] [options...]\n\n"
1198 "Functions:\n"
1199 " --help show this help\n"
1200 " --show read hardware clock and print result\n"
1201 " --set set the rtc to the time given with --date\n"
1202 " --hctosys set the system time from the hardware clock\n"
1203 " --systohc set the hardware clock to the current system time\n"
1204 " --adjust adjust the rtc to account for systematic drift since \n"
1205 " the clock was last set or adjusted\n"
1206 " --getepoch print out the kernel's hardware clock epoch value\n"
1207 " --setepoch set the kernel's hardware clock epoch value to the \n"
1208 " value given with --epoch\n"
1209 " --version print out the version of hwclock to stdout\n"
1210 "\nOptions: \n"
1211 " --utc the hardware clock is kept in coordinated universal time\n"
1212 " --localtime the hardware clock is kept in local time\n"
66ee8158 1213 " --directisa access the ISA bus directly instead of %s\n"
eb63b9b8
KZ
1214 " --badyear ignore rtc's year because the bios is broken\n"
1215 " --date specifies the time to which to set the hardware clock\n"
1216 " --epoch=year specifies the year which is the beginning of the \n"
1217 " hardware clock's epoch value\n"
364cda48
KZ
1218 " --noadjfile do not access /etc/adjtime. Requires the use of\n"
1219 " either --utc or --localtime\n"
66ee8158 1220 ),RTC_DEV);
eb63b9b8 1221#ifdef __alpha__
63cccae4 1222 fprintf(usageto, _(
eb63b9b8
KZ
1223 " --jensen, --arc, --srm, --funky-toy\n"
1224 " tell hwclock the type of alpha you have (see hwclock(8))\n"
1225 ) );
1226#endif
1227
1228
1229 fflush(stdout);
63cccae4 1230 if (fmt) {
eb63b9b8
KZ
1231 usageto = stderr;
1232 va_start(ap, fmt);
1233 vfprintf(stderr, fmt, ap);
1234 va_end(ap);
1235 }
1236
63cccae4 1237 exit(fmt ? EX_USAGE : 0);
eb63b9b8
KZ
1238}
1239
63cccae4
KZ
1240static const struct option longopts[] = {
1241 { "adjust", 0, 0, 'a' },
1242 { "help", 0, 0, 'h' },
1243 { "show", 0, 0, 'r' },
1244 { "hctosys", 0, 0, 's' },
1245 { "utc", 0, 0, 'u' },
1246 { "version", 0, 0, 'v' },
1247 { "systohc", 0, 0, 'w' },
1248 { "debug", 0, 0, 'D' },
1249#ifdef __alpha__
1250 { "ARC", 0, 0, 'A' },
1251 { "arc", 0, 0, 'A' },
1252 { "Jensen", 0, 0, 'J' },
1253 { "jensen", 0, 0, 'J' },
1254 { "SRM", 0, 0, 'S' },
1255 { "srm", 0, 0, 'S' },
f0c8eda1 1256 { "funky-toy", 0, 0, 'F'},
63cccae4
KZ
1257#endif
1258 { "set", 0, 0, 128 },
1259 { "getepoch", 0, 0, 129 },
1260 { "setepoch", 0, 0, 130 },
1261 { "noadjfile", 0, 0, 131 },
1262 { "localtime", 0, 0, 132 },
1263 { "badyear", 0, 0, 133 },
1264 { "directisa", 0, 0, 134 },
1265 { "test", 0, 0, 135 },
1266 { "date", 1, 0, 136 },
1267 { "epoch", 1, 0, 137 },
1268 { NULL, 0, 0, 0 }
1269};
1270
1271/*
1272 * Returns:
1273 * EX_USAGE: bad invocation
1274 * EX_NOPERM: no permission
1275 * EX_OSFILE: cannot open /dev/rtc or /etc/adjtime
1276 * EX_IOERR: ioctl error getting or setting the time
1277 * 0: OK (or not)
1278 * 1: failure
1279 */
7eda085c 1280int
66ee8158 1281main(int argc, char **argv) {
7eda085c 1282
63cccae4
KZ
1283 struct timeval startup_time;
1284 /* The time we started up, in seconds into the epoch, including
1285 fractions. */
1286 time_t set_time; /* Time to which user said to set Hardware Clock */
7eda085c 1287
63cccae4
KZ
1288 bool permitted; /* User is permitted to do the function */
1289 int rc, c;
7eda085c 1290
63cccae4
KZ
1291 /* Variables set by various options; show may also be set later */
1292 /* The options debug, badyear and epoch_option are global */
1293 bool show, set, systohc, hctosys, adjust, getepoch, setepoch;
1294 bool utc, testing, local_opt, noadjfile, directisa;
1295 bool ARCconsole, Jensen, SRM, funky_toy;
1296 char *date_opt;
7eda085c 1297
63cccae4
KZ
1298 /* Remember what time we were invoked */
1299 gettimeofday(&startup_time, NULL);
7eda085c 1300
63cccae4 1301 setlocale(LC_ALL, "");
66ee8158 1302#ifdef LC_NUMERIC
63cccae4
KZ
1303 /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
1304 LC_NUMERIC since it gives problems when we write to /etc/adjtime.
1305 - gqueri@mail.dotcom.fr */
1306 setlocale(LC_NUMERIC, "C");
66ee8158 1307#endif
63cccae4
KZ
1308 bindtextdomain(PACKAGE, LOCALEDIR);
1309 textdomain(PACKAGE);
1310
1311 /* Set option defaults */
1312 show = set = systohc = hctosys = adjust = noadjfile = FALSE;
1313 getepoch = setepoch = utc = local_opt = testing = debug = FALSE;
1314 ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
1315 date_opt = NULL;
1316
1317 while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSF", longopts, NULL))
1318 != -1) {
1319 switch (c) {
1320 case 'D':
1321 debug = TRUE;
1322 break;
1323 case 'a':
1324 adjust = TRUE;
1325 break;
1326 case 'r':
1327 show = TRUE;
1328 break;
1329 case 's':
1330 hctosys = TRUE;
1331 break;
1332 case 'u':
1333 utc = TRUE;
1334 break;
1335 case 'w':
1336 systohc = TRUE;
1337 break;
1338#ifdef __alpha__
1339 case 'A':
1340 ARCconsole = TRUE;
1341 break;
1342 case 'J':
1343 Jensen = TRUE;
1344 break;
1345 case 'S':
1346 SRM = TRUE;
1347 break;
1348 case 'F':
1349 funky_toy = TRUE;
1350 break;
1351#endif
1352 case 128:
1353 set = TRUE;
1354 break;
1355 case 129:
1356 getepoch = TRUE;
1357 break;
1358 case 130:
1359 setepoch = TRUE;
1360 break;
1361 case 131:
1362 noadjfile = TRUE;
1363 break;
1364 case 132:
1365 local_opt = TRUE; /* --localtime */
1366 break;
1367 case 133:
1368 badyear = TRUE;
1369 break;
1370 case 134:
1371 directisa = TRUE;
1372 break;
1373 case 135:
1374 testing = TRUE; /* --test */
1375 break;
1376 case 136:
1377 date_opt = optarg; /* --date */
1378 break;
1379 case 137:
1380 epoch_option = atoi(optarg); /* --epoch */
1381 break;
1382 case 'v': /* --version */
1383 case 'V':
1384 out_version();
1385 return 0;
1386 case 'h': /* --help */
1387 case '?':
1388 default:
1389 usage(NULL);
1390 }
1391 }
7eda085c 1392
63cccae4
KZ
1393 argc -= optind;
1394 argv += optind;
eb63b9b8 1395
63cccae4
KZ
1396 if (argc > 0) {
1397 usage(_("%s takes no non-option arguments. "
1398 "You supplied %d.\n"),
1399 MYNAME, argc);
1400 }
7eda085c 1401
63cccae4
KZ
1402 if (show + set + systohc + hctosys + adjust + getepoch + setepoch > 1){
1403 fprintf(stderr, _("You have specified multiple functions.\n"
1404 "You can only perform one function "
1405 "at a time.\n"));
1406 exit(EX_USAGE);
1407 }
eb63b9b8 1408
63cccae4
KZ
1409 if (utc && local_opt) {
1410 fprintf(stderr, _("%s: The --utc and --localtime options "
1411 "are mutually exclusive. You specified "
1412 "both.\n"), MYNAME);
1413 exit(EX_USAGE);
1414 }
364cda48 1415
63cccae4
KZ
1416 if (adjust && noadjfile) {
1417 fprintf(stderr, _("%s: The --adjust and --noadjfile options "
1418 "are mutually exclusive. You specified "
1419 "both.\n"), MYNAME);
1420 exit(EX_USAGE);
1421 }
1422
1423 if (noadjfile && !(utc || local_opt)) {
1424 fprintf(stderr, _("%s: With --noadjfile, you must specify "
1425 "either --utc or --localtime\n"), MYNAME);
1426 exit(EX_USAGE);
1427 }
364cda48 1428
7eda085c 1429#ifdef __alpha__
63cccae4
KZ
1430 set_cmos_epoch(ARCconsole, SRM);
1431 set_cmos_access(Jensen, funky_toy);
7eda085c
KZ
1432#endif
1433
63cccae4
KZ
1434 if (set) {
1435 rc = interpret_date_string(date_opt, &set_time);
1436 /* (time-consuming) */
1437 if (rc != 0) {
1438 fprintf(stderr, _("No usable set-to time. "
1439 "Cannot set clock.\n"));
1440 exit(EX_USAGE);
1441 }
1442 }
7eda085c 1443
63cccae4
KZ
1444 if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch))
1445 show = 1; /* default to show */
7eda085c
KZ
1446
1447
63cccae4
KZ
1448 if (getuid() == 0)
1449 permitted = TRUE;
1450 else {
1451 /* program is designed to run setuid (in some situations) */
1452 if (set || hctosys || systohc || adjust) {
1453 fprintf(stderr,
1454 _("Sorry, only the superuser can change "
1455 "the Hardware Clock.\n"));
1456 permitted = FALSE;
1457 } else if (hctosys) {
1458 fprintf(stderr,
1459 _("Sorry, only the superuser can change "
1460 "the System Clock.\n"));
1461 permitted = FALSE;
1462 } else if (setepoch) {
1463 fprintf(stderr,
1464 _("Sorry, only the superuser can change the "
1465 "Hardware Clock epoch in the kernel.\n"));
1466 permitted = FALSE;
1467 } else
1468 permitted = TRUE;
1469 }
7eda085c 1470
63cccae4
KZ
1471 if (!permitted)
1472 exit(EX_NOPERM);
1473
1474 if (getepoch || setepoch) {
1475 manipulate_epoch(getepoch, setepoch, epoch_option, testing);
1476 return 0;
1477 }
1478
1479 if (debug)
1480 out_version();
1481 determine_clock_access_method(directisa);
1482 if (!ur) {
22853e4a 1483 fprintf(stderr,
63cccae4
KZ
1484 _("Cannot access the Hardware Clock via "
1485 "any known method.\n"));
1486 if (!debug)
1487 fprintf(stderr,
1488 _("Use the --debug option to see the details "
1489 "of our search for an access method.\n"));
1490 exit(1);
1491 }
1492
1493 return manipulate_clock(show, adjust, noadjfile, set, set_time,
1494 hctosys, systohc, startup_time, utc,
1495 local_opt, testing);
7eda085c
KZ
1496}
1497
1498/* A single routine for greater uniformity */
1499void
66ee8158
KZ
1500outsyserr(char *msg, ...) {
1501 va_list args;
1502 int errsv = errno;
1503
1504 fprintf(stderr, "%s: ", progname);
1505 va_start(args, msg);
1506 vfprintf(stderr, msg, args);
1507 va_end(args);
1508 fprintf(stderr, ", errno=%d: %s.\n",
1509 errsv, strerror(errsv));
7eda085c
KZ
1510}
1511
1512/****************************************************************************
1513
1514 History of this program:
1515
1516 98.08.12 BJH Version 2.4
1517
1518 Don't use century byte from Hardware Clock. Add comments telling why.
1519
1520
1521 98.06.20 BJH Version 2.3.
1522
1523 Make --hctosys set the kernel timezone from TZ environment variable
1524 and/or /usr/lib/zoneinfo. From Klaus Ripke (klaus@ripke.com).
1525
1526 98.03.05 BJH. Version 2.2.
1527
1528 Add --getepoch and --setepoch.
1529
1530 Fix some word length things so it works on Alpha.
1531
1532 Make it work when /dev/rtc doesn't have the interrupt functions.
1533 In this case, busywait for the top of a second instead of blocking and
1534 waiting for the update complete interrupt.
1535
1536 Fix a bunch of bugs too numerous to mention.
1537
1538 97.06.01: BJH. Version 2.1. Read and write the century byte (Byte
1539 50) of the ISA Hardware Clock when using direct ISA I/O. Problem
1540 discovered by job (jei@iclnl.icl.nl).
1541
1542 Use the rtc clock access method in preference to the KDGHWCLK method.
1543 Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
1544
1545 November 1996: Version 2.0.1. Modifications by Nicolai Langfeldt
1546 (janl@math.uio.no) to make it compile on linux 1.2 machines as well
1547 as more recent versions of the kernel. Introduced the NO_CLOCK
1548 access method and wrote feature test code to detect absense of rtc
1549 headers.
1550
1551
1552**************************************************************************
1553 Maintenance notes
1554
1555 To compile this, you must use GNU compiler optimization (-O option)
1556 in order to make the "extern inline" functions from asm/io.h (inb(),
1557 etc.) compile. If you don't optimize, which means the compiler
1558 will generate no inline functions, the references to these functions
1559 in this program will be compiled as external references. Since you
1560 probably won't be linking with any functions by these names, you will
1561 have unresolved external references when you link.
1562
1563 The program is designed to run setuid superuser, since we need to be
1564 able to do direct I/O. (More to the point: we need permission to
1565 execute the iopl() system call). (However, if you use one of the
1566 methods other than direct ISA I/O to access the clock, no setuid is
1567 required).
1568
1569 Here's some info on how we must deal with the time that elapses while
1570 this program runs: There are two major delays as we run:
1571
1572 1) Waiting up to 1 second for a transition of the Hardware Clock so
1573 we are synchronized to the Hardware Clock.
1574
1575 2) Running the "date" program to interpret the value of our --date
1576 option.
1577
1578 Reading the /etc/adjtime file is the next biggest source of delay and
1579 uncertainty.
1580
1581 The user wants to know what time it was at the moment he invoked us,
1582 not some arbitrary time later. And in setting the clock, he is
1583 giving us the time at the moment we are invoked, so if we set the
1584 clock some time later, we have to add some time to that.
1585
1586 So we check the system time as soon as we start up, then run "date"
1587 and do file I/O if necessary, then wait to synchronize with a
1588 Hardware Clock edge, then check the system time again to see how
1589 much time we spent. We immediately read the clock then and (if
1590 appropriate) report that time, and additionally, the delay we measured.
1591
1592 If we're setting the clock to a time given by the user, we wait some
1593 more so that the total delay is an integral number of seconds, then
1594 set the Hardware Clock to the time the user requested plus that
1595 integral number of seconds. N.B. The Hardware Clock can only be set
1596 in integral seconds.
1597
1598 If we're setting the clock to the system clock value, we wait for
1599 the system clock to reach the top of a second, and then set the
1600 Hardware Clock to the system clock's value.
1601
1602 Here's an interesting point about setting the Hardware Clock: On my
1603 machine, when you set it, it sets to that precise time. But one can
1604 imagine another clock whose update oscillator marches on a steady one
1605 second period, so updating the clock between any two oscillator ticks
1606 is the same as updating it right at the earlier tick. To avoid any
1607 complications that might cause, we set the clock as soon as possible
1608 after an oscillator tick.
1609
1610
1611 About synchronizing to the Hardware Clock when reading the time: The
1612 precision of the Hardware Clock counters themselves is one second.
1613 You can't read the counters and find out that is 12:01:02.5. But if
1614 you consider the location in time of the counter's ticks as part of
1615 its value, then its precision is as infinite as time is continuous!
1616 What I'm saying is this: To find out the _exact_ time in the
1617 hardware clock, we wait until the next clock tick (the next time the
1618 second counter changes) and measure how long we had to wait. We
1619 then read the value of the clock counters and subtract the wait time
1620 and we know precisely what time it was when we set out to query the
1621 time.
1622
1623 hwclock uses this method, and considers the Hardware Clock to have
1624 infinite precision.
1625
1626
1627 Enhancements needed:
1628
1629 - When waiting for whole second boundary in set_hardware_clock_exact,
1630 fail if we miss the goal by more than .1 second, as could happen if
1631 we get pre-empted (by the kernel dispatcher).
1632
1633****************************************************************************/
1634