xref: /illumos-gate/usr/src/cmd/zdump/zdump.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1986-2002 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * zdump 7.24
29*7c478bd9Sstevel@tonic-gate  * Taken from elsie.nci.nih.gov to replace the existing Solaris zdump,
30*7c478bd9Sstevel@tonic-gate  * which was based on an earlier version of the elsie code.
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * For zdump 7.24, the following changes were made to the elsie code:
33*7c478bd9Sstevel@tonic-gate  *   locale/textdomain/messages to match existing Solaris style.
34*7c478bd9Sstevel@tonic-gate  *   Solaris verbose mode is documented to display the current time first.
35*7c478bd9Sstevel@tonic-gate  *   cstyle cleaned code.
36*7c478bd9Sstevel@tonic-gate  *   removed old locale/textdomain code.
37*7c478bd9Sstevel@tonic-gate  */
38*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /* static char	elsieid[] = "@(#)zdump.c	7.28"; */
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * This code has been made independent of the rest of the time
44*7c478bd9Sstevel@tonic-gate  * conversion package to increase confidence in the verification it provides.
45*7c478bd9Sstevel@tonic-gate  * You can use this code to help in verifying other implementations.
46*7c478bd9Sstevel@tonic-gate  */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #include "stdio.h"	/* for stdout, stderr, perror */
49*7c478bd9Sstevel@tonic-gate #include "string.h"	/* for strcpy */
50*7c478bd9Sstevel@tonic-gate #include "sys/types.h"	/* for time_t */
51*7c478bd9Sstevel@tonic-gate #include "time.h"	/* for struct tm */
52*7c478bd9Sstevel@tonic-gate #include "stdlib.h"	/* for exit, malloc, atoi */
53*7c478bd9Sstevel@tonic-gate #include "locale.h"	/* for setlocale, textdomain */
54*7c478bd9Sstevel@tonic-gate #include "libintl.h"
55*7c478bd9Sstevel@tonic-gate #include "tzfile.h"	/* for defines */
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #ifndef MAX_STRING_LENGTH
58*7c478bd9Sstevel@tonic-gate #define	MAX_STRING_LENGTH	1024
59*7c478bd9Sstevel@tonic-gate #endif /* !defined MAX_STRING_LENGTH */
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate #ifndef TRUE
62*7c478bd9Sstevel@tonic-gate #define	TRUE		1
63*7c478bd9Sstevel@tonic-gate #endif /* !defined TRUE */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #ifndef FALSE
66*7c478bd9Sstevel@tonic-gate #define	FALSE		0
67*7c478bd9Sstevel@tonic-gate #endif /* !defined FALSE */
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate #ifndef INITIALIZE
70*7c478bd9Sstevel@tonic-gate #ifdef lint
71*7c478bd9Sstevel@tonic-gate #define	INITIALIZE(x)	((x) = 0)
72*7c478bd9Sstevel@tonic-gate #endif /* defined lint */
73*7c478bd9Sstevel@tonic-gate #ifndef lint
74*7c478bd9Sstevel@tonic-gate #define	INITIALIZE(x)
75*7c478bd9Sstevel@tonic-gate #endif /* !defined lint */
76*7c478bd9Sstevel@tonic-gate #endif /* !defined INITIALIZE */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate extern char **	environ;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate static char *	abbr(struct tm *);
81*7c478bd9Sstevel@tonic-gate static long	delta(struct tm *, struct tm *);
82*7c478bd9Sstevel@tonic-gate static time_t	hunt(char *, time_t, time_t);
83*7c478bd9Sstevel@tonic-gate static size_t	longest;
84*7c478bd9Sstevel@tonic-gate static char *	progname;
85*7c478bd9Sstevel@tonic-gate static void	show(char *, time_t, int);
86*7c478bd9Sstevel@tonic-gate static void	usage(char *);
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate int
89*7c478bd9Sstevel@tonic-gate main(argc, argv)
90*7c478bd9Sstevel@tonic-gate int	argc;
91*7c478bd9Sstevel@tonic-gate char *	argv[];
92*7c478bd9Sstevel@tonic-gate {
93*7c478bd9Sstevel@tonic-gate 	register int		i;
94*7c478bd9Sstevel@tonic-gate 	register int		c;
95*7c478bd9Sstevel@tonic-gate 	register int		vflag;
96*7c478bd9Sstevel@tonic-gate 	register char *		cutoff;
97*7c478bd9Sstevel@tonic-gate 	register int		cutyear;
98*7c478bd9Sstevel@tonic-gate 	register long		cuttime;
99*7c478bd9Sstevel@tonic-gate 	char **			fakeenv;
100*7c478bd9Sstevel@tonic-gate 	time_t			now;
101*7c478bd9Sstevel@tonic-gate 	time_t			t;
102*7c478bd9Sstevel@tonic-gate 	time_t			newt;
103*7c478bd9Sstevel@tonic-gate 	time_t			hibit;
104*7c478bd9Sstevel@tonic-gate 	struct tm		tm;
105*7c478bd9Sstevel@tonic-gate 	struct tm		newtm;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	INITIALIZE(cuttime);
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
110*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
111*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
112*7c478bd9Sstevel@tonic-gate #endif
113*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	progname = argv[0];
116*7c478bd9Sstevel@tonic-gate 	vflag = 0;
117*7c478bd9Sstevel@tonic-gate 	cutoff = NULL;
118*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
119*7c478bd9Sstevel@tonic-gate 		if (c == 'v')
120*7c478bd9Sstevel@tonic-gate 			vflag = 1;
121*7c478bd9Sstevel@tonic-gate 		else	cutoff = optarg;
122*7c478bd9Sstevel@tonic-gate 	if (c != EOF ||
123*7c478bd9Sstevel@tonic-gate 		(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
124*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
125*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	if (cutoff != NULL) {
128*7c478bd9Sstevel@tonic-gate 		int	y;
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		cutyear = atoi(cutoff);
131*7c478bd9Sstevel@tonic-gate 		cuttime = 0;
132*7c478bd9Sstevel@tonic-gate 		for (y = EPOCH_YEAR; y < cutyear; ++y)
133*7c478bd9Sstevel@tonic-gate 			cuttime += DAYSPERNYEAR + isleap(y);
134*7c478bd9Sstevel@tonic-gate 		cuttime *= SECSPERHOUR * HOURSPERDAY;
135*7c478bd9Sstevel@tonic-gate 	}
136*7c478bd9Sstevel@tonic-gate 	(void) time(&now);
137*7c478bd9Sstevel@tonic-gate 	longest = 0;
138*7c478bd9Sstevel@tonic-gate 	for (i = optind; i < argc; ++i)
139*7c478bd9Sstevel@tonic-gate 		if (strlen(argv[i]) > longest)
140*7c478bd9Sstevel@tonic-gate 			longest = strlen(argv[i]);
141*7c478bd9Sstevel@tonic-gate 	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
142*7c478bd9Sstevel@tonic-gate 		continue;
143*7c478bd9Sstevel@tonic-gate 	{
144*7c478bd9Sstevel@tonic-gate 		register int	from;
145*7c478bd9Sstevel@tonic-gate 		register int	to;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		for (i = 0;  environ[i] != NULL;  ++i)
148*7c478bd9Sstevel@tonic-gate 			continue;
149*7c478bd9Sstevel@tonic-gate 		fakeenv = (char **) malloc((size_t) ((i + 2) *
150*7c478bd9Sstevel@tonic-gate 			sizeof (*fakeenv)));
151*7c478bd9Sstevel@tonic-gate 		if (fakeenv == NULL ||
152*7c478bd9Sstevel@tonic-gate 			(fakeenv[0] = (char *) malloc(longest + 4)) == NULL) {
153*7c478bd9Sstevel@tonic-gate 					(void) perror(progname);
154*7c478bd9Sstevel@tonic-gate 					(void) exit(EXIT_FAILURE);
155*7c478bd9Sstevel@tonic-gate 		}
156*7c478bd9Sstevel@tonic-gate 		to = 0;
157*7c478bd9Sstevel@tonic-gate 		(void) strcpy(fakeenv[to++], "TZ=");
158*7c478bd9Sstevel@tonic-gate 		for (from = 0; environ[from] != NULL; ++from)
159*7c478bd9Sstevel@tonic-gate 			if (strncmp(environ[from], "TZ=", 3) != 0)
160*7c478bd9Sstevel@tonic-gate 				fakeenv[to++] = environ[from];
161*7c478bd9Sstevel@tonic-gate 		fakeenv[to] = NULL;
162*7c478bd9Sstevel@tonic-gate 		environ = fakeenv;
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 	for (i = optind; i < argc; ++i) {
165*7c478bd9Sstevel@tonic-gate 		static char	buf[MAX_STRING_LENGTH];
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&fakeenv[0][3], argv[i]);
168*7c478bd9Sstevel@tonic-gate 		if (!vflag) {
169*7c478bd9Sstevel@tonic-gate 			show(argv[i], now, FALSE);
170*7c478bd9Sstevel@tonic-gate 			continue;
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate #if defined(sun)
174*7c478bd9Sstevel@tonic-gate 		/*
175*7c478bd9Sstevel@tonic-gate 		 * We show the current time first, probably because we froze
176*7c478bd9Sstevel@tonic-gate 		 * the behavior of zdump some time ago and then it got
177*7c478bd9Sstevel@tonic-gate 		 * changed.
178*7c478bd9Sstevel@tonic-gate 		 */
179*7c478bd9Sstevel@tonic-gate 		show(argv[i], now, TRUE);
180*7c478bd9Sstevel@tonic-gate #endif
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 		/*
183*7c478bd9Sstevel@tonic-gate 		 * Get lowest value of t.
184*7c478bd9Sstevel@tonic-gate 		 */
185*7c478bd9Sstevel@tonic-gate 		t = hibit;
186*7c478bd9Sstevel@tonic-gate 		if (t > 0)		/* time_t is unsigned */
187*7c478bd9Sstevel@tonic-gate 			t = 0;
188*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
189*7c478bd9Sstevel@tonic-gate 		t += SECSPERHOUR * HOURSPERDAY;
190*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
191*7c478bd9Sstevel@tonic-gate 		tm = *localtime(&t);
192*7c478bd9Sstevel@tonic-gate 		(void) strncpy(buf, abbr(&tm), (sizeof (buf)) - 1);
193*7c478bd9Sstevel@tonic-gate 		for (;;) {
194*7c478bd9Sstevel@tonic-gate 			if (cutoff != NULL && t >= cuttime)
195*7c478bd9Sstevel@tonic-gate 				break;
196*7c478bd9Sstevel@tonic-gate 			newt = t + SECSPERHOUR * 12;
197*7c478bd9Sstevel@tonic-gate 			if (cutoff != NULL && newt >= cuttime)
198*7c478bd9Sstevel@tonic-gate 				break;
199*7c478bd9Sstevel@tonic-gate 			if (newt <= t)
200*7c478bd9Sstevel@tonic-gate 				break;
201*7c478bd9Sstevel@tonic-gate 			newtm = *localtime(&newt);
202*7c478bd9Sstevel@tonic-gate 			if (delta(&newtm, &tm) != (newt - t) ||
203*7c478bd9Sstevel@tonic-gate 				newtm.tm_isdst != tm.tm_isdst ||
204*7c478bd9Sstevel@tonic-gate 				strcmp(abbr(&newtm), buf) != 0) {
205*7c478bd9Sstevel@tonic-gate 					newt = hunt(argv[i], t, newt);
206*7c478bd9Sstevel@tonic-gate 					newtm = *localtime(&newt);
207*7c478bd9Sstevel@tonic-gate 					(void) strncpy(buf, abbr(&newtm),
208*7c478bd9Sstevel@tonic-gate 						(sizeof (buf)) - 1);
209*7c478bd9Sstevel@tonic-gate 			}
210*7c478bd9Sstevel@tonic-gate 			t = newt;
211*7c478bd9Sstevel@tonic-gate 			tm = newtm;
212*7c478bd9Sstevel@tonic-gate 		}
213*7c478bd9Sstevel@tonic-gate 		/*
214*7c478bd9Sstevel@tonic-gate 		 * Get highest value of t.
215*7c478bd9Sstevel@tonic-gate 		 */
216*7c478bd9Sstevel@tonic-gate 		t = ~((time_t) 0);
217*7c478bd9Sstevel@tonic-gate 		if (t < 0)		/* time_t is signed */
218*7c478bd9Sstevel@tonic-gate 			t &= ~hibit;
219*7c478bd9Sstevel@tonic-gate #if defined(sun)
220*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
221*7c478bd9Sstevel@tonic-gate 		t -= SECSPERHOUR * HOURSPERDAY;
222*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
223*7c478bd9Sstevel@tonic-gate #else /* !defined(sun) */
224*7c478bd9Sstevel@tonic-gate 		t -= SECSPERHOUR * HOURSPERDAY;
225*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
226*7c478bd9Sstevel@tonic-gate 		t += SECSPERHOUR * HOURSPERDAY;
227*7c478bd9Sstevel@tonic-gate 		show(argv[i], t, TRUE);
228*7c478bd9Sstevel@tonic-gate #endif /* !defined(sun) */
229*7c478bd9Sstevel@tonic-gate 	}
230*7c478bd9Sstevel@tonic-gate 	if (fflush(stdout) || ferror(stdout)) {
231*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
232*7c478bd9Sstevel@tonic-gate 		    "%s: Error writing standard output "), argv[0]);
233*7c478bd9Sstevel@tonic-gate 		(void) perror(gettext("standard output"));
234*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 	return (EXIT_SUCCESS);
237*7c478bd9Sstevel@tonic-gate }
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate static time_t
240*7c478bd9Sstevel@tonic-gate hunt(name, lot, hit)
241*7c478bd9Sstevel@tonic-gate char *	name;
242*7c478bd9Sstevel@tonic-gate time_t	lot;
243*7c478bd9Sstevel@tonic-gate time_t	hit;
244*7c478bd9Sstevel@tonic-gate {
245*7c478bd9Sstevel@tonic-gate 	time_t		t;
246*7c478bd9Sstevel@tonic-gate 	struct tm	lotm;
247*7c478bd9Sstevel@tonic-gate 	struct tm	tm;
248*7c478bd9Sstevel@tonic-gate 	static char	loab[MAX_STRING_LENGTH];
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	lotm = *localtime(&lot);
251*7c478bd9Sstevel@tonic-gate 	(void) strncpy(loab, abbr(&lotm), (sizeof (loab)) - 1);
252*7c478bd9Sstevel@tonic-gate 	while ((hit - lot) >= 2) {
253*7c478bd9Sstevel@tonic-gate 		t = lot / 2 + hit / 2;
254*7c478bd9Sstevel@tonic-gate 		if (t <= lot)
255*7c478bd9Sstevel@tonic-gate 			++t;
256*7c478bd9Sstevel@tonic-gate 		else if (t >= hit)
257*7c478bd9Sstevel@tonic-gate 			--t;
258*7c478bd9Sstevel@tonic-gate 		tm = *localtime(&t);
259*7c478bd9Sstevel@tonic-gate 		if (delta(&tm, &lotm) == (t - lot) &&
260*7c478bd9Sstevel@tonic-gate 			tm.tm_isdst == lotm.tm_isdst &&
261*7c478bd9Sstevel@tonic-gate 			strcmp(abbr(&tm), loab) == 0) {
262*7c478bd9Sstevel@tonic-gate 				lot = t;
263*7c478bd9Sstevel@tonic-gate 				lotm = tm;
264*7c478bd9Sstevel@tonic-gate 		} else	hit = t;
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 	show(name, lot, TRUE);
267*7c478bd9Sstevel@tonic-gate 	show(name, hit, TRUE);
268*7c478bd9Sstevel@tonic-gate 	return (hit);
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate /*
272*7c478bd9Sstevel@tonic-gate  * Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
273*7c478bd9Sstevel@tonic-gate  */
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate static long
276*7c478bd9Sstevel@tonic-gate delta(newp, oldp)
277*7c478bd9Sstevel@tonic-gate struct tm *	newp;
278*7c478bd9Sstevel@tonic-gate struct tm *	oldp;
279*7c478bd9Sstevel@tonic-gate {
280*7c478bd9Sstevel@tonic-gate 	long	result;
281*7c478bd9Sstevel@tonic-gate 	int	tmy;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	if (newp->tm_year < oldp->tm_year)
284*7c478bd9Sstevel@tonic-gate 		return (-delta(oldp, newp));
285*7c478bd9Sstevel@tonic-gate 	result = 0;
286*7c478bd9Sstevel@tonic-gate 	for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
287*7c478bd9Sstevel@tonic-gate 		result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
288*7c478bd9Sstevel@tonic-gate 	result += newp->tm_yday - oldp->tm_yday;
289*7c478bd9Sstevel@tonic-gate 	result *= HOURSPERDAY;
290*7c478bd9Sstevel@tonic-gate 	result += newp->tm_hour - oldp->tm_hour;
291*7c478bd9Sstevel@tonic-gate 	result *= MINSPERHOUR;
292*7c478bd9Sstevel@tonic-gate 	result += newp->tm_min - oldp->tm_min;
293*7c478bd9Sstevel@tonic-gate 	result *= SECSPERMIN;
294*7c478bd9Sstevel@tonic-gate 	result += newp->tm_sec - oldp->tm_sec;
295*7c478bd9Sstevel@tonic-gate 	return (result);
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate static void
299*7c478bd9Sstevel@tonic-gate show(zone, t, v)
300*7c478bd9Sstevel@tonic-gate char *	zone;
301*7c478bd9Sstevel@tonic-gate time_t	t;
302*7c478bd9Sstevel@tonic-gate int	v;
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate 	struct tm *	tmp;
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*s  ", (int)longest, zone);
307*7c478bd9Sstevel@tonic-gate 	if (v)
308*7c478bd9Sstevel@tonic-gate 		(void) printf("%.24s UTC = ", asctime(gmtime(&t)));
309*7c478bd9Sstevel@tonic-gate 	tmp = localtime(&t);
310*7c478bd9Sstevel@tonic-gate 	(void) printf("%.24s", asctime(tmp));
311*7c478bd9Sstevel@tonic-gate 	if (*abbr(tmp) != '\0')
312*7c478bd9Sstevel@tonic-gate 		(void) printf(" %s", abbr(tmp));
313*7c478bd9Sstevel@tonic-gate 	if (v) {
314*7c478bd9Sstevel@tonic-gate 		(void) printf(" isdst=%d", tmp->tm_isdst);
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 	(void) printf("\n");
317*7c478bd9Sstevel@tonic-gate }
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate static char *
320*7c478bd9Sstevel@tonic-gate abbr(tmp)
321*7c478bd9Sstevel@tonic-gate struct tm *	tmp;
322*7c478bd9Sstevel@tonic-gate {
323*7c478bd9Sstevel@tonic-gate 	register char *	result;
324*7c478bd9Sstevel@tonic-gate 	static char	nada;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
327*7c478bd9Sstevel@tonic-gate 		return (&nada);
328*7c478bd9Sstevel@tonic-gate 	result = tzname[tmp->tm_isdst];
329*7c478bd9Sstevel@tonic-gate 	return ((result == NULL) ? &nada : result);
330*7c478bd9Sstevel@tonic-gate }
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate static void
333*7c478bd9Sstevel@tonic-gate usage(char *progname)
334*7c478bd9Sstevel@tonic-gate {
335*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
336*7c478bd9Sstevel@tonic-gate 	    "%s: [ -v ] [ -c cutoffyear ] [ zonename ... ]\n"), progname);
337*7c478bd9Sstevel@tonic-gate 	(void) exit(EXIT_FAILURE);
338*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
339*7c478bd9Sstevel@tonic-gate }
340