zdump.c revision 2703
1#ifndef lint
2#ifndef NOID
3static char	elsieid[] = "@(#)zdump.c	7.10";
4#endif /* !defined NOID */
5#endif /* !defined lint */
6
7/*
8** This code has been made independent of the rest of the time
9** conversion package to increase confidence in the verification it provides.
10** You can use this code to help in verifying other implementations.
11*/
12
13#include "stdio.h"	/* for stdout, stderr */
14#include "string.h"	/* for strcpy */
15#include "sys/types.h"	/* for time_t */
16#include "time.h"	/* for struct tm */
17
18#ifndef MAX_STRING_LENGTH
19#define MAX_STRING_LENGTH	1024
20#endif /* !defined MAX_STRING_LENGTH */
21
22#ifndef TRUE
23#define TRUE		1
24#endif /* !defined TRUE */
25
26#ifndef FALSE
27#define FALSE		0
28#endif /* !defined FALSE */
29
30#ifndef EXIT_SUCCESS
31#define EXIT_SUCCESS	0
32#endif /* !defined EXIT_SUCCESS */
33
34#ifndef EXIT_FAILURE
35#define EXIT_FAILURE	1
36#endif /* !defined EXIT_FAILURE */
37
38#ifndef SECSPERMIN
39#define SECSPERMIN	60
40#endif /* !defined SECSPERMIN */
41
42#ifndef MINSPERHOUR
43#define MINSPERHOUR	60
44#endif /* !defined MINSPERHOUR */
45
46#ifndef SECSPERHOUR
47#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
48#endif /* !defined SECSPERHOUR */
49
50#ifndef HOURSPERDAY
51#define HOURSPERDAY	24
52#endif /* !defined HOURSPERDAY */
53
54#ifndef EPOCH_YEAR
55#define EPOCH_YEAR	1970
56#endif /* !defined EPOCH_YEAR */
57
58#ifndef TM_YEAR_BASE
59#define TM_YEAR_BASE	1900
60#endif /* !defined TM_YEAR_BASE */
61
62#ifndef DAYSPERNYEAR
63#define DAYSPERNYEAR	365
64#endif /* !defined DAYSPERNYEAR */
65
66#ifndef isleap
67#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
68#endif /* !defined isleap */
69
70extern char **	environ;
71extern int	getopt();
72extern char *	optarg;
73extern int	optind;
74extern time_t	time();
75extern char *	tzname[2];
76extern void	tzset();
77
78#ifdef USG
79extern void	exit();
80extern void	perror();
81#endif /* defined USG */
82
83static char *	abbr();
84static long	delta();
85static time_t	hunt();
86static int	longest;
87static char *	progname;
88static void	show();
89
90int
91main(argc, argv)
92int	argc;
93char *	argv[];
94{
95	register int	i, c;
96	register int	vflag;
97	register char *	cutoff;
98	register int	cutyear;
99	register long	cuttime;
100	time_t		now;
101	time_t		t, newt;
102	time_t		hibit;
103	struct tm	tm, newtm;
104
105	progname = argv[0];
106	vflag = 0;
107	cutoff = NULL;
108	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
109		if (c == 'v')
110			vflag = 1;
111		else	cutoff = optarg;
112	if (c != EOF ||
113		(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
114			(void) fprintf(stderr,
115"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n",
116				argv[0], argv[0]);
117			(void) exit(EXIT_FAILURE);
118	}
119	if (cutoff != NULL) {
120		int	y;
121
122		cutyear = atoi(cutoff);
123		cuttime = 0;
124		for (y = EPOCH_YEAR; y < cutyear; ++y)
125			cuttime += DAYSPERNYEAR + isleap(y);
126		cuttime *= SECSPERHOUR * HOURSPERDAY;
127	}
128	(void) time(&now);
129	longest = 0;
130	for (i = optind; i < argc; ++i)
131		if (strlen(argv[i]) > longest)
132			longest = strlen(argv[i]);
133	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
134		continue;
135	for (i = optind; i < argc; ++i) {
136		register char **	saveenv;
137		static char		buf[MAX_STRING_LENGTH];
138		char *			fakeenv[2];
139
140		if (strlen(argv[i]) + 4 > sizeof buf) {
141			(void) fflush(stdout);
142			(void) fprintf(stderr, "%s: argument too long -- %s\n",
143				progname, argv[i]);
144			(void) exit(EXIT_FAILURE);
145		}
146		(void) strcpy(buf, "TZ=");
147		(void) strcat(buf, argv[i]);
148		fakeenv[0] = buf;
149		fakeenv[1] = NULL;
150		saveenv = environ;
151		environ = fakeenv;
152		(void) tzset();
153		environ = saveenv;
154		show(argv[i], now, FALSE);
155		if (!vflag)
156			continue;
157		/*
158		** Get lowest value of t.
159		*/
160		t = hibit;
161		if (t > 0)		/* time_t is unsigned */
162			t = 0;
163		show(argv[i], t, TRUE);
164		t += SECSPERHOUR * HOURSPERDAY;
165		show(argv[i], t, TRUE);
166		tm = *localtime(&t);
167		(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
168		for ( ; ; ) {
169			if (cutoff != NULL && t >= cuttime)
170				break;
171			newt = t + SECSPERHOUR * 12;
172			if (cutoff != NULL && newt >= cuttime)
173				break;
174			if (newt <= t)
175				break;
176			newtm = *localtime(&newt);
177			if (delta(&newtm, &tm) != (newt - t) ||
178				newtm.tm_isdst != tm.tm_isdst ||
179				strcmp(abbr(&newtm), buf) != 0) {
180					newt = hunt(argv[i], t, newt);
181					newtm = *localtime(&newt);
182					(void) strncpy(buf, abbr(&newtm),
183						(sizeof buf) - 1);
184			}
185			t = newt;
186			tm = newtm;
187		}
188		/*
189		** Get highest value of t.
190		*/
191		t = ~((time_t) 0);
192		if (t < 0)		/* time_t is signed */
193			t &= ~hibit;
194		t -= SECSPERHOUR * HOURSPERDAY;
195		show(argv[i], t, TRUE);
196		t += SECSPERHOUR * HOURSPERDAY;
197		show(argv[i], t, TRUE);
198	}
199	if (fflush(stdout) || ferror(stdout)) {
200		(void) fprintf(stderr, "%s: Error writing standard output ",
201			argv[0]);
202		(void) perror("standard output");
203		(void) exit(EXIT_FAILURE);
204	}
205	exit(EXIT_SUCCESS);
206
207	/* gcc -Wall pacifier */
208	for ( ; ; )
209		continue;
210}
211
212static time_t
213hunt(name, lot, hit)
214char *	name;
215time_t	lot;
216time_t	hit;
217{
218	time_t		t;
219	struct tm	lotm;
220	struct tm	tm;
221	static char	loab[MAX_STRING_LENGTH];
222
223	lotm = *localtime(&lot);
224	(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
225	while ((hit - lot) >= 2) {
226		t = lot / 2 + hit / 2;
227		if (t <= lot)
228			++t;
229		else if (t >= hit)
230			--t;
231		tm = *localtime(&t);
232		if (delta(&tm, &lotm) == (t - lot) &&
233			tm.tm_isdst == lotm.tm_isdst &&
234			strcmp(abbr(&tm), loab) == 0) {
235				lot = t;
236				lotm = tm;
237		} else	hit = t;
238	}
239	show(name, lot, TRUE);
240	show(name, hit, TRUE);
241	return hit;
242}
243
244/*
245** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
246*/
247
248static long
249delta(newp, oldp)
250struct tm *	newp;
251struct tm *	oldp;
252{
253	long	result;
254	int	tmy;
255
256	if (newp->tm_year < oldp->tm_year)
257		return -delta(oldp, newp);
258	result = 0;
259	for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
260		result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
261	result += newp->tm_yday - oldp->tm_yday;
262	result *= HOURSPERDAY;
263	result += newp->tm_hour - oldp->tm_hour;
264	result *= MINSPERHOUR;
265	result += newp->tm_min - oldp->tm_min;
266	result *= SECSPERMIN;
267	result += newp->tm_sec - oldp->tm_sec;
268	return result;
269}
270
271static void
272show(zone, t, v)
273char *	zone;
274time_t	t;
275int	v;
276{
277	struct tm *		tmp;
278	extern struct tm *	localtime();
279
280	(void) printf("%-*s  ", longest, zone);
281	if (v)
282		(void) printf("%.24s GMT = ", asctime(gmtime(&t)));
283	tmp = localtime(&t);
284	(void) printf("%.24s", asctime(tmp));
285	if (*abbr(tmp) != '\0')
286		(void) printf(" %s", abbr(tmp));
287	if (v) {
288		(void) printf(" isdst=%d", tmp->tm_isdst);
289#ifdef TM_GMTOFF
290		(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
291#endif /* defined TM_GMTOFF */
292	}
293	(void) printf("\n");
294}
295
296static char *
297abbr(tmp)
298struct tm *	tmp;
299{
300	register char *	result;
301	static char	nada[1];
302
303	if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
304		return nada;
305	result = tzname[tmp->tm_isdst];
306	return (result == NULL) ? nada : result;
307}
308