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