zdump.c revision 9937
12702Swollman#ifndef lint 22702Swollman#ifndef NOID 39937Swollmanstatic char elsieid[] = "@(#)zdump.c 7.20"; 42702Swollman#endif /* !defined NOID */ 52702Swollman#endif /* !defined lint */ 62702Swollman 72702Swollman/* 82702Swollman** This code has been made independent of the rest of the time 92702Swollman** conversion package to increase confidence in the verification it provides. 102702Swollman** You can use this code to help in verifying other implementations. 112702Swollman*/ 122702Swollman 139937Swollman#include "stdio.h" /* for stdout, stderr, perror */ 142702Swollman#include "string.h" /* for strcpy */ 152702Swollman#include "sys/types.h" /* for time_t */ 162702Swollman#include "time.h" /* for struct tm */ 179937Swollman#include "stdlib.h" /* for exit, malloc, atoi */ 182702Swollman 192702Swollman#ifndef MAX_STRING_LENGTH 202702Swollman#define MAX_STRING_LENGTH 1024 212702Swollman#endif /* !defined MAX_STRING_LENGTH */ 222702Swollman 232702Swollman#ifndef TRUE 242702Swollman#define TRUE 1 252702Swollman#endif /* !defined TRUE */ 262702Swollman 272702Swollman#ifndef FALSE 282702Swollman#define FALSE 0 292702Swollman#endif /* !defined FALSE */ 302702Swollman 312702Swollman#ifndef EXIT_SUCCESS 322702Swollman#define EXIT_SUCCESS 0 332702Swollman#endif /* !defined EXIT_SUCCESS */ 342702Swollman 352702Swollman#ifndef EXIT_FAILURE 362702Swollman#define EXIT_FAILURE 1 372702Swollman#endif /* !defined EXIT_FAILURE */ 382702Swollman 392702Swollman#ifndef SECSPERMIN 402702Swollman#define SECSPERMIN 60 412702Swollman#endif /* !defined SECSPERMIN */ 422702Swollman 432702Swollman#ifndef MINSPERHOUR 442702Swollman#define MINSPERHOUR 60 452702Swollman#endif /* !defined MINSPERHOUR */ 462702Swollman 472702Swollman#ifndef SECSPERHOUR 482702Swollman#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 492702Swollman#endif /* !defined SECSPERHOUR */ 502702Swollman 512702Swollman#ifndef HOURSPERDAY 522702Swollman#define HOURSPERDAY 24 532702Swollman#endif /* !defined HOURSPERDAY */ 542702Swollman 552702Swollman#ifndef EPOCH_YEAR 562702Swollman#define EPOCH_YEAR 1970 572702Swollman#endif /* !defined EPOCH_YEAR */ 582702Swollman 592702Swollman#ifndef TM_YEAR_BASE 602702Swollman#define TM_YEAR_BASE 1900 612702Swollman#endif /* !defined TM_YEAR_BASE */ 622702Swollman 632702Swollman#ifndef DAYSPERNYEAR 642702Swollman#define DAYSPERNYEAR 365 652702Swollman#endif /* !defined DAYSPERNYEAR */ 662702Swollman 672702Swollman#ifndef isleap 682702Swollman#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) 692702Swollman#endif /* !defined isleap */ 702702Swollman 719937Swollman#ifndef GNUC_or_lint 729937Swollman#ifdef lint 739937Swollman#define GNUC_or_lint 749937Swollman#endif /* defined lint */ 759937Swollman#ifndef lint 769937Swollman#ifdef __GNUC__ 779937Swollman#define GNUC_or_lint 789937Swollman#endif /* defined __GNUC__ */ 799937Swollman#endif /* !defined lint */ 809937Swollman#endif /* !defined GNUC_or_lint */ 819937Swollman 829937Swollman#ifndef INITIALIZE 839937Swollman#ifdef GNUC_or_lint 849937Swollman#define INITIALIZE(x) ((x) = 0) 859937Swollman#endif /* defined GNUC_or_lint */ 869937Swollman#ifndef GNUC_or_lint 879937Swollman#define INITIALIZE(x) 889937Swollman#endif /* !defined GNUC_or_lint */ 899937Swollman#endif /* !defined INITIALIZE */ 909937Swollman 912702Swollmanextern char ** environ; 922702Swollmanextern int getopt(); 932702Swollmanextern char * optarg; 942702Swollmanextern int optind; 952702Swollmanextern time_t time(); 962702Swollmanextern char * tzname[2]; 972702Swollman 982702Swollmanstatic char * abbr(); 992702Swollmanstatic long delta(); 1002702Swollmanstatic time_t hunt(); 1012702Swollmanstatic int longest; 1022702Swollmanstatic char * progname; 1032702Swollmanstatic void show(); 1042702Swollman 1052702Swollmanint 1062702Swollmanmain(argc, argv) 1072702Swollmanint argc; 1082702Swollmanchar * argv[]; 1092702Swollman{ 1109937Swollman register int i; 1119937Swollman register int c; 1129937Swollman register int vflag; 1139937Swollman register char * cutoff; 1149937Swollman register int cutyear; 1159937Swollman register long cuttime; 1169937Swollman char ** fakeenv; 1179937Swollman time_t now; 1189937Swollman time_t t; 1199937Swollman time_t newt; 1209937Swollman time_t hibit; 1219937Swollman struct tm tm; 1229937Swollman struct tm newtm; 1232702Swollman 1249937Swollman INITIALIZE(cuttime); 1252702Swollman progname = argv[0]; 1262702Swollman vflag = 0; 1272702Swollman cutoff = NULL; 1282702Swollman while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 1292702Swollman if (c == 'v') 1302702Swollman vflag = 1; 1312702Swollman else cutoff = optarg; 1322702Swollman if (c != EOF || 1332702Swollman (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 1342702Swollman (void) fprintf(stderr, 1352702Swollman"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n", 1362702Swollman argv[0], argv[0]); 1372702Swollman (void) exit(EXIT_FAILURE); 1382702Swollman } 1392702Swollman if (cutoff != NULL) { 1402702Swollman int y; 1412702Swollman 1422702Swollman cutyear = atoi(cutoff); 1432702Swollman cuttime = 0; 1442702Swollman for (y = EPOCH_YEAR; y < cutyear; ++y) 1452702Swollman cuttime += DAYSPERNYEAR + isleap(y); 1462702Swollman cuttime *= SECSPERHOUR * HOURSPERDAY; 1472702Swollman } 1482702Swollman (void) time(&now); 1492702Swollman longest = 0; 1502702Swollman for (i = optind; i < argc; ++i) 1512702Swollman if (strlen(argv[i]) > longest) 1522702Swollman longest = strlen(argv[i]); 1532702Swollman for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) 1542702Swollman continue; 1559937Swollman { 1569937Swollman register int from; 1579937Swollman register int to; 1582702Swollman 1599937Swollman for (i = 0; environ[i] != NULL; ++i) 1609937Swollman continue; 1619937Swollman fakeenv = (char **) malloc((size_t) ((i + 2) * 1629937Swollman sizeof *fakeenv)); 1639937Swollman if (fakeenv == NULL || 1649937Swollman (fakeenv[0] = (char *) malloc((size_t) (longest + 1659937Swollman 4))) == NULL) { 1669937Swollman (void) perror(progname); 1679937Swollman (void) exit(EXIT_FAILURE); 1682702Swollman } 1699937Swollman to = 0; 1709937Swollman (void) strcpy(fakeenv[to++], "TZ="); 1719937Swollman for (from = 0; environ[from] != NULL; ++from) 1729937Swollman if (strncmp(environ[from], "TZ=", 3) != 0) 1739937Swollman fakeenv[to++] = environ[from]; 1749937Swollman fakeenv[to] = NULL; 1752702Swollman environ = fakeenv; 1769937Swollman } 1779937Swollman for (i = optind; i < argc; ++i) { 1789937Swollman static char buf[MAX_STRING_LENGTH]; 1799937Swollman 1809937Swollman (void) strcpy(&fakeenv[0][3], argv[i]); 1812702Swollman show(argv[i], now, FALSE); 1822702Swollman if (!vflag) 1832702Swollman continue; 1842702Swollman /* 1852702Swollman ** Get lowest value of t. 1862702Swollman */ 1872702Swollman t = hibit; 1882702Swollman if (t > 0) /* time_t is unsigned */ 1892702Swollman t = 0; 1902702Swollman show(argv[i], t, TRUE); 1912702Swollman t += SECSPERHOUR * HOURSPERDAY; 1922702Swollman show(argv[i], t, TRUE); 1932702Swollman tm = *localtime(&t); 1942702Swollman (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); 1952702Swollman for ( ; ; ) { 1962702Swollman if (cutoff != NULL && t >= cuttime) 1972702Swollman break; 1982702Swollman newt = t + SECSPERHOUR * 12; 1992702Swollman if (cutoff != NULL && newt >= cuttime) 2002702Swollman break; 2012702Swollman if (newt <= t) 2022702Swollman break; 2032702Swollman newtm = *localtime(&newt); 2042702Swollman if (delta(&newtm, &tm) != (newt - t) || 2052702Swollman newtm.tm_isdst != tm.tm_isdst || 2062702Swollman strcmp(abbr(&newtm), buf) != 0) { 2072702Swollman newt = hunt(argv[i], t, newt); 2082702Swollman newtm = *localtime(&newt); 2092702Swollman (void) strncpy(buf, abbr(&newtm), 2102702Swollman (sizeof buf) - 1); 2112702Swollman } 2122702Swollman t = newt; 2132702Swollman tm = newtm; 2142702Swollman } 2152702Swollman /* 2162702Swollman ** Get highest value of t. 2172702Swollman */ 2182702Swollman t = ~((time_t) 0); 2192702Swollman if (t < 0) /* time_t is signed */ 2202702Swollman t &= ~hibit; 2212702Swollman t -= SECSPERHOUR * HOURSPERDAY; 2222702Swollman show(argv[i], t, TRUE); 2232702Swollman t += SECSPERHOUR * HOURSPERDAY; 2242702Swollman show(argv[i], t, TRUE); 2252702Swollman } 2262702Swollman if (fflush(stdout) || ferror(stdout)) { 2272702Swollman (void) fprintf(stderr, "%s: Error writing standard output ", 2282702Swollman argv[0]); 2292702Swollman (void) perror("standard output"); 2302702Swollman (void) exit(EXIT_FAILURE); 2312702Swollman } 2322702Swollman exit(EXIT_SUCCESS); 2332702Swollman 2342702Swollman /* gcc -Wall pacifier */ 2352702Swollman for ( ; ; ) 2362702Swollman continue; 2372702Swollman} 2382702Swollman 2392702Swollmanstatic time_t 2402702Swollmanhunt(name, lot, hit) 2412702Swollmanchar * name; 2422702Swollmantime_t lot; 2432702Swollmantime_t hit; 2442702Swollman{ 2452702Swollman time_t t; 2462702Swollman struct tm lotm; 2472702Swollman struct tm tm; 2482702Swollman static char loab[MAX_STRING_LENGTH]; 2492702Swollman 2502702Swollman lotm = *localtime(&lot); 2512702Swollman (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); 2522702Swollman while ((hit - lot) >= 2) { 2532702Swollman t = lot / 2 + hit / 2; 2542702Swollman if (t <= lot) 2552702Swollman ++t; 2562702Swollman else if (t >= hit) 2572702Swollman --t; 2582702Swollman tm = *localtime(&t); 2592702Swollman if (delta(&tm, &lotm) == (t - lot) && 2602702Swollman tm.tm_isdst == lotm.tm_isdst && 2612702Swollman strcmp(abbr(&tm), loab) == 0) { 2622702Swollman lot = t; 2632702Swollman lotm = tm; 2642702Swollman } else hit = t; 2652702Swollman } 2662702Swollman show(name, lot, TRUE); 2672702Swollman show(name, hit, TRUE); 2682702Swollman return hit; 2692702Swollman} 2702702Swollman 2712702Swollman/* 2722702Swollman** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. 2732702Swollman*/ 2742702Swollman 2752702Swollmanstatic long 2762702Swollmandelta(newp, oldp) 2772702Swollmanstruct tm * newp; 2782702Swollmanstruct tm * oldp; 2792702Swollman{ 2802702Swollman long result; 2812702Swollman int tmy; 2822702Swollman 2832702Swollman if (newp->tm_year < oldp->tm_year) 2842702Swollman return -delta(oldp, newp); 2852702Swollman result = 0; 2862702Swollman for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) 2872702Swollman result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE); 2882702Swollman result += newp->tm_yday - oldp->tm_yday; 2892702Swollman result *= HOURSPERDAY; 2902702Swollman result += newp->tm_hour - oldp->tm_hour; 2912702Swollman result *= MINSPERHOUR; 2922702Swollman result += newp->tm_min - oldp->tm_min; 2932702Swollman result *= SECSPERMIN; 2942702Swollman result += newp->tm_sec - oldp->tm_sec; 2952702Swollman return result; 2962702Swollman} 2972702Swollman 2989937Swollmanextern struct tm * localtime(); 2999937Swollman 3002702Swollmanstatic void 3012702Swollmanshow(zone, t, v) 3022702Swollmanchar * zone; 3032702Swollmantime_t t; 3042702Swollmanint v; 3052702Swollman{ 3069937Swollman struct tm * tmp; 3072702Swollman 3082702Swollman (void) printf("%-*s ", longest, zone); 3092702Swollman if (v) 3102702Swollman (void) printf("%.24s GMT = ", asctime(gmtime(&t))); 3112702Swollman tmp = localtime(&t); 3122702Swollman (void) printf("%.24s", asctime(tmp)); 3132702Swollman if (*abbr(tmp) != '\0') 3142702Swollman (void) printf(" %s", abbr(tmp)); 3152702Swollman if (v) { 3162702Swollman (void) printf(" isdst=%d", tmp->tm_isdst); 3172702Swollman#ifdef TM_GMTOFF 3182702Swollman (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); 3192702Swollman#endif /* defined TM_GMTOFF */ 3202702Swollman } 3212702Swollman (void) printf("\n"); 3222702Swollman} 3232702Swollman 3242702Swollmanstatic char * 3252702Swollmanabbr(tmp) 3262702Swollmanstruct tm * tmp; 3272702Swollman{ 3282702Swollman register char * result; 3299937Swollman static char nada; 3302702Swollman 3312702Swollman if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) 3329937Swollman return &nada; 3332702Swollman result = tzname[tmp->tm_isdst]; 3349937Swollman return (result == NULL) ? &nada : result; 3352702Swollman} 336