~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to hwclock/hwclock.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

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