date.c revision 1.70 1 1.70 kre /* $NetBSD: date.c,v 1.70 2024/09/17 15:25:39 kre Exp $ */
2 1.9 cgd
3 1.1 cgd /*
4 1.8 mycroft * Copyright (c) 1985, 1987, 1988, 1993
5 1.8 mycroft * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * Redistribution and use in source and binary forms, with or without
8 1.1 cgd * modification, are permitted provided that the following conditions
9 1.1 cgd * are met:
10 1.1 cgd * 1. Redistributions of source code must retain the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer.
12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 cgd * notice, this list of conditions and the following disclaimer in the
14 1.1 cgd * documentation and/or other materials provided with the distribution.
15 1.37 agc * 3. Neither the name of the University nor the names of its contributors
16 1.1 cgd * may be used to endorse or promote products derived from this software
17 1.1 cgd * without specific prior written permission.
18 1.1 cgd *
19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 cgd * SUCH DAMAGE.
30 1.1 cgd */
31 1.1 cgd
32 1.62 christos #if HAVE_NBTOOL_CONFIG_H
33 1.62 christos #include "nbtool_config.h"
34 1.62 christos #endif
35 1.62 christos
36 1.15 thorpej #include <sys/cdefs.h>
37 1.1 cgd #ifndef lint
38 1.15 thorpej __COPYRIGHT(
39 1.52 lukem "@(#) Copyright (c) 1985, 1987, 1988, 1993\
40 1.52 lukem The Regents of the University of California. All rights reserved.");
41 1.1 cgd #endif /* not lint */
42 1.1 cgd
43 1.1 cgd #ifndef lint
44 1.10 cgd #if 0
45 1.11 jtc static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
46 1.10 cgd #else
47 1.70 kre __RCSID("$NetBSD: date.c,v 1.70 2024/09/17 15:25:39 kre Exp $");
48 1.10 cgd #endif
49 1.1 cgd #endif /* not lint */
50 1.1 cgd
51 1.1 cgd #include <sys/param.h>
52 1.1 cgd #include <sys/time.h>
53 1.8 mycroft
54 1.8 mycroft #include <ctype.h>
55 1.8 mycroft #include <err.h>
56 1.8 mycroft #include <fcntl.h>
57 1.59 christos #include <errno.h>
58 1.34 wiz #include <locale.h>
59 1.1 cgd #include <stdio.h>
60 1.1 cgd #include <stdlib.h>
61 1.1 cgd #include <string.h>
62 1.8 mycroft #include <syslog.h>
63 1.22 kleink #include <time.h>
64 1.18 mycroft #include <tzfile.h>
65 1.8 mycroft #include <unistd.h>
66 1.14 cgd #include <util.h>
67 1.63 christos #if !HAVE_NBTOOL_CONFIG_H
68 1.63 christos #include <utmpx.h>
69 1.63 christos #endif
70 1.8 mycroft
71 1.8 mycroft #include "extern.h"
72 1.1 cgd
73 1.38 dsl static time_t tval;
74 1.64 kim static int Rflag, aflag, jflag, rflag, nflag;
75 1.1 cgd
76 1.61 dholland __dead static void badcanotime(const char *, const char *, size_t);
77 1.34 wiz static void setthetime(const char *);
78 1.60 joerg __dead static void usage(void);
79 1.8 mycroft
80 1.68 kre #if HAVE_NBTOOL_CONFIG_H
81 1.68 kre static int parse_iso_datetime(time_t *, const char *);
82 1.68 kre #else
83 1.68 kre static char *fmt;
84 1.68 kre #endif
85 1.68 kre
86 1.67 kre #if !defined(isleap)
87 1.67 kre # define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
88 1.67 kre #endif
89 1.67 kre
90 1.8 mycroft int
91 1.34 wiz main(int argc, char *argv[])
92 1.1 cgd {
93 1.43 christos char *buf;
94 1.43 christos size_t bufsiz;
95 1.40 christos const char *format;
96 1.38 dsl int ch;
97 1.59 christos long long val;
98 1.59 christos struct tm *tm;
99 1.69 kre char *default_tz;
100 1.1 cgd
101 1.35 wiz setprogname(argv[0]);
102 1.16 cgd (void)setlocale(LC_ALL, "");
103 1.7 jtc
104 1.69 kre default_tz = getenv("TZ");
105 1.69 kre
106 1.69 kre while ((ch = getopt(argc, argv, "ad:f:jnRr:Uuz:")) != -1) {
107 1.42 peter switch (ch) {
108 1.38 dsl case 'a': /* adjust time slowly */
109 1.38 dsl aflag = 1;
110 1.38 dsl nflag = 1;
111 1.38 dsl break;
112 1.47 christos case 'd':
113 1.66 christos rflag = 1;
114 1.68 kre #ifdef HAVE_NBTOOL_CONFIG_H
115 1.68 kre if (parse_iso_datetime(&tval, optarg))
116 1.68 kre break;
117 1.68 kre errx(EXIT_FAILURE,
118 1.68 kre "-d only supports ISO format in the tool version");
119 1.68 kre break;
120 1.68 kre #else
121 1.68 kre errno = 0;
122 1.49 christos tval = parsedate(optarg, NULL, NULL);
123 1.68 kre if (tval == -1 && errno != 0) {
124 1.61 dholland errx(EXIT_FAILURE,
125 1.61 dholland "%s: Unrecognized date format", optarg);
126 1.61 dholland }
127 1.47 christos break;
128 1.63 christos case 'f':
129 1.63 christos fmt = optarg;
130 1.63 christos break;
131 1.68 kre #endif
132 1.46 jdarrow case 'j': /* don't set time */
133 1.46 jdarrow jflag = 1;
134 1.46 jdarrow break;
135 1.1 cgd case 'n': /* don't set network */
136 1.1 cgd nflag = 1;
137 1.1 cgd break;
138 1.64 kim case 'R': /* RFC-5322 email format */
139 1.64 kim Rflag = 1;
140 1.64 kim break;
141 1.1 cgd case 'r': /* user specified seconds */
142 1.61 dholland if (optarg[0] == '\0') {
143 1.61 dholland errx(EXIT_FAILURE, "<empty>: Invalid number");
144 1.61 dholland }
145 1.59 christos errno = 0;
146 1.59 christos val = strtoll(optarg, &buf, 0);
147 1.61 dholland if (errno) {
148 1.61 dholland err(EXIT_FAILURE, "%s", optarg);
149 1.61 dholland }
150 1.61 dholland if (optarg[0] == '\0' || *buf != '\0') {
151 1.61 dholland errx(EXIT_FAILURE,
152 1.61 dholland "%s: Invalid number", optarg);
153 1.61 dholland }
154 1.1 cgd rflag = 1;
155 1.59 christos tval = (time_t)val;
156 1.1 cgd break;
157 1.69 kre case 'U': /* reset to default timezone */
158 1.69 kre if (default_tz)
159 1.69 kre (void)setenv("TZ", default_tz, 1);
160 1.69 kre else
161 1.69 kre (void)unsetenv("TZ");
162 1.69 kre break;
163 1.27 mycroft case 'u': /* do everything in UTC */
164 1.55 gson (void)setenv("TZ", "UTC0", 1);
165 1.1 cgd break;
166 1.69 kre case 'z':
167 1.69 kre if (optarg[0] == '\0')
168 1.69 kre (void)unsetenv("TZ");
169 1.69 kre else
170 1.69 kre (void)setenv("TZ", optarg, 1);
171 1.69 kre break;
172 1.1 cgd default:
173 1.1 cgd usage();
174 1.1 cgd }
175 1.38 dsl }
176 1.1 cgd argc -= optind;
177 1.1 cgd argv += optind;
178 1.1 cgd
179 1.8 mycroft if (!rflag && time(&tval) == -1)
180 1.42 peter err(EXIT_FAILURE, "time");
181 1.1 cgd
182 1.1 cgd
183 1.1 cgd /* allow the operands in any order */
184 1.1 cgd if (*argv && **argv == '+') {
185 1.53 dholland format = *argv;
186 1.1 cgd ++argv;
187 1.64 kim } else if (Rflag) {
188 1.64 kim (void)setlocale(LC_TIME, "C");
189 1.64 kim format = "+%a, %-e %b %Y %H:%M:%S %z";
190 1.59 christos } else
191 1.59 christos format = "+%a %b %e %H:%M:%S %Z %Y";
192 1.1 cgd
193 1.1 cgd if (*argv) {
194 1.1 cgd setthetime(*argv);
195 1.1 cgd ++argv;
196 1.68 kre #ifndef HAVE_NBTOOL_CONFIG_H
197 1.68 kre } else if (fmt) {
198 1.63 christos usage();
199 1.68 kre #endif
200 1.68 kre }
201 1.1 cgd
202 1.1 cgd if (*argv && **argv == '+')
203 1.53 dholland format = *argv;
204 1.1 cgd
205 1.43 christos if ((buf = malloc(bufsiz = 1024)) == NULL)
206 1.43 christos goto bad;
207 1.59 christos
208 1.59 christos if ((tm = localtime(&tval)) == NULL)
209 1.61 dholland err(EXIT_FAILURE, "%lld: localtime", (long long)tval);
210 1.59 christos
211 1.59 christos while (strftime(buf, bufsiz, format, tm) == 0)
212 1.43 christos if ((buf = realloc(buf, bufsiz <<= 1)) == NULL)
213 1.43 christos goto bad;
214 1.59 christos
215 1.59 christos (void)printf("%s\n", buf + 1);
216 1.43 christos free(buf);
217 1.43 christos return 0;
218 1.43 christos bad:
219 1.59 christos err(EXIT_FAILURE, "Cannot allocate format buffer");
220 1.1 cgd }
221 1.1 cgd
222 1.34 wiz static void
223 1.61 dholland badcanotime(const char *msg, const char *val, size_t where)
224 1.34 wiz {
225 1.61 dholland warnx("%s in canonical time", msg);
226 1.61 dholland warnx("%s", val);
227 1.61 dholland warnx("%*s", (int)where + 1, "^");
228 1.45 elad usage();
229 1.45 elad }
230 1.45 elad
231 1.34 wiz #define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
232 1.21 mycroft
233 1.68 kre #if HAVE_NBTOOL_CONFIG_H
234 1.68 kre
235 1.68 kre inline static int
236 1.68 kre digitstring(const char *s, int len)
237 1.68 kre {
238 1.68 kre while (--len > 0) {
239 1.68 kre if (!isdigit(*(unsigned char *)s))
240 1.68 kre return 0;
241 1.68 kre s++;
242 1.68 kre }
243 1.68 kre return 1;
244 1.68 kre }
245 1.68 kre
246 1.68 kre static int
247 1.68 kre parse_iso_datetime(time_t * res, const char * string)
248 1.68 kre {
249 1.68 kre struct tm tm;
250 1.68 kre time_t t;
251 1.68 kre
252 1.68 kre memset(&tm, 0, sizeof tm);
253 1.68 kre
254 1.68 kre if (!digitstring(string, 4))
255 1.68 kre return 0;
256 1.68 kre tm.tm_year = ATOI2(string) * 100;
257 1.68 kre tm.tm_year += ATOI2(string);
258 1.68 kre tm.tm_year -= 1900;
259 1.68 kre
260 1.68 kre if (*string == '-')
261 1.68 kre string++;
262 1.68 kre
263 1.68 kre if (!digitstring(string, 2))
264 1.68 kre return 0;
265 1.68 kre
266 1.68 kre tm.tm_mon = ATOI2(string);
267 1.68 kre if (tm.tm_mon < 1 || tm.tm_mon > 12)
268 1.68 kre return 0;
269 1.68 kre tm.tm_mon--;
270 1.68 kre
271 1.68 kre if (*string == '-')
272 1.68 kre string++;
273 1.68 kre
274 1.68 kre if (!digitstring(string, 2))
275 1.68 kre return 0;
276 1.68 kre
277 1.68 kre tm.tm_mday = ATOI2(string);
278 1.68 kre if (tm.tm_mday < 1)
279 1.68 kre return 0;
280 1.68 kre switch (tm.tm_mon) {
281 1.68 kre case 0: case 2: case 4: case 6: case 7: case 9: case 11:
282 1.68 kre if (tm.tm_mday > 31)
283 1.68 kre return 0;
284 1.68 kre break;
285 1.68 kre case 3: case 5: case 8: case 10:
286 1.68 kre if (tm.tm_mday > 30)
287 1.68 kre return 0;
288 1.68 kre break;
289 1.68 kre case 1:
290 1.68 kre if (tm.tm_mday > 28 + isleap(tm.tm_year + 1900))
291 1.68 kre return 0;
292 1.68 kre break;
293 1.68 kre default:
294 1.68 kre abort();
295 1.68 kre }
296 1.68 kre
297 1.68 kre do {
298 1.68 kre if (*string == '\0')
299 1.68 kre break;
300 1.68 kre if (*string == 'T' || *string == 't' || *string == ' ' ||
301 1.68 kre *string == '-')
302 1.68 kre string++;
303 1.68 kre
304 1.68 kre if (!digitstring(string, 2))
305 1.68 kre return 0;
306 1.68 kre tm.tm_hour = ATOI2(string);
307 1.68 kre if (tm.tm_hour > 23)
308 1.68 kre return 0;
309 1.68 kre
310 1.68 kre if (*string == '\0')
311 1.68 kre break;
312 1.68 kre if (*string == ':')
313 1.68 kre string++;
314 1.68 kre
315 1.68 kre if (!digitstring(string, 2))
316 1.68 kre return 0;
317 1.68 kre tm.tm_min = ATOI2(string);
318 1.68 kre if (tm.tm_min >= 60)
319 1.68 kre return 0;
320 1.68 kre
321 1.68 kre if (*string == '\0')
322 1.68 kre break;
323 1.68 kre if (*string == ':')
324 1.68 kre string++;
325 1.68 kre
326 1.68 kre if (!digitstring(string, 2))
327 1.68 kre return 0;
328 1.68 kre tm.tm_sec = ATOI2(string);
329 1.68 kre if (tm.tm_sec >= 60)
330 1.68 kre return 0;
331 1.68 kre } while (0);
332 1.68 kre
333 1.68 kre if (*string != '\0')
334 1.68 kre return 0;
335 1.68 kre
336 1.68 kre tm.tm_isdst = -1;
337 1.68 kre tm.tm_wday = -1;
338 1.68 kre
339 1.68 kre t = mktime(&tm);
340 1.68 kre if (tm.tm_wday == -1)
341 1.68 kre return 0;
342 1.68 kre
343 1.68 kre *res = t;
344 1.68 kre return 1;
345 1.68 kre }
346 1.68 kre
347 1.68 kre #endif /*NBTOOL*/
348 1.68 kre
349 1.33 gmcgarry static void
350 1.34 wiz setthetime(const char *p)
351 1.1 cgd {
352 1.34 wiz struct timeval tv;
353 1.38 dsl time_t new_time;
354 1.12 tls struct tm *lt;
355 1.61 dholland const char *dot, *t, *op;
356 1.50 cbiere size_t len;
357 1.50 cbiere int yearset;
358 1.1 cgd
359 1.63 christos if ((lt = localtime(&tval)) == NULL)
360 1.63 christos err(EXIT_FAILURE, "%lld: localtime", (long long)tval);
361 1.63 christos
362 1.63 christos lt->tm_isdst = -1; /* Divine correct DST */
363 1.63 christos
364 1.68 kre #ifndef HAVE_NBTOOL_CONFIG_H
365 1.63 christos if (fmt) {
366 1.63 christos t = strptime(p, fmt, lt);
367 1.63 christos if (t == NULL) {
368 1.63 christos warnx("Failed conversion of ``%s''"
369 1.63 christos " using format ``%s''\n", p, fmt);
370 1.63 christos } else if (*t != '\0')
371 1.63 christos warnx("Ignoring %zu extraneous"
372 1.63 christos " characters in date string (%s)",
373 1.63 christos strlen(t), t);
374 1.63 christos goto setit;
375 1.63 christos }
376 1.70 kre if (getenv("POSIXLY_CORRECT") != NULL) {
377 1.70 kre int yrdigs;
378 1.70 kre const char * const e = "Bad POSIX format date ``%s''";
379 1.70 kre
380 1.70 kre t = strptime(p, "%m%d%H%M", lt);
381 1.70 kre if (t == NULL)
382 1.70 kre errx(EXIT_FAILURE, e, p);
383 1.70 kre if (*t != '\0') {
384 1.70 kre yrdigs = strspn(t, "0123456789");
385 1.70 kre if (yrdigs != 2 && yrdigs != 4)
386 1.70 kre errx(EXIT_FAILURE, e, p);
387 1.70 kre t = strptime(t, yrdigs == 2 ? "%y" : "%Y", lt);
388 1.70 kre if (t == NULL || *t != '\0')
389 1.70 kre errx(EXIT_FAILURE, e, p);
390 1.70 kre }
391 1.70 kre goto setit;
392 1.70 kre }
393 1.68 kre #endif
394 1.8 mycroft for (t = p, dot = NULL; *t; ++t) {
395 1.61 dholland if (*t == '.') {
396 1.61 dholland if (dot == NULL) {
397 1.61 dholland dot = t;
398 1.61 dholland } else {
399 1.61 dholland badcanotime("Unexpected dot", p, t - p);
400 1.61 dholland }
401 1.61 dholland } else if (!isdigit((unsigned char)*t)) {
402 1.61 dholland badcanotime("Expected digit", p, t - p);
403 1.8 mycroft }
404 1.8 mycroft }
405 1.1 cgd
406 1.1 cgd
407 1.8 mycroft if (dot != NULL) { /* .ss */
408 1.23 mycroft len = strlen(dot);
409 1.61 dholland if (len > 3) {
410 1.61 dholland badcanotime("Unexpected digit after seconds field",
411 1.61 dholland p, strlen(p) - 1);
412 1.61 dholland } else if (len < 3) {
413 1.61 dholland badcanotime("Expected digit in seconds field",
414 1.61 dholland p, strlen(p));
415 1.61 dholland }
416 1.23 mycroft ++dot;
417 1.8 mycroft lt->tm_sec = ATOI2(dot);
418 1.45 elad if (lt->tm_sec > 61)
419 1.61 dholland badcanotime("Seconds out of range", p, strlen(p) - 1);
420 1.23 mycroft } else {
421 1.23 mycroft len = 0;
422 1.1 cgd lt->tm_sec = 0;
423 1.23 mycroft }
424 1.1 cgd
425 1.61 dholland op = p;
426 1.18 mycroft yearset = 0;
427 1.23 mycroft switch (strlen(p) - len) {
428 1.21 mycroft case 12: /* cc */
429 1.21 mycroft lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
430 1.45 elad if (lt->tm_year < 0)
431 1.61 dholland badcanotime("Year before 1900", op, p - op + 1);
432 1.18 mycroft yearset = 1;
433 1.18 mycroft /* FALLTHROUGH */
434 1.1 cgd case 10: /* yy */
435 1.18 mycroft if (yearset) {
436 1.21 mycroft lt->tm_year += ATOI2(p);
437 1.18 mycroft } else {
438 1.18 mycroft yearset = ATOI2(p);
439 1.21 mycroft if (yearset < 69)
440 1.21 mycroft lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
441 1.18 mycroft else
442 1.21 mycroft lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
443 1.18 mycroft }
444 1.1 cgd /* FALLTHROUGH */
445 1.1 cgd case 8: /* mm */
446 1.1 cgd lt->tm_mon = ATOI2(p);
447 1.45 elad if (lt->tm_mon > 12 || lt->tm_mon == 0)
448 1.61 dholland badcanotime("Month out of range", op, p - op - 1);
449 1.1 cgd --lt->tm_mon; /* time struct is 0 - 11 */
450 1.1 cgd /* FALLTHROUGH */
451 1.1 cgd case 6: /* dd */
452 1.1 cgd lt->tm_mday = ATOI2(p);
453 1.45 elad switch (lt->tm_mon) {
454 1.45 elad case 0:
455 1.45 elad case 2:
456 1.45 elad case 4:
457 1.45 elad case 6:
458 1.45 elad case 7:
459 1.45 elad case 9:
460 1.45 elad case 11:
461 1.45 elad if (lt->tm_mday > 31 || lt->tm_mday == 0)
462 1.61 dholland badcanotime("Day out of range (max 31)",
463 1.61 dholland op, p - op - 1);
464 1.45 elad break;
465 1.45 elad case 3:
466 1.45 elad case 5:
467 1.45 elad case 8:
468 1.45 elad case 10:
469 1.45 elad if (lt->tm_mday > 30 || lt->tm_mday == 0)
470 1.61 dholland badcanotime("Day out of range (max 30)",
471 1.61 dholland op, p - op - 1);
472 1.45 elad break;
473 1.45 elad case 1:
474 1.61 dholland if (isleap(lt->tm_year + TM_YEAR_BASE)) {
475 1.61 dholland if (lt->tm_mday > 29 || lt->tm_mday == 0) {
476 1.61 dholland badcanotime("Day out of range "
477 1.61 dholland "(max 29)",
478 1.61 dholland op, p - op - 1);
479 1.61 dholland }
480 1.61 dholland } else {
481 1.61 dholland if (lt->tm_mday > 28 || lt->tm_mday == 0) {
482 1.61 dholland badcanotime("Day out of range "
483 1.61 dholland "(max 28)",
484 1.61 dholland op, p - op - 1);
485 1.61 dholland }
486 1.61 dholland }
487 1.45 elad break;
488 1.45 elad default:
489 1.61 dholland /*
490 1.61 dholland * If the month was given, it's already been
491 1.61 dholland * checked. If a bad value came back from
492 1.61 dholland * localtime, something's badly broken.
493 1.61 dholland * (make this an assertion?)
494 1.61 dholland */
495 1.61 dholland errx(EXIT_FAILURE, "localtime gave invalid month %d",
496 1.61 dholland lt->tm_mon);
497 1.45 elad }
498 1.1 cgd /* FALLTHROUGH */
499 1.1 cgd case 4: /* hh */
500 1.1 cgd lt->tm_hour = ATOI2(p);
501 1.45 elad if (lt->tm_hour > 23)
502 1.61 dholland badcanotime("Hour out of range", op, p - op - 1);
503 1.1 cgd /* FALLTHROUGH */
504 1.1 cgd case 2: /* mm */
505 1.1 cgd lt->tm_min = ATOI2(p);
506 1.45 elad if (lt->tm_min > 59)
507 1.61 dholland badcanotime("Minute out of range", op, p - op - 1);
508 1.1 cgd break;
509 1.38 dsl case 0: /* was just .sss */
510 1.38 dsl if (len != 0)
511 1.38 dsl break;
512 1.38 dsl /* FALLTHROUGH */
513 1.1 cgd default:
514 1.61 dholland if (strlen(p) - len > 12) {
515 1.61 dholland badcanotime("Too many digits", p, 12);
516 1.61 dholland } else {
517 1.61 dholland badcanotime("Not enough digits", p, strlen(p) - len);
518 1.61 dholland }
519 1.1 cgd }
520 1.63 christos setit:
521 1.27 mycroft /* convert broken-down time to UTC clock time */
522 1.61 dholland if ((new_time = mktime(lt)) == -1) {
523 1.61 dholland /* Can this actually happen? */
524 1.63 christos err(EXIT_FAILURE, "mktime");
525 1.61 dholland }
526 1.1 cgd
527 1.46 jdarrow /* if jflag is set, don't actually change the time, just return */
528 1.46 jdarrow if (jflag) {
529 1.46 jdarrow tval = new_time;
530 1.46 jdarrow return;
531 1.46 jdarrow }
532 1.46 jdarrow
533 1.1 cgd /* set the time */
534 1.62 christos #ifndef HAVE_NBTOOL_CONFIG_H
535 1.63 christos struct utmpx utx;
536 1.63 christos memset(&utx, 0, sizeof(utx));
537 1.63 christos utx.ut_type = OLD_TIME;
538 1.63 christos (void)gettimeofday(&utx.ut_tv, NULL);
539 1.63 christos pututxline(&utx);
540 1.63 christos
541 1.38 dsl if (nflag || netsettime(new_time)) {
542 1.1 cgd logwtmp("|", "date", "");
543 1.38 dsl if (aflag) {
544 1.38 dsl tv.tv_sec = new_time - tval;
545 1.38 dsl tv.tv_usec = 0;
546 1.41 hubertf if (adjtime(&tv, NULL))
547 1.44 jnemeth err(EXIT_FAILURE, "adjtime");
548 1.38 dsl } else {
549 1.39 dsl tval = new_time;
550 1.38 dsl tv.tv_sec = tval;
551 1.38 dsl tv.tv_usec = 0;
552 1.41 hubertf if (settimeofday(&tv, NULL))
553 1.44 jnemeth err(EXIT_FAILURE, "settimeofday");
554 1.1 cgd }
555 1.1 cgd logwtmp("{", "date", "");
556 1.1 cgd }
557 1.63 christos utx.ut_type = NEW_TIME;
558 1.63 christos (void)gettimeofday(&utx.ut_tv, NULL);
559 1.63 christos pututxline(&utx);
560 1.8 mycroft
561 1.8 mycroft if ((p = getlogin()) == NULL)
562 1.8 mycroft p = "???";
563 1.8 mycroft syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
564 1.63 christos #else
565 1.63 christos errx(EXIT_FAILURE, "Can't set the time in the tools version");
566 1.63 christos #endif
567 1.1 cgd }
568 1.1 cgd
569 1.8 mycroft static void
570 1.34 wiz usage(void)
571 1.1 cgd {
572 1.1 cgd (void)fprintf(stderr,
573 1.69 kre "Usage: %s [-ajnRUu] [-d date] [-r seconds] [-z zone] [+format]",
574 1.59 christos getprogname());
575 1.69 kre (void)fprintf(stderr, "\n\t%*s[[[[[[CC]yy]mm]dd]HH]MM[.SS]]\n",
576 1.69 kre (int)strlen(getprogname()), "");
577 1.63 christos (void)fprintf(stderr,
578 1.65 kim " %s [-ajnRu] -f input_format new_date [+format]\n",
579 1.63 christos getprogname());
580 1.41 hubertf exit(EXIT_FAILURE);
581 1.24 mycroft /* NOTREACHED */
582 1.1 cgd }
583