~ubuntu-branches/ubuntu/natty/eglibc/natty-security

« back to all changes in this revision

Viewing changes to timezone/zdump.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno
  • Date: 2009-05-05 09:54:14 UTC
  • Revision ID: james.westby@ubuntu.com-20090505095414-c45qsg9ixjheohru
ImportĀ upstreamĀ versionĀ 2.9

Show diffs side-by-side

added added

removed removed

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