Home | History | Annotate | Line # | Download | only in time
zdump.c revision 1.10.12.1
      1  1.10.12.1   nathanw /*	$NetBSD: zdump.c,v 1.10.12.1 2002/03/08 21:36:55 nathanw Exp $	*/
      2        1.2       jtc 
      3        1.6  christos #include <sys/cdefs.h>
      4        1.1       jtc #ifndef lint
      5        1.1       jtc #ifndef NOID
      6        1.6  christos #if 0
      7  1.10.12.1   nathanw static char	elsieid[] = "@(#)zdump.c	7.29";
      8        1.6  christos #else
      9  1.10.12.1   nathanw __RCSID("$NetBSD: zdump.c,v 1.10.12.1 2002/03/08 21:36:55 nathanw Exp $");
     10        1.6  christos #endif
     11        1.1       jtc #endif /* !defined NOID */
     12        1.1       jtc #endif /* !defined lint */
     13        1.1       jtc 
     14        1.1       jtc /*
     15        1.1       jtc ** This code has been made independent of the rest of the time
     16        1.1       jtc ** conversion package to increase confidence in the verification it provides.
     17        1.1       jtc ** You can use this code to help in verifying other implementations.
     18        1.1       jtc */
     19        1.1       jtc 
     20        1.1       jtc #include "stdio.h"	/* for stdout, stderr, perror */
     21        1.1       jtc #include "string.h"	/* for strcpy */
     22        1.1       jtc #include "sys/types.h"	/* for time_t */
     23        1.1       jtc #include "time.h"	/* for struct tm */
     24        1.1       jtc #include "stdlib.h"	/* for exit, malloc, atoi */
     25        1.1       jtc 
     26        1.1       jtc #ifndef MAX_STRING_LENGTH
     27        1.1       jtc #define MAX_STRING_LENGTH	1024
     28        1.1       jtc #endif /* !defined MAX_STRING_LENGTH */
     29        1.1       jtc 
     30        1.1       jtc #ifndef TRUE
     31        1.1       jtc #define TRUE		1
     32        1.1       jtc #endif /* !defined TRUE */
     33        1.1       jtc 
     34        1.1       jtc #ifndef FALSE
     35        1.1       jtc #define FALSE		0
     36        1.1       jtc #endif /* !defined FALSE */
     37        1.1       jtc 
     38        1.1       jtc #ifndef EXIT_SUCCESS
     39        1.1       jtc #define EXIT_SUCCESS	0
     40        1.1       jtc #endif /* !defined EXIT_SUCCESS */
     41        1.1       jtc 
     42        1.1       jtc #ifndef EXIT_FAILURE
     43        1.1       jtc #define EXIT_FAILURE	1
     44        1.1       jtc #endif /* !defined EXIT_FAILURE */
     45        1.1       jtc 
     46        1.1       jtc #ifndef SECSPERMIN
     47        1.1       jtc #define SECSPERMIN	60
     48        1.1       jtc #endif /* !defined SECSPERMIN */
     49        1.1       jtc 
     50        1.1       jtc #ifndef MINSPERHOUR
     51        1.1       jtc #define MINSPERHOUR	60
     52        1.1       jtc #endif /* !defined MINSPERHOUR */
     53        1.1       jtc 
     54        1.1       jtc #ifndef SECSPERHOUR
     55        1.1       jtc #define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
     56        1.1       jtc #endif /* !defined SECSPERHOUR */
     57        1.1       jtc 
     58        1.1       jtc #ifndef HOURSPERDAY
     59        1.1       jtc #define HOURSPERDAY	24
     60        1.1       jtc #endif /* !defined HOURSPERDAY */
     61        1.1       jtc 
     62        1.1       jtc #ifndef EPOCH_YEAR
     63        1.1       jtc #define EPOCH_YEAR	1970
     64        1.1       jtc #endif /* !defined EPOCH_YEAR */
     65        1.1       jtc 
     66        1.1       jtc #ifndef TM_YEAR_BASE
     67        1.1       jtc #define TM_YEAR_BASE	1900
     68        1.1       jtc #endif /* !defined TM_YEAR_BASE */
     69        1.1       jtc 
     70        1.1       jtc #ifndef DAYSPERNYEAR
     71        1.1       jtc #define DAYSPERNYEAR	365
     72        1.1       jtc #endif /* !defined DAYSPERNYEAR */
     73        1.1       jtc 
     74        1.1       jtc #ifndef isleap
     75        1.1       jtc #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
     76        1.1       jtc #endif /* !defined isleap */
     77        1.1       jtc 
     78        1.3       jtc #if HAVE_GETTEXT - 0
     79        1.3       jtc #include "locale.h"	/* for setlocale */
     80        1.3       jtc #include "libintl.h"
     81        1.3       jtc #endif /* HAVE_GETTEXT - 0 */
     82        1.3       jtc 
     83        1.1       jtc #ifndef GNUC_or_lint
     84        1.1       jtc #ifdef lint
     85        1.1       jtc #define GNUC_or_lint
     86        1.1       jtc #endif /* defined lint */
     87        1.1       jtc #ifndef lint
     88        1.1       jtc #ifdef __GNUC__
     89        1.1       jtc #define GNUC_or_lint
     90        1.1       jtc #endif /* defined __GNUC__ */
     91        1.1       jtc #endif /* !defined lint */
     92        1.1       jtc #endif /* !defined GNUC_or_lint */
     93        1.1       jtc 
     94        1.1       jtc #ifndef INITIALIZE
     95        1.1       jtc #ifdef GNUC_or_lint
     96        1.1       jtc #define INITIALIZE(x)	((x) = 0)
     97        1.1       jtc #endif /* defined GNUC_or_lint */
     98        1.1       jtc #ifndef GNUC_or_lint
     99        1.1       jtc #define INITIALIZE(x)
    100        1.1       jtc #endif /* !defined GNUC_or_lint */
    101        1.1       jtc #endif /* !defined INITIALIZE */
    102        1.1       jtc 
    103        1.3       jtc /*
    104        1.3       jtc ** For the benefit of GNU folk...
    105        1.3       jtc ** `_(MSGID)' uses the current locale's message library string for MSGID.
    106        1.3       jtc ** The default is to use gettext if available, and use MSGID otherwise.
    107        1.3       jtc */
    108        1.3       jtc 
    109        1.3       jtc #ifndef _
    110        1.3       jtc #if HAVE_GETTEXT - 0
    111        1.3       jtc #define _(msgid) gettext(msgid)
    112        1.3       jtc #else /* !(HAVE_GETTEXT - 0) */
    113        1.3       jtc #define _(msgid) msgid
    114        1.3       jtc #endif /* !(HAVE_GETTEXT - 0) */
    115        1.3       jtc #endif /* !defined _ */
    116        1.3       jtc 
    117        1.3       jtc #ifndef TZ_DOMAIN
    118        1.3       jtc #define TZ_DOMAIN "tz"
    119        1.3       jtc #endif /* !defined TZ_DOMAIN */
    120        1.3       jtc 
    121        1.5       jtc #ifndef P
    122        1.5       jtc #ifdef __STDC__
    123        1.5       jtc #define P(x)	x
    124        1.5       jtc #endif /* defined __STDC__ */
    125        1.5       jtc #ifndef __STDC__
    126        1.5       jtc #define P(x)	()
    127        1.5       jtc #endif /* !defined __STDC__ */
    128        1.5       jtc #endif /* !defined P */
    129        1.5       jtc 
    130        1.1       jtc extern char **	environ;
    131        1.5       jtc extern int	getopt P((int argc, char * const argv[],
    132        1.5       jtc 			  const char * options));
    133        1.1       jtc extern char *	optarg;
    134        1.1       jtc extern int	optind;
    135        1.1       jtc 
    136        1.9   mycroft static const char *	abbr P((struct tm * tmp));
    137        1.5       jtc static long	delta P((struct tm * newp, struct tm * oldp));
    138        1.5       jtc static time_t	hunt P((char * name, time_t lot, time_t	hit));
    139        1.7     lukem int		main P((int, char **));
    140        1.5       jtc static size_t	longest;
    141        1.1       jtc static char *	progname;
    142        1.5       jtc static void	show P((char * zone, time_t t, int v));
    143        1.1       jtc 
    144        1.1       jtc int
    145        1.1       jtc main(argc, argv)
    146        1.1       jtc int	argc;
    147        1.1       jtc char *	argv[];
    148        1.1       jtc {
    149        1.1       jtc 	register int		i;
    150        1.1       jtc 	register int		c;
    151        1.1       jtc 	register int		vflag;
    152        1.1       jtc 	register char *		cutoff;
    153        1.1       jtc 	register int		cutyear;
    154        1.1       jtc 	register long		cuttime;
    155        1.1       jtc 	char **			fakeenv;
    156        1.1       jtc 	time_t			now;
    157        1.1       jtc 	time_t			t;
    158        1.1       jtc 	time_t			newt;
    159        1.1       jtc 	time_t			hibit;
    160        1.1       jtc 	struct tm		tm;
    161        1.1       jtc 	struct tm		newtm;
    162        1.1       jtc 
    163        1.1       jtc 	INITIALIZE(cuttime);
    164        1.3       jtc #if HAVE_GETTEXT - 0
    165        1.3       jtc 	(void) setlocale(LC_MESSAGES, "");
    166        1.3       jtc #ifdef TZ_DOMAINDIR
    167        1.3       jtc 	(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
    168        1.3       jtc #endif /* defined(TEXTDOMAINDIR) */
    169        1.3       jtc 	(void) textdomain(TZ_DOMAIN);
    170        1.3       jtc #endif /* HAVE_GETTEXT - 0 */
    171        1.1       jtc 	progname = argv[0];
    172        1.1       jtc 	vflag = 0;
    173        1.1       jtc 	cutoff = NULL;
    174        1.1       jtc 	while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
    175        1.1       jtc 		if (c == 'v')
    176        1.1       jtc 			vflag = 1;
    177        1.1       jtc 		else	cutoff = optarg;
    178        1.5       jtc 	if ((c != EOF && c != -1) ||
    179        1.1       jtc 		(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
    180        1.1       jtc 			(void) fprintf(stderr,
    181        1.3       jtc _("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
    182        1.1       jtc 				argv[0], argv[0]);
    183        1.1       jtc 			(void) exit(EXIT_FAILURE);
    184        1.1       jtc 	}
    185        1.1       jtc 	if (cutoff != NULL) {
    186        1.1       jtc 		int	y;
    187        1.1       jtc 
    188        1.1       jtc 		cutyear = atoi(cutoff);
    189        1.1       jtc 		cuttime = 0;
    190        1.1       jtc 		for (y = EPOCH_YEAR; y < cutyear; ++y)
    191        1.1       jtc 			cuttime += DAYSPERNYEAR + isleap(y);
    192        1.1       jtc 		cuttime *= SECSPERHOUR * HOURSPERDAY;
    193        1.1       jtc 	}
    194        1.1       jtc 	(void) time(&now);
    195        1.1       jtc 	longest = 0;
    196        1.1       jtc 	for (i = optind; i < argc; ++i)
    197        1.1       jtc 		if (strlen(argv[i]) > longest)
    198        1.1       jtc 			longest = strlen(argv[i]);
    199        1.1       jtc 	for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
    200        1.1       jtc 		continue;
    201        1.1       jtc 	{
    202        1.1       jtc 		register int	from;
    203        1.1       jtc 		register int	to;
    204        1.1       jtc 
    205        1.1       jtc 		for (i = 0;  environ[i] != NULL;  ++i)
    206        1.1       jtc 			continue;
    207        1.1       jtc 		fakeenv = (char **) malloc((size_t) ((i + 2) *
    208        1.1       jtc 			sizeof *fakeenv));
    209        1.1       jtc 		if (fakeenv == NULL ||
    210        1.5       jtc 			(fakeenv[0] = (char *) malloc(longest + 4)) == NULL) {
    211        1.1       jtc 					(void) perror(progname);
    212        1.1       jtc 					(void) exit(EXIT_FAILURE);
    213        1.1       jtc 		}
    214        1.1       jtc 		to = 0;
    215        1.4       mrg 		(void)strcpy(fakeenv[to++], "TZ=");	/* XXX strcpy is safe */
    216        1.1       jtc 		for (from = 0; environ[from] != NULL; ++from)
    217        1.1       jtc 			if (strncmp(environ[from], "TZ=", 3) != 0)
    218        1.1       jtc 				fakeenv[to++] = environ[from];
    219        1.1       jtc 		fakeenv[to] = NULL;
    220        1.1       jtc 		environ = fakeenv;
    221        1.1       jtc 	}
    222        1.1       jtc 	for (i = optind; i < argc; ++i) {
    223        1.1       jtc 		static char	buf[MAX_STRING_LENGTH];
    224        1.1       jtc 
    225        1.4       mrg 		(void) strcpy(&fakeenv[0][3], argv[i]);	/* XXX strcpy is safe */
    226        1.3       jtc 		if (!vflag) {
    227        1.3       jtc 			show(argv[i], now, FALSE);
    228        1.1       jtc 			continue;
    229        1.3       jtc 		}
    230        1.1       jtc 		/*
    231        1.1       jtc 		** Get lowest value of t.
    232        1.1       jtc 		*/
    233        1.1       jtc 		t = hibit;
    234        1.1       jtc 		if (t > 0)		/* time_t is unsigned */
    235        1.1       jtc 			t = 0;
    236        1.1       jtc 		show(argv[i], t, TRUE);
    237        1.1       jtc 		t += SECSPERHOUR * HOURSPERDAY;
    238        1.1       jtc 		show(argv[i], t, TRUE);
    239        1.1       jtc 		tm = *localtime(&t);
    240        1.1       jtc 		(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
    241        1.1       jtc 		for ( ; ; ) {
    242        1.1       jtc 			if (cutoff != NULL && t >= cuttime)
    243        1.1       jtc 				break;
    244        1.1       jtc 			newt = t + SECSPERHOUR * 12;
    245        1.1       jtc 			if (cutoff != NULL && newt >= cuttime)
    246        1.1       jtc 				break;
    247        1.1       jtc 			if (newt <= t)
    248        1.1       jtc 				break;
    249        1.1       jtc 			newtm = *localtime(&newt);
    250        1.1       jtc 			if (delta(&newtm, &tm) != (newt - t) ||
    251        1.1       jtc 				newtm.tm_isdst != tm.tm_isdst ||
    252        1.1       jtc 				strcmp(abbr(&newtm), buf) != 0) {
    253        1.1       jtc 					newt = hunt(argv[i], t, newt);
    254        1.1       jtc 					newtm = *localtime(&newt);
    255        1.1       jtc 					(void) strncpy(buf, abbr(&newtm),
    256        1.1       jtc 						(sizeof buf) - 1);
    257        1.1       jtc 			}
    258        1.1       jtc 			t = newt;
    259        1.1       jtc 			tm = newtm;
    260        1.1       jtc 		}
    261        1.1       jtc 		/*
    262        1.1       jtc 		** Get highest value of t.
    263        1.1       jtc 		*/
    264        1.1       jtc 		t = ~((time_t) 0);
    265        1.1       jtc 		if (t < 0)		/* time_t is signed */
    266        1.1       jtc 			t &= ~hibit;
    267        1.1       jtc 		t -= SECSPERHOUR * HOURSPERDAY;
    268        1.1       jtc 		show(argv[i], t, TRUE);
    269        1.1       jtc 		t += SECSPERHOUR * HOURSPERDAY;
    270        1.1       jtc 		show(argv[i], t, TRUE);
    271        1.1       jtc 	}
    272        1.1       jtc 	if (fflush(stdout) || ferror(stdout)) {
    273  1.10.12.1   nathanw 		(void) fprintf(stderr, "%s: ", argv[0]);
    274  1.10.12.1   nathanw 		(void) perror(_("Error writing standard output"));
    275        1.1       jtc 		(void) exit(EXIT_FAILURE);
    276        1.1       jtc 	}
    277        1.1       jtc 	exit(EXIT_SUCCESS);
    278        1.1       jtc 
    279        1.1       jtc 	/* gcc -Wall pacifier */
    280        1.1       jtc 	for ( ; ; )
    281        1.1       jtc 		continue;
    282        1.1       jtc }
    283        1.1       jtc 
    284        1.1       jtc static time_t
    285        1.1       jtc hunt(name, lot, hit)
    286        1.1       jtc char *	name;
    287        1.1       jtc time_t	lot;
    288        1.1       jtc time_t	hit;
    289        1.1       jtc {
    290        1.1       jtc 	time_t		t;
    291        1.1       jtc 	struct tm	lotm;
    292        1.1       jtc 	struct tm	tm;
    293        1.1       jtc 	static char	loab[MAX_STRING_LENGTH];
    294        1.1       jtc 
    295        1.1       jtc 	lotm = *localtime(&lot);
    296        1.1       jtc 	(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
    297        1.1       jtc 	while ((hit - lot) >= 2) {
    298        1.1       jtc 		t = lot / 2 + hit / 2;
    299        1.1       jtc 		if (t <= lot)
    300        1.1       jtc 			++t;
    301        1.1       jtc 		else if (t >= hit)
    302        1.1       jtc 			--t;
    303        1.1       jtc 		tm = *localtime(&t);
    304        1.1       jtc 		if (delta(&tm, &lotm) == (t - lot) &&
    305        1.1       jtc 			tm.tm_isdst == lotm.tm_isdst &&
    306        1.1       jtc 			strcmp(abbr(&tm), loab) == 0) {
    307        1.1       jtc 				lot = t;
    308        1.1       jtc 				lotm = tm;
    309        1.1       jtc 		} else	hit = t;
    310        1.1       jtc 	}
    311        1.1       jtc 	show(name, lot, TRUE);
    312        1.1       jtc 	show(name, hit, TRUE);
    313        1.1       jtc 	return hit;
    314        1.1       jtc }
    315        1.1       jtc 
    316        1.1       jtc /*
    317        1.1       jtc ** Thanks to Paul Eggert (eggert (at) twinsun.com) for logic used in delta.
    318        1.1       jtc */
    319        1.1       jtc 
    320        1.1       jtc static long
    321        1.1       jtc delta(newp, oldp)
    322        1.1       jtc struct tm *	newp;
    323        1.1       jtc struct tm *	oldp;
    324        1.1       jtc {
    325        1.1       jtc 	long	result;
    326        1.1       jtc 	int	tmy;
    327        1.1       jtc 
    328        1.1       jtc 	if (newp->tm_year < oldp->tm_year)
    329        1.1       jtc 		return -delta(oldp, newp);
    330        1.1       jtc 	result = 0;
    331        1.1       jtc 	for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
    332        1.1       jtc 		result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
    333        1.1       jtc 	result += newp->tm_yday - oldp->tm_yday;
    334        1.1       jtc 	result *= HOURSPERDAY;
    335        1.1       jtc 	result += newp->tm_hour - oldp->tm_hour;
    336        1.1       jtc 	result *= MINSPERHOUR;
    337        1.1       jtc 	result += newp->tm_min - oldp->tm_min;
    338        1.1       jtc 	result *= SECSPERMIN;
    339        1.1       jtc 	result += newp->tm_sec - oldp->tm_sec;
    340        1.1       jtc 	return result;
    341        1.1       jtc }
    342        1.1       jtc 
    343        1.1       jtc static void
    344        1.1       jtc show(zone, t, v)
    345        1.1       jtc char *	zone;
    346        1.1       jtc time_t	t;
    347        1.1       jtc int	v;
    348        1.1       jtc {
    349        1.1       jtc 	struct tm *	tmp;
    350        1.1       jtc 
    351        1.5       jtc 	(void) printf("%-*s  ", (int) longest, zone);
    352        1.1       jtc 	if (v)
    353        1.8       jtc 		(void) printf("%.24s UTC = ", asctime(gmtime(&t)));
    354        1.1       jtc 	tmp = localtime(&t);
    355        1.1       jtc 	(void) printf("%.24s", asctime(tmp));
    356        1.1       jtc 	if (*abbr(tmp) != '\0')
    357        1.1       jtc 		(void) printf(" %s", abbr(tmp));
    358        1.1       jtc 	if (v) {
    359        1.1       jtc 		(void) printf(" isdst=%d", tmp->tm_isdst);
    360        1.1       jtc #ifdef TM_GMTOFF
    361        1.1       jtc 		(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
    362        1.1       jtc #endif /* defined TM_GMTOFF */
    363        1.1       jtc 	}
    364        1.1       jtc 	(void) printf("\n");
    365        1.1       jtc }
    366        1.1       jtc 
    367        1.9   mycroft static const char *
    368        1.1       jtc abbr(tmp)
    369        1.1       jtc struct tm *	tmp;
    370        1.1       jtc {
    371        1.9   mycroft 	register const char *	result;
    372        1.9   mycroft 	static const char	nada;
    373        1.1       jtc 
    374        1.1       jtc 	if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
    375        1.1       jtc 		return &nada;
    376        1.1       jtc 	result = tzname[tmp->tm_isdst];
    377        1.1       jtc 	return (result == NULL) ? &nada : result;
    378        1.1       jtc }
    379