137206Sbostic #ifndef lint
237206Sbostic #ifndef NOID
3*37207Sbostic static char elsieid[] = "@(#)zdump.c 4.10";
437206Sbostic #endif /* !defined NOID */
537206Sbostic #endif /* !defined lint */
637206Sbostic
737206Sbostic /*
837206Sbostic ** This code has been made entirely independent of the rest of the time
937206Sbostic ** conversion package to increase confidence in the verification it provides.
1037206Sbostic ** You can use this code to help in verifying other implementations.
1137206Sbostic */
1237206Sbostic
1337206Sbostic #include <stdio.h>
1437206Sbostic #include <time.h>
1537206Sbostic #include <sys/types.h>
1637206Sbostic
1737206Sbostic #ifndef TRUE
1837206Sbostic #define TRUE 1
1937206Sbostic #endif /* !defined TRUE */
2037206Sbostic
2137206Sbostic #ifndef FALSE
2237206Sbostic #define FALSE 0
2337206Sbostic #endif /* !defined TRUE */
2437206Sbostic
2537206Sbostic #ifndef EXIT_SUCCESS
2637206Sbostic #define EXIT_SUCCESS 0
2737206Sbostic #endif /* !defined EXIT_SUCCESS */
2837206Sbostic
2937206Sbostic #ifndef EXIT_FAILURE
3037206Sbostic #define EXIT_FAILURE 1
3137206Sbostic #endif /* !defined EXIT_FAILURE */
3237206Sbostic
3337206Sbostic #ifndef SECSPERMIN
3437206Sbostic #define SECSPERMIN 60
3537206Sbostic #endif /* !defined SECSPERMIN */
3637206Sbostic
3737206Sbostic #ifndef SECSPERHOUR
3837206Sbostic #define SECSPERHOUR 3600
3937206Sbostic #endif /* !defined SECSPERHOUR */
4037206Sbostic
4137206Sbostic #ifndef HOURSPERDAY
4237206Sbostic #define HOURSPERDAY 24
4337206Sbostic #endif /* !defined HOURSPERDAY */
4437206Sbostic
4537206Sbostic #ifndef EPOCH_YEAR
4637206Sbostic #define EPOCH_YEAR 1970
4737206Sbostic #endif /* !defined EPOCH_YEAR */
4837206Sbostic
4937206Sbostic #ifndef DAYSPERNYEAR
5037206Sbostic #define DAYSPERNYEAR 365
5137206Sbostic #endif /* !defined DAYSPERNYEAR */
5237206Sbostic
5337206Sbostic extern char ** environ;
5437206Sbostic extern int getopt();
5537206Sbostic extern char * malloc();
5637206Sbostic extern char * optarg;
5737206Sbostic extern int optind;
5837206Sbostic extern void tzset();
5937206Sbostic
6037206Sbostic char * tzname[2];
6137206Sbostic
6237206Sbostic static int longest;
6337206Sbostic static void show();
6437206Sbostic static void hunt();
6537206Sbostic static long delta();
66*37207Sbostic static char * ecpyalloc();
6737206Sbostic
68*37207Sbostic static char * progname;
69*37207Sbostic
7037206Sbostic int
main(argc,argv)7137206Sbostic main(argc, argv)
7237206Sbostic int argc;
7337206Sbostic char * argv[];
7437206Sbostic {
7537206Sbostic register int i, c;
7637206Sbostic register int vflag;
7737206Sbostic register char * cutoff;
7837206Sbostic register int cutyear;
7937206Sbostic register long cuttime;
8037206Sbostic time_t now;
8137206Sbostic time_t t, newt;
8237206Sbostic time_t hibit;
8337206Sbostic struct tm tm, newtm;
8437206Sbostic
85*37207Sbostic progname = argv[0];
8637206Sbostic vflag = 0;
8737206Sbostic cutoff = NULL;
8837206Sbostic while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
8937206Sbostic if (c == 'v')
9037206Sbostic vflag = 1;
9137206Sbostic else cutoff = optarg;
9237206Sbostic if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) {
9337206Sbostic (void) fprintf(stderr,
9437206Sbostic "%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n",
9537206Sbostic argv[0], argv[0]);
9637206Sbostic (void) exit(EXIT_FAILURE);
9737206Sbostic }
9837206Sbostic if (cutoff != NULL)
9937206Sbostic cutyear = atoi(cutoff);
10037206Sbostic /*
10137206Sbostic ** VERY approximate.
10237206Sbostic */
10337206Sbostic cuttime = (long) (cutyear - EPOCH_YEAR) *
10437206Sbostic SECSPERHOUR * HOURSPERDAY * DAYSPERNYEAR;
10537206Sbostic (void) time(&now);
10637206Sbostic longest = 0;
10737206Sbostic for (i = optind; i < argc; ++i)
10837206Sbostic if (strlen(argv[i]) > longest)
10937206Sbostic longest = strlen(argv[i]);
11037206Sbostic for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
11137206Sbostic ;
11237206Sbostic for (i = optind; i < argc; ++i) {
11337206Sbostic register char ** saveenv;
11437206Sbostic char * tzequals;
115*37207Sbostic char * ab;
11637206Sbostic char * fakeenv[2];
11737206Sbostic
11837206Sbostic tzequals = malloc((unsigned) (strlen(argv[i]) + 4));
11937206Sbostic if (tzequals == NULL) {
12037206Sbostic (void) fprintf(stderr, "%s: can't allocate memory\n",
12137206Sbostic argv[0]);
12237206Sbostic (void) exit(EXIT_FAILURE);
12337206Sbostic }
12437206Sbostic (void) sprintf(tzequals, "TZ=%s", argv[i]);
12537206Sbostic fakeenv[0] = tzequals;
12637206Sbostic fakeenv[1] = NULL;
12737206Sbostic saveenv = environ;
12837206Sbostic environ = fakeenv;
12937206Sbostic (void) tzset();
13037206Sbostic free(tzequals);
13137206Sbostic environ = saveenv;
13237206Sbostic show(argv[i], now, FALSE);
13337206Sbostic if (!vflag)
13437206Sbostic continue;
13537206Sbostic /*
13637206Sbostic ** Get lowest value of t.
13737206Sbostic */
13837206Sbostic t = hibit;
13937206Sbostic if (t > 0) /* time_t is unsigned */
14037206Sbostic t = 0;
14137206Sbostic show(argv[i], t, TRUE);
14237206Sbostic t += SECSPERHOUR * HOURSPERDAY;
14337206Sbostic show(argv[i], t, TRUE);
14437206Sbostic tm = *localtime(&t);
145*37207Sbostic ab = ecpyalloc(tzname[tm.tm_isdst]);
14637206Sbostic for ( ; ; ) {
14737206Sbostic if (cutoff != NULL && t >= cuttime)
14837206Sbostic break;
14937206Sbostic newt = t + SECSPERHOUR * 12;
15037206Sbostic if (cutoff != NULL && newt >= cuttime)
15137206Sbostic break;
15237206Sbostic if (newt <= t)
15337206Sbostic break;
15437206Sbostic newtm = *localtime(&newt);
15537206Sbostic if (delta(&newtm, &tm) != (newt - t) ||
156*37207Sbostic newtm.tm_isdst != tm.tm_isdst ||
157*37207Sbostic strcmp(tzname[newtm.tm_isdst], ab) != 0) {
15837206Sbostic hunt(argv[i], t, newt);
159*37207Sbostic free(ab);
160*37207Sbostic ab = ecpyalloc(tzname[newtm.tm_isdst]);
161*37207Sbostic }
16237206Sbostic t = newt;
16337206Sbostic tm = newtm;
16437206Sbostic }
16537206Sbostic /*
16637206Sbostic ** Get highest value of t.
16737206Sbostic */
16837206Sbostic t = ~((time_t) 0);
16937206Sbostic if (t < 0) /* time_t is signed */
17037206Sbostic t &= ~hibit;
17137206Sbostic t -= SECSPERHOUR * HOURSPERDAY;
17237206Sbostic show(argv[i], t, TRUE);
17337206Sbostic t += SECSPERHOUR * HOURSPERDAY;
17437206Sbostic show(argv[i], t, TRUE);
17537206Sbostic }
17637206Sbostic if (fflush(stdout) || ferror(stdout)) {
17737206Sbostic (void) fprintf(stderr, "%s: Error writing standard output ",
17837206Sbostic argv[0]);
17937206Sbostic (void) perror("standard output");
18037206Sbostic (void) exit(EXIT_FAILURE);
18137206Sbostic }
18237206Sbostic exit(EXIT_SUCCESS);
18337206Sbostic for ( ; ; )
18437206Sbostic ;
18537206Sbostic }
18637206Sbostic
18737206Sbostic static void
hunt(name,lot,hit)18837206Sbostic hunt(name, lot, hit)
18937206Sbostic char * name;
19037206Sbostic time_t lot;
19137206Sbostic time_t hit;
19237206Sbostic {
19337206Sbostic time_t t;
19437206Sbostic struct tm lotm;
19537206Sbostic struct tm tm;
196*37207Sbostic char * loab;
19737206Sbostic
19837206Sbostic lotm = *localtime(&lot);
199*37207Sbostic loab = ecpyalloc(tzname[lotm.tm_isdst]);
20037206Sbostic while ((hit - lot) >= 2) {
20137206Sbostic t = lot / 2 + hit / 2;
20237206Sbostic if (t <= lot)
20337206Sbostic ++t;
20437206Sbostic else if (t >= hit)
20537206Sbostic --t;
20637206Sbostic tm = *localtime(&t);
20737206Sbostic if (delta(&tm, &lotm) == (t - lot) &&
208*37207Sbostic tm.tm_isdst == lotm.tm_isdst &&
209*37207Sbostic strcmp(tzname[tm.tm_isdst], loab) == 0) {
21037206Sbostic lot = t;
21137206Sbostic lotm = tm;
21237206Sbostic } else hit = t;
21337206Sbostic }
21437206Sbostic show(name, lot, TRUE);
21537206Sbostic show(name, hit, TRUE);
216*37207Sbostic free(loab);
21737206Sbostic }
21837206Sbostic
21937206Sbostic static long
delta(newp,oldp)22037206Sbostic delta(newp, oldp)
22137206Sbostic struct tm * newp;
22237206Sbostic struct tm * oldp;
22337206Sbostic {
22437206Sbostic long result;
22537206Sbostic
22637206Sbostic result = newp->tm_hour - oldp->tm_hour;
22737206Sbostic if (result < 0)
22837206Sbostic result += HOURSPERDAY;
22937206Sbostic result *= SECSPERHOUR;
23037206Sbostic result += (newp->tm_min - oldp->tm_min) * SECSPERMIN;
23137206Sbostic return result + newp->tm_sec - oldp->tm_sec;
23237206Sbostic }
23337206Sbostic
23437206Sbostic static void
show(zone,t,v)23537206Sbostic show(zone, t, v)
23637206Sbostic char * zone;
23737206Sbostic time_t t;
23837206Sbostic int v;
23937206Sbostic {
24037206Sbostic struct tm * tmp;
24137206Sbostic extern struct tm * localtime();
24237206Sbostic
24337206Sbostic (void) printf("%-*s ", longest, zone);
24437206Sbostic if (v)
24537206Sbostic (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
24637206Sbostic tmp = localtime(&t);
24737206Sbostic (void) printf("%.24s", asctime(tmp));
24837206Sbostic if (tzname[tmp->tm_isdst] != NULL &&
24937206Sbostic *tzname[tmp->tm_isdst] != '\0')
25037206Sbostic (void) printf(" %s", tzname[tmp->tm_isdst]);
25137206Sbostic if (v) {
25237206Sbostic (void) printf(" isdst=%d", tmp->tm_isdst);
25337206Sbostic #ifdef TM_GMTOFF
25437206Sbostic (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
25537206Sbostic #endif /* defined TM_GMTOFF */
25637206Sbostic }
25737206Sbostic (void) printf("\n");
25837206Sbostic }
259*37207Sbostic
260*37207Sbostic static char *
ecpyalloc(string)261*37207Sbostic ecpyalloc(string)
262*37207Sbostic char * string;
263*37207Sbostic {
264*37207Sbostic register char * result;
265*37207Sbostic register int length;
266*37207Sbostic
267*37207Sbostic length = strlen(string);
268*37207Sbostic result = malloc(length + 1);
269*37207Sbostic if (result == 0) {
270*37207Sbostic (void) fprintf(stderr, "%s: can't allocate memory\n", progname);
271*37207Sbostic (void) exit(EXIT_FAILURE);
272*37207Sbostic }
273*37207Sbostic (void) strcpy(result, string);
274*37207Sbostic return result;
275*37207Sbostic }
276