xref: /csrg-svn/share/zoneinfo/DIST/zdump.c (revision 37207)
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