xref: /csrg-svn/share/zoneinfo/DIST/zdump.c (revision 37206)
1*37206Sbostic #ifndef lint
2*37206Sbostic #ifndef NOID
3*37206Sbostic static char	elsieid[] = "@(#)zdump.c	4.9";
4*37206Sbostic #endif /* !defined NOID */
5*37206Sbostic #endif /* !defined lint */
6*37206Sbostic 
7*37206Sbostic /*
8*37206Sbostic ** This code has been made entirely independent of the rest of the time
9*37206Sbostic ** conversion package to increase confidence in the verification it provides.
10*37206Sbostic ** You can use this code to help in verifying other implementations.
11*37206Sbostic */
12*37206Sbostic 
13*37206Sbostic #include <stdio.h>
14*37206Sbostic #include <time.h>
15*37206Sbostic #include <sys/types.h>
16*37206Sbostic 
17*37206Sbostic #ifndef TRUE
18*37206Sbostic #define TRUE		1
19*37206Sbostic #endif /* !defined TRUE */
20*37206Sbostic 
21*37206Sbostic #ifndef FALSE
22*37206Sbostic #define FALSE		0
23*37206Sbostic #endif /* !defined TRUE */
24*37206Sbostic 
25*37206Sbostic #ifndef EXIT_SUCCESS
26*37206Sbostic #define EXIT_SUCCESS	0
27*37206Sbostic #endif /* !defined EXIT_SUCCESS */
28*37206Sbostic 
29*37206Sbostic #ifndef EXIT_FAILURE
30*37206Sbostic #define EXIT_FAILURE	1
31*37206Sbostic #endif /* !defined EXIT_FAILURE */
32*37206Sbostic 
33*37206Sbostic #ifndef SECSPERMIN
34*37206Sbostic #define SECSPERMIN	60
35*37206Sbostic #endif /* !defined SECSPERMIN */
36*37206Sbostic 
37*37206Sbostic #ifndef SECSPERHOUR
38*37206Sbostic #define SECSPERHOUR	3600
39*37206Sbostic #endif /* !defined SECSPERHOUR */
40*37206Sbostic 
41*37206Sbostic #ifndef HOURSPERDAY
42*37206Sbostic #define HOURSPERDAY	24
43*37206Sbostic #endif /* !defined HOURSPERDAY */
44*37206Sbostic 
45*37206Sbostic #ifndef EPOCH_YEAR
46*37206Sbostic #define EPOCH_YEAR	1970
47*37206Sbostic #endif /* !defined EPOCH_YEAR */
48*37206Sbostic 
49*37206Sbostic #ifndef DAYSPERNYEAR
50*37206Sbostic #define DAYSPERNYEAR	365
51*37206Sbostic #endif /* !defined DAYSPERNYEAR */
52*37206Sbostic 
53*37206Sbostic extern char **	environ;
54*37206Sbostic extern int	getopt();
55*37206Sbostic extern char *	malloc();
56*37206Sbostic extern char *	optarg;
57*37206Sbostic extern int	optind;
58*37206Sbostic extern void	tzset();
59*37206Sbostic 
60*37206Sbostic char *		tzname[2];
61*37206Sbostic 
62*37206Sbostic static int	longest;
63*37206Sbostic static void	show();
64*37206Sbostic static void	hunt();
65*37206Sbostic static long	delta();
66*37206Sbostic 
67*37206Sbostic int
68*37206Sbostic main(argc, argv)
69*37206Sbostic int	argc;
70*37206Sbostic char *	argv[];
71*37206Sbostic {
72*37206Sbostic 	register int	i, c;
73*37206Sbostic 	register int	vflag;
74*37206Sbostic 	register char *	cutoff;
75*37206Sbostic 	register int	cutyear;
76*37206Sbostic 	register long	cuttime;
77*37206Sbostic 	time_t		now;
78*37206Sbostic 	time_t		t, newt;
79*37206Sbostic 	time_t		hibit;
80*37206Sbostic 	struct tm	tm, newtm;
81*37206Sbostic 
82*37206Sbostic 	vflag = 0;
83*37206Sbostic 	cutoff = NULL;
84*37206Sbostic 	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
85*37206Sbostic 		if (c == 'v')
86*37206Sbostic 			vflag = 1;
87*37206Sbostic 		else	cutoff = optarg;
88*37206Sbostic 	if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) {
89*37206Sbostic 		(void) fprintf(stderr,
90*37206Sbostic 			"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n",
91*37206Sbostic 			argv[0], argv[0]);
92*37206Sbostic 		(void) exit(EXIT_FAILURE);
93*37206Sbostic 	}
94*37206Sbostic 	if (cutoff != NULL)
95*37206Sbostic 		cutyear = atoi(cutoff);
96*37206Sbostic 	/*
97*37206Sbostic 	** VERY approximate.
98*37206Sbostic 	*/
99*37206Sbostic 	cuttime = (long) (cutyear - EPOCH_YEAR) *
100*37206Sbostic 		SECSPERHOUR * HOURSPERDAY * DAYSPERNYEAR;
101*37206Sbostic 	(void) time(&now);
102*37206Sbostic 	longest = 0;
103*37206Sbostic 	for (i = optind; i < argc; ++i)
104*37206Sbostic 		if (strlen(argv[i]) > longest)
105*37206Sbostic 			longest = strlen(argv[i]);
106*37206Sbostic 	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
107*37206Sbostic 		;
108*37206Sbostic 	for (i = optind; i < argc; ++i) {
109*37206Sbostic 		register char **	saveenv;
110*37206Sbostic 		char *			tzequals;
111*37206Sbostic 		char *			fakeenv[2];
112*37206Sbostic 
113*37206Sbostic 		tzequals = malloc((unsigned) (strlen(argv[i]) + 4));
114*37206Sbostic 		if (tzequals == NULL) {
115*37206Sbostic 			(void) fprintf(stderr, "%s: can't allocate memory\n",
116*37206Sbostic 				argv[0]);
117*37206Sbostic 			(void) exit(EXIT_FAILURE);
118*37206Sbostic 		}
119*37206Sbostic 		(void) sprintf(tzequals, "TZ=%s", argv[i]);
120*37206Sbostic 		fakeenv[0] = tzequals;
121*37206Sbostic 		fakeenv[1] = NULL;
122*37206Sbostic 		saveenv = environ;
123*37206Sbostic 		environ = fakeenv;
124*37206Sbostic 		(void) tzset();
125*37206Sbostic 		free(tzequals);
126*37206Sbostic 		environ = saveenv;
127*37206Sbostic 		show(argv[i], now, FALSE);
128*37206Sbostic 		if (!vflag)
129*37206Sbostic 			continue;
130*37206Sbostic 		/*
131*37206Sbostic 		** Get lowest value of t.
132*37206Sbostic 		*/
133*37206Sbostic 		t = hibit;
134*37206Sbostic 		if (t > 0)		/* time_t is unsigned */
135*37206Sbostic 			t = 0;
136*37206Sbostic 		show(argv[i], t, TRUE);
137*37206Sbostic 		t += SECSPERHOUR * HOURSPERDAY;
138*37206Sbostic 		show(argv[i], t, TRUE);
139*37206Sbostic 		tm = *localtime(&t);
140*37206Sbostic 		for ( ; ; ) {
141*37206Sbostic 			if (cutoff != NULL && t >= cuttime)
142*37206Sbostic 				break;
143*37206Sbostic 			newt = t + SECSPERHOUR * 12;
144*37206Sbostic 			if (cutoff != NULL && newt >= cuttime)
145*37206Sbostic 				break;
146*37206Sbostic 			if (newt <= t)
147*37206Sbostic 				break;
148*37206Sbostic 			newtm = *localtime(&newt);
149*37206Sbostic 			if (delta(&newtm, &tm) != (newt - t) ||
150*37206Sbostic 				newtm.tm_isdst != tm.tm_isdst)
151*37206Sbostic 					hunt(argv[i], t, newt);
152*37206Sbostic 			t = newt;
153*37206Sbostic 			tm = newtm;
154*37206Sbostic 		}
155*37206Sbostic 		/*
156*37206Sbostic 		** Get highest value of t.
157*37206Sbostic 		*/
158*37206Sbostic 		t = ~((time_t) 0);
159*37206Sbostic 		if (t < 0)		/* time_t is signed */
160*37206Sbostic 			t &= ~hibit;
161*37206Sbostic 		t -= SECSPERHOUR * HOURSPERDAY;
162*37206Sbostic 		show(argv[i], t, TRUE);
163*37206Sbostic 		t += SECSPERHOUR * HOURSPERDAY;
164*37206Sbostic 		show(argv[i], t, TRUE);
165*37206Sbostic 	}
166*37206Sbostic 	if (fflush(stdout) || ferror(stdout)) {
167*37206Sbostic 		(void) fprintf(stderr, "%s: Error writing standard output ",
168*37206Sbostic 			argv[0]);
169*37206Sbostic 		(void) perror("standard output");
170*37206Sbostic 		(void) exit(EXIT_FAILURE);
171*37206Sbostic 	}
172*37206Sbostic 	exit(EXIT_SUCCESS);
173*37206Sbostic 	for ( ; ; )
174*37206Sbostic 		;
175*37206Sbostic }
176*37206Sbostic 
177*37206Sbostic static void
178*37206Sbostic hunt(name, lot, hit)
179*37206Sbostic char *	name;
180*37206Sbostic time_t	lot;
181*37206Sbostic time_t	hit;
182*37206Sbostic {
183*37206Sbostic 	time_t		t;
184*37206Sbostic 	struct tm	lotm;
185*37206Sbostic 	struct tm	tm;
186*37206Sbostic 
187*37206Sbostic 	lotm = *localtime(&lot);
188*37206Sbostic 	while ((hit - lot) >= 2) {
189*37206Sbostic 		t = lot / 2 + hit / 2;
190*37206Sbostic 		if (t <= lot)
191*37206Sbostic 			++t;
192*37206Sbostic 		else if (t >= hit)
193*37206Sbostic 			--t;
194*37206Sbostic 		tm = *localtime(&t);
195*37206Sbostic 		if (delta(&tm, &lotm) == (t - lot) &&
196*37206Sbostic 			tm.tm_isdst == lotm.tm_isdst) {
197*37206Sbostic 				lot = t;
198*37206Sbostic 				lotm = tm;
199*37206Sbostic 		} else	hit = t;
200*37206Sbostic 	}
201*37206Sbostic 	show(name, lot, TRUE);
202*37206Sbostic 	show(name, hit, TRUE);
203*37206Sbostic }
204*37206Sbostic 
205*37206Sbostic static long
206*37206Sbostic delta(newp, oldp)
207*37206Sbostic struct tm *	newp;
208*37206Sbostic struct tm *	oldp;
209*37206Sbostic {
210*37206Sbostic 	long	result;
211*37206Sbostic 
212*37206Sbostic 	result = newp->tm_hour - oldp->tm_hour;
213*37206Sbostic 	if (result < 0)
214*37206Sbostic 		result += HOURSPERDAY;
215*37206Sbostic 	result *= SECSPERHOUR;
216*37206Sbostic 	result += (newp->tm_min - oldp->tm_min) * SECSPERMIN;
217*37206Sbostic 	return result + newp->tm_sec - oldp->tm_sec;
218*37206Sbostic }
219*37206Sbostic 
220*37206Sbostic static void
221*37206Sbostic show(zone, t, v)
222*37206Sbostic char *	zone;
223*37206Sbostic time_t	t;
224*37206Sbostic int	v;
225*37206Sbostic {
226*37206Sbostic 	struct tm *		tmp;
227*37206Sbostic 	extern struct tm *	localtime();
228*37206Sbostic 
229*37206Sbostic 	(void) printf("%-*s  ", longest, zone);
230*37206Sbostic 	if (v)
231*37206Sbostic 		(void) printf("%.24s GMT = ", asctime(gmtime(&t)));
232*37206Sbostic 	tmp = localtime(&t);
233*37206Sbostic 	(void) printf("%.24s", asctime(tmp));
234*37206Sbostic 	if (tzname[tmp->tm_isdst] != NULL &&
235*37206Sbostic 		*tzname[tmp->tm_isdst] != '\0')
236*37206Sbostic 			(void) printf(" %s", tzname[tmp->tm_isdst]);
237*37206Sbostic 	if (v) {
238*37206Sbostic 		(void) printf(" isdst=%d", tmp->tm_isdst);
239*37206Sbostic #ifdef TM_GMTOFF
240*37206Sbostic 		(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
241*37206Sbostic #endif /* defined TM_GMTOFF */
242*37206Sbostic 	}
243*37206Sbostic 	(void) printf("\n");
244*37206Sbostic }
245