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