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