zdump.c revision 2702
12702Swollman#ifndef lint 22702Swollman#ifndef NOID 32702Swollmanstatic char elsieid[] = "@(#)zdump.c 7.10"; 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 132702Swollman#include "stdio.h" /* for stdout, stderr */ 142702Swollman#include "string.h" /* for strcpy */ 152702Swollman#include "sys/types.h" /* for time_t */ 162702Swollman#include "time.h" /* for struct tm */ 172702Swollman 182702Swollman#ifndef MAX_STRING_LENGTH 192702Swollman#define MAX_STRING_LENGTH 1024 202702Swollman#endif /* !defined MAX_STRING_LENGTH */ 212702Swollman 222702Swollman#ifndef TRUE 232702Swollman#define TRUE 1 242702Swollman#endif /* !defined TRUE */ 252702Swollman 262702Swollman#ifndef FALSE 272702Swollman#define FALSE 0 282702Swollman#endif /* !defined FALSE */ 292702Swollman 302702Swollman#ifndef EXIT_SUCCESS 312702Swollman#define EXIT_SUCCESS 0 322702Swollman#endif /* !defined EXIT_SUCCESS */ 332702Swollman 342702Swollman#ifndef EXIT_FAILURE 352702Swollman#define EXIT_FAILURE 1 362702Swollman#endif /* !defined EXIT_FAILURE */ 372702Swollman 382702Swollman#ifndef SECSPERMIN 392702Swollman#define SECSPERMIN 60 402702Swollman#endif /* !defined SECSPERMIN */ 412702Swollman 422702Swollman#ifndef MINSPERHOUR 432702Swollman#define MINSPERHOUR 60 442702Swollman#endif /* !defined MINSPERHOUR */ 452702Swollman 462702Swollman#ifndef SECSPERHOUR 472702Swollman#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) 482702Swollman#endif /* !defined SECSPERHOUR */ 492702Swollman 502702Swollman#ifndef HOURSPERDAY 512702Swollman#define HOURSPERDAY 24 522702Swollman#endif /* !defined HOURSPERDAY */ 532702Swollman 542702Swollman#ifndef EPOCH_YEAR 552702Swollman#define EPOCH_YEAR 1970 562702Swollman#endif /* !defined EPOCH_YEAR */ 572702Swollman 582702Swollman#ifndef TM_YEAR_BASE 592702Swollman#define TM_YEAR_BASE 1900 602702Swollman#endif /* !defined TM_YEAR_BASE */ 612702Swollman 622702Swollman#ifndef DAYSPERNYEAR 632702Swollman#define DAYSPERNYEAR 365 642702Swollman#endif /* !defined DAYSPERNYEAR */ 652702Swollman 662702Swollman#ifndef isleap 672702Swollman#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) 682702Swollman#endif /* !defined isleap */ 692702Swollman 702702Swollmanextern char ** environ; 712702Swollmanextern int getopt(); 722702Swollmanextern char * optarg; 732702Swollmanextern int optind; 742702Swollmanextern time_t time(); 752702Swollmanextern char * tzname[2]; 762702Swollmanextern void tzset(); 772702Swollman 782702Swollman#ifdef USG 792702Swollmanextern void exit(); 802702Swollmanextern void perror(); 812702Swollman#endif /* defined USG */ 822702Swollman 832702Swollmanstatic char * abbr(); 842702Swollmanstatic long delta(); 852702Swollmanstatic time_t hunt(); 862702Swollmanstatic int longest; 872702Swollmanstatic char * progname; 882702Swollmanstatic void show(); 892702Swollman 902702Swollmanint 912702Swollmanmain(argc, argv) 922702Swollmanint argc; 932702Swollmanchar * argv[]; 942702Swollman{ 952702Swollman register int i, c; 962702Swollman register int vflag; 972702Swollman register char * cutoff; 982702Swollman register int cutyear; 992702Swollman register long cuttime; 1002702Swollman time_t now; 1012702Swollman time_t t, newt; 1022702Swollman time_t hibit; 1032702Swollman struct tm tm, newtm; 1042702Swollman 1052702Swollman progname = argv[0]; 1062702Swollman vflag = 0; 1072702Swollman cutoff = NULL; 1082702Swollman while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 1092702Swollman if (c == 'v') 1102702Swollman vflag = 1; 1112702Swollman else cutoff = optarg; 1122702Swollman if (c != EOF || 1132702Swollman (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 1142702Swollman (void) fprintf(stderr, 1152702Swollman"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n", 1162702Swollman argv[0], argv[0]); 1172702Swollman (void) exit(EXIT_FAILURE); 1182702Swollman } 1192702Swollman if (cutoff != NULL) { 1202702Swollman int y; 1212702Swollman 1222702Swollman cutyear = atoi(cutoff); 1232702Swollman cuttime = 0; 1242702Swollman for (y = EPOCH_YEAR; y < cutyear; ++y) 1252702Swollman cuttime += DAYSPERNYEAR + isleap(y); 1262702Swollman cuttime *= SECSPERHOUR * HOURSPERDAY; 1272702Swollman } 1282702Swollman (void) time(&now); 1292702Swollman longest = 0; 1302702Swollman for (i = optind; i < argc; ++i) 1312702Swollman if (strlen(argv[i]) > longest) 1322702Swollman longest = strlen(argv[i]); 1332702Swollman for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) 1342702Swollman continue; 1352702Swollman for (i = optind; i < argc; ++i) { 1362702Swollman register char ** saveenv; 1372702Swollman static char buf[MAX_STRING_LENGTH]; 1382702Swollman char * fakeenv[2]; 1392702Swollman 1402702Swollman if (strlen(argv[i]) + 4 > sizeof buf) { 1412702Swollman (void) fflush(stdout); 1422702Swollman (void) fprintf(stderr, "%s: argument too long -- %s\n", 1432702Swollman progname, argv[i]); 1442702Swollman (void) exit(EXIT_FAILURE); 1452702Swollman } 1462702Swollman (void) strcpy(buf, "TZ="); 1472702Swollman (void) strcat(buf, argv[i]); 1482702Swollman fakeenv[0] = buf; 1492702Swollman fakeenv[1] = NULL; 1502702Swollman saveenv = environ; 1512702Swollman environ = fakeenv; 1522702Swollman (void) tzset(); 1532702Swollman environ = saveenv; 1542702Swollman show(argv[i], now, FALSE); 1552702Swollman if (!vflag) 1562702Swollman continue; 1572702Swollman /* 1582702Swollman ** Get lowest value of t. 1592702Swollman */ 1602702Swollman t = hibit; 1612702Swollman if (t > 0) /* time_t is unsigned */ 1622702Swollman t = 0; 1632702Swollman show(argv[i], t, TRUE); 1642702Swollman t += SECSPERHOUR * HOURSPERDAY; 1652702Swollman show(argv[i], t, TRUE); 1662702Swollman tm = *localtime(&t); 1672702Swollman (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); 1682702Swollman for ( ; ; ) { 1692702Swollman if (cutoff != NULL && t >= cuttime) 1702702Swollman break; 1712702Swollman newt = t + SECSPERHOUR * 12; 1722702Swollman if (cutoff != NULL && newt >= cuttime) 1732702Swollman break; 1742702Swollman if (newt <= t) 1752702Swollman break; 1762702Swollman newtm = *localtime(&newt); 1772702Swollman if (delta(&newtm, &tm) != (newt - t) || 1782702Swollman newtm.tm_isdst != tm.tm_isdst || 1792702Swollman strcmp(abbr(&newtm), buf) != 0) { 1802702Swollman newt = hunt(argv[i], t, newt); 1812702Swollman newtm = *localtime(&newt); 1822702Swollman (void) strncpy(buf, abbr(&newtm), 1832702Swollman (sizeof buf) - 1); 1842702Swollman } 1852702Swollman t = newt; 1862702Swollman tm = newtm; 1872702Swollman } 1882702Swollman /* 1892702Swollman ** Get highest value of t. 1902702Swollman */ 1912702Swollman t = ~((time_t) 0); 1922702Swollman if (t < 0) /* time_t is signed */ 1932702Swollman t &= ~hibit; 1942702Swollman t -= SECSPERHOUR * HOURSPERDAY; 1952702Swollman show(argv[i], t, TRUE); 1962702Swollman t += SECSPERHOUR * HOURSPERDAY; 1972702Swollman show(argv[i], t, TRUE); 1982702Swollman } 1992702Swollman if (fflush(stdout) || ferror(stdout)) { 2002702Swollman (void) fprintf(stderr, "%s: Error writing standard output ", 2012702Swollman argv[0]); 2022702Swollman (void) perror("standard output"); 2032702Swollman (void) exit(EXIT_FAILURE); 2042702Swollman } 2052702Swollman exit(EXIT_SUCCESS); 2062702Swollman 2072702Swollman /* gcc -Wall pacifier */ 2082702Swollman for ( ; ; ) 2092702Swollman continue; 2102702Swollman} 2112702Swollman 2122702Swollmanstatic time_t 2132702Swollmanhunt(name, lot, hit) 2142702Swollmanchar * name; 2152702Swollmantime_t lot; 2162702Swollmantime_t hit; 2172702Swollman{ 2182702Swollman time_t t; 2192702Swollman struct tm lotm; 2202702Swollman struct tm tm; 2212702Swollman static char loab[MAX_STRING_LENGTH]; 2222702Swollman 2232702Swollman lotm = *localtime(&lot); 2242702Swollman (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); 2252702Swollman while ((hit - lot) >= 2) { 2262702Swollman t = lot / 2 + hit / 2; 2272702Swollman if (t <= lot) 2282702Swollman ++t; 2292702Swollman else if (t >= hit) 2302702Swollman --t; 2312702Swollman tm = *localtime(&t); 2322702Swollman if (delta(&tm, &lotm) == (t - lot) && 2332702Swollman tm.tm_isdst == lotm.tm_isdst && 2342702Swollman strcmp(abbr(&tm), loab) == 0) { 2352702Swollman lot = t; 2362702Swollman lotm = tm; 2372702Swollman } else hit = t; 2382702Swollman } 2392702Swollman show(name, lot, TRUE); 2402702Swollman show(name, hit, TRUE); 2412702Swollman return hit; 2422702Swollman} 2432702Swollman 2442702Swollman/* 2452702Swollman** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. 2462702Swollman*/ 2472702Swollman 2482702Swollmanstatic long 2492702Swollmandelta(newp, oldp) 2502702Swollmanstruct tm * newp; 2512702Swollmanstruct tm * oldp; 2522702Swollman{ 2532702Swollman long result; 2542702Swollman int tmy; 2552702Swollman 2562702Swollman if (newp->tm_year < oldp->tm_year) 2572702Swollman return -delta(oldp, newp); 2582702Swollman result = 0; 2592702Swollman for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) 2602702Swollman result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE); 2612702Swollman result += newp->tm_yday - oldp->tm_yday; 2622702Swollman result *= HOURSPERDAY; 2632702Swollman result += newp->tm_hour - oldp->tm_hour; 2642702Swollman result *= MINSPERHOUR; 2652702Swollman result += newp->tm_min - oldp->tm_min; 2662702Swollman result *= SECSPERMIN; 2672702Swollman result += newp->tm_sec - oldp->tm_sec; 2682702Swollman return result; 2692702Swollman} 2702702Swollman 2712702Swollmanstatic void 2722702Swollmanshow(zone, t, v) 2732702Swollmanchar * zone; 2742702Swollmantime_t t; 2752702Swollmanint v; 2762702Swollman{ 2772702Swollman struct tm * tmp; 2782702Swollman extern struct tm * localtime(); 2792702Swollman 2802702Swollman (void) printf("%-*s ", longest, zone); 2812702Swollman if (v) 2822702Swollman (void) printf("%.24s GMT = ", asctime(gmtime(&t))); 2832702Swollman tmp = localtime(&t); 2842702Swollman (void) printf("%.24s", asctime(tmp)); 2852702Swollman if (*abbr(tmp) != '\0') 2862702Swollman (void) printf(" %s", abbr(tmp)); 2872702Swollman if (v) { 2882702Swollman (void) printf(" isdst=%d", tmp->tm_isdst); 2892702Swollman#ifdef TM_GMTOFF 2902702Swollman (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); 2912702Swollman#endif /* defined TM_GMTOFF */ 2922702Swollman } 2932702Swollman (void) printf("\n"); 2942702Swollman} 2952702Swollman 2962702Swollmanstatic char * 2972702Swollmanabbr(tmp) 2982702Swollmanstruct tm * tmp; 2992702Swollman{ 3002702Swollman register char * result; 3012702Swollman static char nada[1]; 3022702Swollman 3032702Swollman if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) 3042702Swollman return nada; 3052702Swollman result = tzname[tmp->tm_isdst]; 3062702Swollman return (result == NULL) ? nada : result; 3072702Swollman} 308