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