Print this page
6869 Update zdump to better-handle POSIX timezones
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/zdump/zdump.c
+++ new/usr/src/cmd/zdump/zdump.c
1 1 /*
2 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 -#pragma ident "%Z%%M% %I% %E% SMI"
7 -
8 6 /*
9 7 * zdump 7.24
10 8 * Taken from elsie.nci.nih.gov to replace the existing Solaris zdump,
11 9 * which was based on an earlier version of the elsie code.
12 10 *
13 11 * For zdump 7.24, the following changes were made to the elsie code:
14 12 * locale/textdomain/messages to match existing Solaris style.
15 13 * Solaris verbose mode is documented to display the current time first.
16 14 * cstyle cleaned code.
17 15 * removed old locale/textdomain code.
18 16 */
19 17
20 18 static char elsieid[] = "@(#)zdump.c 7.74";
21 19
22 20 /*
23 21 * This code has been made independent of the rest of the time
24 22 * conversion package to increase confidence in the verification it provides.
25 23 * You can use this code to help in verifying other implementations.
26 24 */
27 25
28 26 #include "stdio.h" /* for stdout, stderr, perror */
29 27 #include "string.h" /* for strcpy */
30 28 #include "sys/types.h" /* for time_t */
31 29 #include "time.h" /* for struct tm */
32 30 #include "stdlib.h" /* for exit, malloc, atoi */
33 31 #include "locale.h" /* for setlocale, textdomain */
34 32 #include "libintl.h"
35 33 #include <ctype.h>
36 34 #include "tzfile.h" /* for defines */
37 35 #include <limits.h>
38 36
39 37 #ifndef ZDUMP_LO_YEAR
40 38 #define ZDUMP_LO_YEAR (-500)
41 39 #endif /* !defined ZDUMP_LO_YEAR */
42 40
43 41 #ifndef ZDUMP_HI_YEAR
44 42 #define ZDUMP_HI_YEAR 2500
45 43 #endif /* !defined ZDUMP_HI_YEAR */
46 44
47 45 #ifndef MAX_STRING_LENGTH
48 46 #define MAX_STRING_LENGTH 1024
49 47 #endif /* !defined MAX_STRING_LENGTH */
50 48
51 49 #ifndef TRUE
52 50 #define TRUE 1
53 51 #endif /* !defined TRUE */
54 52
55 53 #ifndef FALSE
56 54 #define FALSE 0
57 55 #endif /* !defined FALSE */
58 56
59 57 #ifndef isleap_sum
60 58 /*
61 59 * See tzfile.h for details on isleap_sum.
62 60 */
63 61 #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
64 62 #endif /* !defined isleap_sum */
65 63
66 64 #ifndef SECSPERDAY
67 65 #define SECSPERDAY ((long)SECSPERHOUR * HOURSPERDAY)
68 66 #endif
69 67 #define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR)
70 68 #define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY)
71 69
72 70 #ifndef GNUC_or_lint
73 71 #ifdef lint
74 72 #define GNUC_or_lint
75 73 #else /* !defined lint */
76 74 #ifdef __GNUC__
77 75 #define GNUC_or_lint
78 76 #endif /* defined __GNUC__ */
79 77 #endif /* !defined lint */
80 78 #endif /* !defined GNUC_or_lint */
81 79
82 80 #ifndef INITIALIZE
83 81 #ifdef GNUC_or_lint
84 82 #define INITIALIZE(x) ((x) = 0)
85 83 #else /* !defined GNUC_or_lint */
86 84 #define INITIALIZE(x)
87 85 #endif /* !defined GNUC_or_lint */
88 86 #endif /* !defined INITIALIZE */
89 87
90 88 static time_t absolute_min_time;
91 89 static time_t absolute_max_time;
92 90 static size_t longest;
93 91 static char *progname;
94 92 static int warned;
95 93
96 94 static char *abbr(struct tm *);
97 95 static void abbrok(const char *, const char *);
98 96 static long delta(struct tm *, struct tm *);
99 97 static void dumptime(const struct tm *);
100 98 static time_t hunt(char *, time_t, time_t);
101 99 static void setabsolutes(void);
102 100 static void show(char *, time_t, int);
103 101 static void usage(void);
104 102 static const char *tformat(void);
105 103 static time_t yeartot(long y);
106 104
107 105 #ifndef TYPECHECK
108 106 #define my_localtime localtime
109 107 #else /* !defined TYPECHECK */
110 108 static struct tm *
111 109 my_localtime(tp)
112 110 time_t *tp;
113 111 {
114 112 register struct tm *tmp;
115 113
116 114 tmp = localtime(tp);
117 115 if (tp != NULL && tmp != NULL) {
118 116 struct tm tm;
119 117 register time_t t;
120 118
121 119 tm = *tmp;
122 120 t = mktime(&tm);
123 121 if (t - *tp >= 1 || *tp - t >= 1) {
124 122 (void) fflush(stdout);
125 123 (void) fprintf(stderr, "\n%s: ", progname);
126 124 (void) fprintf(stderr, tformat(), *tp);
127 125 (void) fprintf(stderr, " ->");
128 126 (void) fprintf(stderr, " year=%d", tmp->tm_year);
129 127 (void) fprintf(stderr, " mon=%d", tmp->tm_mon);
130 128 (void) fprintf(stderr, " mday=%d", tmp->tm_mday);
131 129 (void) fprintf(stderr, " hour=%d", tmp->tm_hour);
132 130 (void) fprintf(stderr, " min=%d", tmp->tm_min);
133 131 (void) fprintf(stderr, " sec=%d", tmp->tm_sec);
134 132 (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
|
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
135 133 (void) fprintf(stderr, " -> ");
136 134 (void) fprintf(stderr, tformat(), t);
137 135 (void) fprintf(stderr, "\n");
138 136 }
139 137 }
140 138 return (tmp);
141 139 }
142 140 #endif /* !defined TYPECHECK */
143 141
144 142 static void
145 -abbrok(abbrp, zone)
146 -const char * const abbrp;
147 -const char * const zone;
143 +abbrok(const char * const abbrp, const char * const zone)
148 144 {
149 145 register const char *cp;
150 146 int error = 0;
151 147
152 148 if (warned)
153 149 return;
154 150 cp = abbrp;
155 - while (isascii(*cp) && isalpha((unsigned char)*cp))
151 + while (isalpha(*cp) || isdigit(*cp) || *cp == '-' || *cp == '+')
156 152 ++cp;
157 153 (void) fflush(stdout);
158 - if (cp - abbrp == 0) {
159 - /*
160 - * TRANSLATION_NOTE
161 - * The first %s prints for the program name (zdump),
162 - * the second %s prints the timezone name, the third
163 - * %s prints the timezone abbreviation (tzname[0] or
164 - * tzname[1]).
165 - */
154 + if (cp - abbrp < 3) {
166 155 (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
167 - "abbreviation \"%s\" lacks alphabetic at start\n"),
168 - progname, zone, abbrp);
169 - error = 1;
170 - } else if (cp - abbrp < 3) {
171 - (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
172 156 "abbreviation \"%s\" has fewer than 3 alphabetics\n"),
173 157 progname, zone, abbrp);
174 158 error = 1;
175 159 } else if (cp - abbrp > 6) {
176 160 (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
177 - "abbreviation \"%s\" has more than 6 alphabetics\n"),
161 + "abbreviation \"%s\" has more than 6 characters\n"),
178 162 progname, zone, abbrp);
179 163 error = 1;
164 + } else if (*cp != '\0') {
165 + (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
166 + "abbreviation \"%s\" has characters other than "
167 + "alphanumerics\n"), progname, zone, abbrp);
168 + error = 1;
180 169 }
181 - if (error == 0 && (*cp == '+' || *cp == '-')) {
182 - ++cp;
183 - if (isascii(*cp) && isdigit((unsigned char)*cp))
184 - if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
185 - ++cp;
186 - if (*cp != '\0') {
187 - (void) fprintf(stderr, gettext("%s: warning: "
188 - "zone \"%s\" abbreviation \"%s\" differs from "
189 - "POSIX standard\n"), progname, zone, abbrp);
190 - error = 1;
191 - }
192 - }
193 170 if (error)
194 171 warned = TRUE;
195 172 }
196 173
197 174 int
198 175 main(argc, argv)
199 176 int argc;
200 177 char *argv[];
201 178 {
202 179 register int i;
203 180 register int c;
204 181 register int vflag;
205 182 register char *cutarg;
206 183 register long cutloyear = ZDUMP_LO_YEAR;
207 184 register long cuthiyear = ZDUMP_HI_YEAR;
208 185 register time_t cutlotime;
209 186 register time_t cuthitime;
210 187 time_t now;
211 188 time_t t;
212 189 time_t newt;
213 190 struct tm tm;
214 191 struct tm newtm;
215 192 register struct tm *tmp;
216 193 register struct tm *newtmp;
217 194
218 195 INITIALIZE(cutlotime);
219 196 INITIALIZE(cuthitime);
220 197
221 198 (void) setlocale(LC_ALL, "");
222 199 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
223 200 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
224 201 #endif
225 202 (void) textdomain(TEXT_DOMAIN);
226 203
227 204 progname = argv[0];
228 205 for (i = 1; i < argc; ++i)
229 206 if (strcmp(argv[i], "--version") == 0) {
230 207 (void) printf("%s\n", elsieid);
231 208 exit(EXIT_SUCCESS);
232 209 }
233 210 vflag = 0;
234 211 cutarg = NULL;
235 212 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
236 213 if (c == 'v')
237 214 vflag = 1;
238 215 else cutarg = optarg;
239 216 if (c != EOF ||
240 217 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
241 218 usage();
242 219 /* NOTREACHED */
243 220 }
244 221 if (vflag) {
245 222 if (cutarg != NULL) {
246 223 long lo;
247 224 long hi;
248 225 char dummy;
249 226
250 227 if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
251 228 cuthiyear = hi;
252 229 } else if (sscanf(cutarg, "%ld,%ld%c",
253 230 &lo, &hi, &dummy) == 2) {
254 231 cutloyear = lo;
255 232 cuthiyear = hi;
256 233 } else {
257 234 (void) fprintf(stderr, gettext("%s: wild -c argument %s\n"),
258 235 progname, cutarg);
259 236 exit(EXIT_FAILURE);
260 237 }
261 238 }
262 239 setabsolutes();
263 240 cutlotime = yeartot(cutloyear);
264 241 cuthitime = yeartot(cuthiyear);
265 242 }
266 243 (void) time(&now);
267 244 longest = 0;
268 245 for (i = optind; i < argc; ++i)
269 246 if (strlen(argv[i]) > longest)
270 247 longest = strlen(argv[i]);
271 248
272 249 for (i = optind; i < argc; ++i) {
273 250 static char buf[MAX_STRING_LENGTH];
274 251 static char *tzp = NULL;
275 252
276 253 (void) unsetenv("TZ");
277 254 if (tzp != NULL)
278 255 free(tzp);
279 256 if ((tzp = malloc(3 + strlen(argv[i]) + 1)) == NULL) {
280 257 perror(progname);
281 258 exit(EXIT_FAILURE);
282 259 }
283 260 (void) strcpy(tzp, "TZ=");
284 261 (void) strcat(tzp, argv[i]);
285 262 if (putenv(tzp) != 0) {
286 263 perror(progname);
287 264 exit(EXIT_FAILURE);
288 265 }
289 266 if (!vflag) {
290 267 show(argv[i], now, FALSE);
291 268 continue;
292 269 }
293 270
294 271 #if defined(sun)
295 272 /*
296 273 * We show the current time first, probably because we froze
297 274 * the behavior of zdump some time ago and then it got
298 275 * changed.
299 276 */
300 277 show(argv[i], now, TRUE);
301 278 #endif
302 279 warned = FALSE;
303 280 t = absolute_min_time;
304 281 show(argv[i], t, TRUE);
305 282 t += SECSPERHOUR * HOURSPERDAY;
306 283 show(argv[i], t, TRUE);
307 284 if (t < cutlotime)
308 285 t = cutlotime;
309 286 tmp = my_localtime(&t);
310 287 if (tmp != NULL) {
311 288 tm = *tmp;
312 289 (void) strncpy(buf, abbr(&tm), sizeof (buf) - 1);
313 290 }
314 291 for (;;) {
315 292 if (t >= cuthitime)
316 293 break;
317 294 /* check if newt will overrun maximum time_t value */
318 295 if (t > LONG_MAX - (SECSPERHOUR * 12))
319 296 break;
320 297 newt = t + SECSPERHOUR * 12;
321 298 if (newt >= cuthitime)
322 299 break;
323 300 newtmp = localtime(&newt);
324 301 if (newtmp != NULL)
325 302 newtm = *newtmp;
326 303 if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
327 304 (delta(&newtm, &tm) != (newt - t) ||
328 305 newtm.tm_isdst != tm.tm_isdst ||
329 306 strcmp(abbr(&newtm), buf) != 0)) {
330 307 newt = hunt(argv[i], t, newt);
331 308 newtmp = localtime(&newt);
332 309 if (newtmp != NULL) {
333 310 newtm = *newtmp;
334 311 (void) strncpy(buf,
335 312 abbr(&newtm),
336 313 sizeof (buf) - 1);
337 314 }
338 315 }
339 316 t = newt;
340 317 tm = newtm;
341 318 tmp = newtmp;
342 319 }
343 320 t = absolute_max_time;
344 321 #if defined(sun)
345 322 show(argv[i], t, TRUE);
346 323 t -= SECSPERHOUR * HOURSPERDAY;
347 324 show(argv[i], t, TRUE);
348 325 #else /* !defined(sun) */
349 326 t -= SECSPERHOUR * HOURSPERDAY;
350 327 show(argv[i], t, TRUE);
351 328 t += SECSPERHOUR * HOURSPERDAY;
352 329 show(argv[i], t, TRUE);
353 330 #endif /* !defined(sun) */
354 331 }
355 332 if (fflush(stdout) || ferror(stdout)) {
356 333 (void) fprintf(stderr, "%s: ", progname);
357 334 (void) perror(gettext("Error writing standard output"));
358 335 exit(EXIT_FAILURE);
359 336 }
360 337 return (EXIT_SUCCESS);
361 338 }
362 339
363 340 static void
364 341 setabsolutes()
365 342 {
366 343 #if defined(sun)
367 344 absolute_min_time = LONG_MIN;
368 345 absolute_max_time = LONG_MAX;
369 346 #else
370 347 if (0.5 == (time_t)0.5) {
371 348 /*
372 349 * time_t is floating.
373 350 */
374 351 if (sizeof (time_t) == sizeof (float)) {
375 352 absolute_min_time = (time_t)-FLT_MAX;
376 353 absolute_max_time = (time_t)FLT_MAX;
377 354 } else if (sizeof (time_t) == sizeof (double)) {
378 355 absolute_min_time = (time_t)-DBL_MAX;
379 356 absolute_max_time = (time_t)DBL_MAX;
380 357 } else {
381 358 (void) fprintf(stderr, gettext("%s: use of -v on "
382 359 "system with floating time_t other than float "
383 360 "or double\n"), progname);
384 361 exit(EXIT_FAILURE);
385 362 }
386 363 } else
387 364 /*CONSTANTCONDITION*/
388 365 if (0 > (time_t)-1) {
389 366 /*
390 367 * time_t is signed.
391 368 */
392 369 register time_t hibit;
393 370
394 371 for (hibit = 1; (hibit * 2) != 0; hibit *= 2)
395 372 continue;
396 373 absolute_min_time = hibit;
397 374 absolute_max_time = -(hibit + 1);
398 375 } else {
399 376 /*
400 377 * time_t is unsigned.
401 378 */
402 379 absolute_min_time = 0;
403 380 absolute_max_time = absolute_min_time - 1;
404 381 }
405 382 #endif
406 383 }
407 384
408 385 static time_t
409 386 yeartot(y)
410 387 const long y;
411 388 {
412 389 register long myy;
413 390 register long seconds;
414 391 register time_t t;
415 392
416 393 myy = EPOCH_YEAR;
417 394 t = 0;
418 395 while (myy != y) {
419 396 if (myy < y) {
420 397 seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
421 398 ++myy;
422 399 if (t > absolute_max_time - seconds) {
423 400 t = absolute_max_time;
424 401 break;
425 402 }
426 403 t += seconds;
427 404 } else {
428 405 --myy;
429 406 seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
430 407 if (t < absolute_min_time + seconds) {
431 408 t = absolute_min_time;
432 409 break;
433 410 }
434 411 t -= seconds;
435 412 }
436 413 }
437 414 return (t);
438 415 }
439 416
440 417 static time_t
441 418 hunt(name, lot, hit)
442 419 char *name;
443 420 time_t lot;
444 421 time_t hit;
445 422 {
446 423 time_t t;
447 424 long diff;
448 425 struct tm lotm;
449 426 register struct tm *lotmp;
450 427 struct tm tm;
451 428 register struct tm *tmp;
452 429 char loab[MAX_STRING_LENGTH];
453 430
454 431 lotmp = my_localtime(&lot);
455 432 if (lotmp != NULL) {
456 433 lotm = *lotmp;
457 434 (void) strncpy(loab, abbr(&lotm), sizeof (loab) - 1);
458 435 }
459 436 for (;;) {
460 437 diff = (long)(hit - lot);
461 438 if (diff < 2)
462 439 break;
463 440 t = lot;
464 441 t += diff / 2;
465 442 if (t <= lot)
466 443 ++t;
467 444 else if (t >= hit)
468 445 --t;
469 446 tmp = my_localtime(&t);
470 447 if (tmp != NULL)
471 448 tm = *tmp;
472 449 if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
473 450 (delta(&tm, &lotm) == (t - lot) &&
474 451 tm.tm_isdst == lotm.tm_isdst &&
475 452 strcmp(abbr(&tm), loab) == 0)) {
476 453 lot = t;
477 454 lotm = tm;
478 455 lotmp = tmp;
479 456 } else hit = t;
480 457 }
481 458 show(name, lot, TRUE);
482 459 show(name, hit, TRUE);
483 460 return (hit);
484 461 }
485 462
486 463 /*
487 464 * Thanks to Paul Eggert for logic used in delta.
488 465 */
489 466
490 467 static long
491 468 delta(newp, oldp)
492 469 struct tm *newp;
493 470 struct tm *oldp;
494 471 {
495 472 register long result;
496 473 register int tmy;
497 474
498 475 if (newp->tm_year < oldp->tm_year)
499 476 return (-delta(oldp, newp));
500 477 result = 0;
501 478 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
502 479 result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
503 480 result += newp->tm_yday - oldp->tm_yday;
504 481 result *= HOURSPERDAY;
505 482 result += newp->tm_hour - oldp->tm_hour;
506 483 result *= MINSPERHOUR;
507 484 result += newp->tm_min - oldp->tm_min;
508 485 result *= SECSPERMIN;
509 486 result += newp->tm_sec - oldp->tm_sec;
510 487 return (result);
511 488 }
512 489
513 490 static void
514 491 show(zone, t, v)
515 492 char *zone;
516 493 time_t t;
517 494 int v;
518 495 {
519 496 register struct tm *tmp;
520 497
521 498 (void) printf("%-*s ", (int)longest, zone);
522 499 if (v) {
523 500 tmp = gmtime(&t);
524 501 if (tmp == NULL) {
525 502 (void) printf(tformat(), t);
526 503 } else {
527 504 dumptime(tmp);
528 505 (void) printf(" UTC");
529 506 }
530 507 (void) printf(" = ");
531 508 }
532 509 tmp = my_localtime(&t);
533 510 dumptime(tmp);
534 511 if (tmp != NULL) {
535 512 if (*abbr(tmp) != '\0')
536 513 (void) printf(" %s", abbr(tmp));
537 514 if (v) {
538 515 (void) printf(" isdst=%d", tmp->tm_isdst);
539 516 #ifdef TM_GMTOFF
540 517 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
541 518 #endif /* defined TM_GMTOFF */
542 519 }
543 520 }
544 521 (void) printf("\n");
545 522 if (tmp != NULL && *abbr(tmp) != '\0')
546 523 abbrok(abbr(tmp), zone);
547 524 }
548 525
549 526 static char *
550 527 abbr(tmp)
551 528 struct tm *tmp;
552 529 {
553 530 register char *result;
554 531 static char nada;
555 532
556 533 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
557 534 return (&nada);
558 535 result = tzname[tmp->tm_isdst];
559 536 return ((result == NULL) ? &nada : result);
560 537 }
561 538
562 539 /*
563 540 * The code below can fail on certain theoretical systems;
564 541 * it works on all known real-world systems as of 2004-12-30.
565 542 */
566 543
567 544 static const char *
568 545 tformat()
569 546 {
570 547 #if defined(sun)
571 548 /* time_t is signed long */
572 549 return ("%ld");
573 550 #else
574 551 /*CONSTANTCONDITION*/
575 552 if (0.5 == (time_t)0.5) { /* floating */
576 553 /*CONSTANTCONDITION*/
577 554 if (sizeof (time_t) > sizeof (double))
578 555 return ("%Lg");
579 556 return ("%g");
580 557 }
581 558 /*CONSTANTCONDITION*/
582 559 if (0 > (time_t)-1) { /* signed */
583 560 /*CONSTANTCONDITION*/
584 561 if (sizeof (time_t) > sizeof (long))
585 562 return ("%lld");
586 563 /*CONSTANTCONDITION*/
587 564 if (sizeof (time_t) > sizeof (int))
588 565 return ("%ld");
589 566 return ("%d");
590 567 }
591 568 /*CONSTANTCONDITION*/
592 569 if (sizeof (time_t) > sizeof (unsigned long))
593 570 return ("%llu");
594 571 /*CONSTANTCONDITION*/
595 572 if (sizeof (time_t) > sizeof (unsigned int))
596 573 return ("%lu");
597 574 return ("%u");
598 575 #endif
599 576 }
600 577
601 578 static void
602 579 dumptime(timeptr)
603 580 register const struct tm *timeptr;
604 581 {
605 582 static const char wday_name[][3] = {
606 583 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
607 584 };
608 585 static const char mon_name[][3] = {
609 586 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
610 587 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
611 588 };
612 589 register const char *wn;
613 590 register const char *mn;
614 591 register int lead;
615 592 register int trail;
616 593
617 594 if (timeptr == NULL) {
618 595 (void) printf("NULL");
619 596 return;
620 597 }
621 598 /*
622 599 * The packaged versions of localtime and gmtime never put out-of-range
623 600 * values in tm_wday or tm_mon, but since this code might be compiled
624 601 * with other (perhaps experimental) versions, paranoia is in order.
625 602 */
626 603 if (timeptr->tm_wday < 0 || timeptr->tm_wday >=
627 604 (int)(sizeof (wday_name) / sizeof (wday_name[0])))
628 605 wn = "???";
629 606 else wn = wday_name[timeptr->tm_wday];
630 607 if (timeptr->tm_mon < 0 || timeptr->tm_mon >=
631 608 (int)(sizeof (mon_name) / sizeof (mon_name[0])))
632 609 mn = "???";
633 610 else mn = mon_name[timeptr->tm_mon];
634 611 (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
635 612 wn, mn,
636 613 timeptr->tm_mday, timeptr->tm_hour,
637 614 timeptr->tm_min, timeptr->tm_sec);
638 615 #define DIVISOR 10
639 616 trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
640 617 lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
641 618 trail / DIVISOR;
642 619 trail %= DIVISOR;
643 620 if (trail < 0 && lead > 0) {
644 621 trail += DIVISOR;
645 622 --lead;
646 623 } else if (lead < 0 && trail > 0) {
647 624 trail -= DIVISOR;
648 625 ++lead;
649 626 }
650 627 if (lead == 0)
651 628 (void) printf("%d", trail);
652 629 else
653 630 (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
654 631 }
655 632
656 633 static void
657 634 usage()
658 635 {
659 636 (void) fprintf(stderr, gettext(
660 637 "%s: [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
661 638 progname);
662 639 exit(EXIT_FAILURE);
663 640 /* NOTREACHED */
664 641 }
|
↓ open down ↓ |
462 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX