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