xref: /original-bsd/share/zoneinfo/DIST/zdump.c (revision 0b8b3d5a)
18a854286Sbostic #ifndef lint
28a854286Sbostic #ifndef NOID
3*0b8b3d5aSbostic static char	elsieid[] = "@(#)zdump.c	4.10";
48a854286Sbostic #endif /* !defined NOID */
58a854286Sbostic #endif /* !defined lint */
68a854286Sbostic 
78a854286Sbostic /*
88a854286Sbostic ** This code has been made entirely independent of the rest of the time
98a854286Sbostic ** conversion package to increase confidence in the verification it provides.
108a854286Sbostic ** You can use this code to help in verifying other implementations.
118a854286Sbostic */
128a854286Sbostic 
138a854286Sbostic #include <stdio.h>
148a854286Sbostic #include <time.h>
158a854286Sbostic #include <sys/types.h>
168a854286Sbostic 
178a854286Sbostic #ifndef TRUE
188a854286Sbostic #define TRUE		1
198a854286Sbostic #endif /* !defined TRUE */
208a854286Sbostic 
218a854286Sbostic #ifndef FALSE
228a854286Sbostic #define FALSE		0
238a854286Sbostic #endif /* !defined TRUE */
248a854286Sbostic 
258a854286Sbostic #ifndef EXIT_SUCCESS
268a854286Sbostic #define EXIT_SUCCESS	0
278a854286Sbostic #endif /* !defined EXIT_SUCCESS */
288a854286Sbostic 
298a854286Sbostic #ifndef EXIT_FAILURE
308a854286Sbostic #define EXIT_FAILURE	1
318a854286Sbostic #endif /* !defined EXIT_FAILURE */
328a854286Sbostic 
338a854286Sbostic #ifndef SECSPERMIN
348a854286Sbostic #define SECSPERMIN	60
358a854286Sbostic #endif /* !defined SECSPERMIN */
368a854286Sbostic 
378a854286Sbostic #ifndef SECSPERHOUR
388a854286Sbostic #define SECSPERHOUR	3600
398a854286Sbostic #endif /* !defined SECSPERHOUR */
408a854286Sbostic 
418a854286Sbostic #ifndef HOURSPERDAY
428a854286Sbostic #define HOURSPERDAY	24
438a854286Sbostic #endif /* !defined HOURSPERDAY */
448a854286Sbostic 
458a854286Sbostic #ifndef EPOCH_YEAR
468a854286Sbostic #define EPOCH_YEAR	1970
478a854286Sbostic #endif /* !defined EPOCH_YEAR */
488a854286Sbostic 
498a854286Sbostic #ifndef DAYSPERNYEAR
508a854286Sbostic #define DAYSPERNYEAR	365
518a854286Sbostic #endif /* !defined DAYSPERNYEAR */
528a854286Sbostic 
538a854286Sbostic extern char **	environ;
548a854286Sbostic extern int	getopt();
558a854286Sbostic extern char *	malloc();
568a854286Sbostic extern char *	optarg;
578a854286Sbostic extern int	optind;
588a854286Sbostic extern void	tzset();
598a854286Sbostic 
608a854286Sbostic char *		tzname[2];
618a854286Sbostic 
628a854286Sbostic static int	longest;
638a854286Sbostic static void	show();
648a854286Sbostic static void	hunt();
658a854286Sbostic static long	delta();
66*0b8b3d5aSbostic static char *	ecpyalloc();
67*0b8b3d5aSbostic 
68*0b8b3d5aSbostic static char *	progname;
698a854286Sbostic 
708a854286Sbostic int
main(argc,argv)718a854286Sbostic main(argc, argv)
728a854286Sbostic int	argc;
738a854286Sbostic char *	argv[];
748a854286Sbostic {
758a854286Sbostic 	register int	i, c;
768a854286Sbostic 	register int	vflag;
778a854286Sbostic 	register char *	cutoff;
788a854286Sbostic 	register int	cutyear;
798a854286Sbostic 	register long	cuttime;
808a854286Sbostic 	time_t		now;
818a854286Sbostic 	time_t		t, newt;
828a854286Sbostic 	time_t		hibit;
838a854286Sbostic 	struct tm	tm, newtm;
848a854286Sbostic 
85*0b8b3d5aSbostic 	progname = argv[0];
868a854286Sbostic 	vflag = 0;
878a854286Sbostic 	cutoff = NULL;
888a854286Sbostic 	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
898a854286Sbostic 		if (c == 'v')
908a854286Sbostic 			vflag = 1;
918a854286Sbostic 		else	cutoff = optarg;
928a854286Sbostic 	if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) {
938a854286Sbostic 		(void) fprintf(stderr,
948a854286Sbostic 			"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n",
958a854286Sbostic 			argv[0], argv[0]);
968a854286Sbostic 		(void) exit(EXIT_FAILURE);
978a854286Sbostic 	}
988a854286Sbostic 	if (cutoff != NULL)
998a854286Sbostic 		cutyear = atoi(cutoff);
1008a854286Sbostic 	/*
1018a854286Sbostic 	** VERY approximate.
1028a854286Sbostic 	*/
1038a854286Sbostic 	cuttime = (long) (cutyear - EPOCH_YEAR) *
1048a854286Sbostic 		SECSPERHOUR * HOURSPERDAY * DAYSPERNYEAR;
1058a854286Sbostic 	(void) time(&now);
1068a854286Sbostic 	longest = 0;
1078a854286Sbostic 	for (i = optind; i < argc; ++i)
1088a854286Sbostic 		if (strlen(argv[i]) > longest)
1098a854286Sbostic 			longest = strlen(argv[i]);
1108a854286Sbostic 	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
1118a854286Sbostic 		;
1128a854286Sbostic 	for (i = optind; i < argc; ++i) {
1138a854286Sbostic 		register char **	saveenv;
1148a854286Sbostic 		char *			tzequals;
115*0b8b3d5aSbostic 		char *			ab;
1168a854286Sbostic 		char *			fakeenv[2];
1178a854286Sbostic 
1188a854286Sbostic 		tzequals = malloc((unsigned) (strlen(argv[i]) + 4));
1198a854286Sbostic 		if (tzequals == NULL) {
1208a854286Sbostic 			(void) fprintf(stderr, "%s: can't allocate memory\n",
1218a854286Sbostic 				argv[0]);
1228a854286Sbostic 			(void) exit(EXIT_FAILURE);
1238a854286Sbostic 		}
1248a854286Sbostic 		(void) sprintf(tzequals, "TZ=%s", argv[i]);
1258a854286Sbostic 		fakeenv[0] = tzequals;
1268a854286Sbostic 		fakeenv[1] = NULL;
1278a854286Sbostic 		saveenv = environ;
1288a854286Sbostic 		environ = fakeenv;
1298a854286Sbostic 		(void) tzset();
1308a854286Sbostic 		free(tzequals);
1318a854286Sbostic 		environ = saveenv;
1328a854286Sbostic 		show(argv[i], now, FALSE);
1338a854286Sbostic 		if (!vflag)
1348a854286Sbostic 			continue;
1358a854286Sbostic 		/*
1368a854286Sbostic 		** Get lowest value of t.
1378a854286Sbostic 		*/
1388a854286Sbostic 		t = hibit;
1398a854286Sbostic 		if (t > 0)		/* time_t is unsigned */
1408a854286Sbostic 			t = 0;
1418a854286Sbostic 		show(argv[i], t, TRUE);
1428a854286Sbostic 		t += SECSPERHOUR * HOURSPERDAY;
1438a854286Sbostic 		show(argv[i], t, TRUE);
1448a854286Sbostic 		tm = *localtime(&t);
145*0b8b3d5aSbostic 		ab = ecpyalloc(tzname[tm.tm_isdst]);
1468a854286Sbostic 		for ( ; ; ) {
1478a854286Sbostic 			if (cutoff != NULL && t >= cuttime)
1488a854286Sbostic 				break;
1498a854286Sbostic 			newt = t + SECSPERHOUR * 12;
1508a854286Sbostic 			if (cutoff != NULL && newt >= cuttime)
1518a854286Sbostic 				break;
1528a854286Sbostic 			if (newt <= t)
1538a854286Sbostic 				break;
1548a854286Sbostic 			newtm = *localtime(&newt);
1558a854286Sbostic 			if (delta(&newtm, &tm) != (newt - t) ||
156*0b8b3d5aSbostic 				newtm.tm_isdst != tm.tm_isdst ||
157*0b8b3d5aSbostic 				strcmp(tzname[newtm.tm_isdst], ab) != 0) {
1588a854286Sbostic 					hunt(argv[i], t, newt);
159*0b8b3d5aSbostic 					free(ab);
160*0b8b3d5aSbostic 					ab = ecpyalloc(tzname[newtm.tm_isdst]);
161*0b8b3d5aSbostic 			}
1628a854286Sbostic 			t = newt;
1638a854286Sbostic 			tm = newtm;
1648a854286Sbostic 		}
1658a854286Sbostic 		/*
1668a854286Sbostic 		** Get highest value of t.
1678a854286Sbostic 		*/
1688a854286Sbostic 		t = ~((time_t) 0);
1698a854286Sbostic 		if (t < 0)		/* time_t is signed */
1708a854286Sbostic 			t &= ~hibit;
1718a854286Sbostic 		t -= SECSPERHOUR * HOURSPERDAY;
1728a854286Sbostic 		show(argv[i], t, TRUE);
1738a854286Sbostic 		t += SECSPERHOUR * HOURSPERDAY;
1748a854286Sbostic 		show(argv[i], t, TRUE);
1758a854286Sbostic 	}
1768a854286Sbostic 	if (fflush(stdout) || ferror(stdout)) {
1778a854286Sbostic 		(void) fprintf(stderr, "%s: Error writing standard output ",
1788a854286Sbostic 			argv[0]);
1798a854286Sbostic 		(void) perror("standard output");
1808a854286Sbostic 		(void) exit(EXIT_FAILURE);
1818a854286Sbostic 	}
1828a854286Sbostic 	exit(EXIT_SUCCESS);
1838a854286Sbostic 	for ( ; ; )
1848a854286Sbostic 		;
1858a854286Sbostic }
1868a854286Sbostic 
1878a854286Sbostic static void
hunt(name,lot,hit)1888a854286Sbostic hunt(name, lot, hit)
1898a854286Sbostic char *	name;
1908a854286Sbostic time_t	lot;
1918a854286Sbostic time_t	hit;
1928a854286Sbostic {
1938a854286Sbostic 	time_t		t;
1948a854286Sbostic 	struct tm	lotm;
1958a854286Sbostic 	struct tm	tm;
196*0b8b3d5aSbostic 	char *		loab;
1978a854286Sbostic 
1988a854286Sbostic 	lotm = *localtime(&lot);
199*0b8b3d5aSbostic 	loab = ecpyalloc(tzname[lotm.tm_isdst]);
2008a854286Sbostic 	while ((hit - lot) >= 2) {
2018a854286Sbostic 		t = lot / 2 + hit / 2;
2028a854286Sbostic 		if (t <= lot)
2038a854286Sbostic 			++t;
2048a854286Sbostic 		else if (t >= hit)
2058a854286Sbostic 			--t;
2068a854286Sbostic 		tm = *localtime(&t);
2078a854286Sbostic 		if (delta(&tm, &lotm) == (t - lot) &&
208*0b8b3d5aSbostic 			tm.tm_isdst == lotm.tm_isdst &&
209*0b8b3d5aSbostic 			strcmp(tzname[tm.tm_isdst], loab) == 0) {
2108a854286Sbostic 				lot = t;
2118a854286Sbostic 				lotm = tm;
2128a854286Sbostic 		} else	hit = t;
2138a854286Sbostic 	}
2148a854286Sbostic 	show(name, lot, TRUE);
2158a854286Sbostic 	show(name, hit, TRUE);
216*0b8b3d5aSbostic 	free(loab);
2178a854286Sbostic }
2188a854286Sbostic 
2198a854286Sbostic static long
delta(newp,oldp)2208a854286Sbostic delta(newp, oldp)
2218a854286Sbostic struct tm *	newp;
2228a854286Sbostic struct tm *	oldp;
2238a854286Sbostic {
2248a854286Sbostic 	long	result;
2258a854286Sbostic 
2268a854286Sbostic 	result = newp->tm_hour - oldp->tm_hour;
2278a854286Sbostic 	if (result < 0)
2288a854286Sbostic 		result += HOURSPERDAY;
2298a854286Sbostic 	result *= SECSPERHOUR;
2308a854286Sbostic 	result += (newp->tm_min - oldp->tm_min) * SECSPERMIN;
2318a854286Sbostic 	return result + newp->tm_sec - oldp->tm_sec;
2328a854286Sbostic }
2338a854286Sbostic 
2348a854286Sbostic static void
show(zone,t,v)2358a854286Sbostic show(zone, t, v)
2368a854286Sbostic char *	zone;
2378a854286Sbostic time_t	t;
2388a854286Sbostic int	v;
2398a854286Sbostic {
2408a854286Sbostic 	struct tm *		tmp;
2418a854286Sbostic 	extern struct tm *	localtime();
2428a854286Sbostic 
2438a854286Sbostic 	(void) printf("%-*s  ", longest, zone);
2448a854286Sbostic 	if (v)
2458a854286Sbostic 		(void) printf("%.24s GMT = ", asctime(gmtime(&t)));
2468a854286Sbostic 	tmp = localtime(&t);
2478a854286Sbostic 	(void) printf("%.24s", asctime(tmp));
2488a854286Sbostic 	if (tzname[tmp->tm_isdst] != NULL &&
2498a854286Sbostic 		*tzname[tmp->tm_isdst] != '\0')
2508a854286Sbostic 			(void) printf(" %s", tzname[tmp->tm_isdst]);
2518a854286Sbostic 	if (v) {
2528a854286Sbostic 		(void) printf(" isdst=%d", tmp->tm_isdst);
2538a854286Sbostic #ifdef TM_GMTOFF
2548a854286Sbostic 		(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
2558a854286Sbostic #endif /* defined TM_GMTOFF */
2568a854286Sbostic 	}
2578a854286Sbostic 	(void) printf("\n");
2588a854286Sbostic }
259*0b8b3d5aSbostic 
260*0b8b3d5aSbostic static char *
ecpyalloc(string)261*0b8b3d5aSbostic ecpyalloc(string)
262*0b8b3d5aSbostic char *	string;
263*0b8b3d5aSbostic {
264*0b8b3d5aSbostic 	register char *	result;
265*0b8b3d5aSbostic 	register int	length;
266*0b8b3d5aSbostic 
267*0b8b3d5aSbostic 	length = strlen(string);
268*0b8b3d5aSbostic 	result = malloc(length + 1);
269*0b8b3d5aSbostic 	if (result == 0) {
270*0b8b3d5aSbostic 		(void) fprintf(stderr, "%s: can't allocate memory\n", progname);
271*0b8b3d5aSbostic 		(void) exit(EXIT_FAILURE);
272*0b8b3d5aSbostic 	}
273*0b8b3d5aSbostic 	(void) strcpy(result, string);
274*0b8b3d5aSbostic 	return result;
275*0b8b3d5aSbostic }
276