1*37206Sbostic #ifndef lint 2*37206Sbostic #ifndef NOID 3*37206Sbostic static char elsieid[] = "@(#)zdump.c 4.9"; 4*37206Sbostic #endif /* !defined NOID */ 5*37206Sbostic #endif /* !defined lint */ 6*37206Sbostic 7*37206Sbostic /* 8*37206Sbostic ** This code has been made entirely independent of the rest of the time 9*37206Sbostic ** conversion package to increase confidence in the verification it provides. 10*37206Sbostic ** You can use this code to help in verifying other implementations. 11*37206Sbostic */ 12*37206Sbostic 13*37206Sbostic #include <stdio.h> 14*37206Sbostic #include <time.h> 15*37206Sbostic #include <sys/types.h> 16*37206Sbostic 17*37206Sbostic #ifndef TRUE 18*37206Sbostic #define TRUE 1 19*37206Sbostic #endif /* !defined TRUE */ 20*37206Sbostic 21*37206Sbostic #ifndef FALSE 22*37206Sbostic #define FALSE 0 23*37206Sbostic #endif /* !defined TRUE */ 24*37206Sbostic 25*37206Sbostic #ifndef EXIT_SUCCESS 26*37206Sbostic #define EXIT_SUCCESS 0 27*37206Sbostic #endif /* !defined EXIT_SUCCESS */ 28*37206Sbostic 29*37206Sbostic #ifndef EXIT_FAILURE 30*37206Sbostic #define EXIT_FAILURE 1 31*37206Sbostic #endif /* !defined EXIT_FAILURE */ 32*37206Sbostic 33*37206Sbostic #ifndef SECSPERMIN 34*37206Sbostic #define SECSPERMIN 60 35*37206Sbostic #endif /* !defined SECSPERMIN */ 36*37206Sbostic 37*37206Sbostic #ifndef SECSPERHOUR 38*37206Sbostic #define SECSPERHOUR 3600 39*37206Sbostic #endif /* !defined SECSPERHOUR */ 40*37206Sbostic 41*37206Sbostic #ifndef HOURSPERDAY 42*37206Sbostic #define HOURSPERDAY 24 43*37206Sbostic #endif /* !defined HOURSPERDAY */ 44*37206Sbostic 45*37206Sbostic #ifndef EPOCH_YEAR 46*37206Sbostic #define EPOCH_YEAR 1970 47*37206Sbostic #endif /* !defined EPOCH_YEAR */ 48*37206Sbostic 49*37206Sbostic #ifndef DAYSPERNYEAR 50*37206Sbostic #define DAYSPERNYEAR 365 51*37206Sbostic #endif /* !defined DAYSPERNYEAR */ 52*37206Sbostic 53*37206Sbostic extern char ** environ; 54*37206Sbostic extern int getopt(); 55*37206Sbostic extern char * malloc(); 56*37206Sbostic extern char * optarg; 57*37206Sbostic extern int optind; 58*37206Sbostic extern void tzset(); 59*37206Sbostic 60*37206Sbostic char * tzname[2]; 61*37206Sbostic 62*37206Sbostic static int longest; 63*37206Sbostic static void show(); 64*37206Sbostic static void hunt(); 65*37206Sbostic static long delta(); 66*37206Sbostic 67*37206Sbostic int 68*37206Sbostic main(argc, argv) 69*37206Sbostic int argc; 70*37206Sbostic char * argv[]; 71*37206Sbostic { 72*37206Sbostic register int i, c; 73*37206Sbostic register int vflag; 74*37206Sbostic register char * cutoff; 75*37206Sbostic register int cutyear; 76*37206Sbostic register long cuttime; 77*37206Sbostic time_t now; 78*37206Sbostic time_t t, newt; 79*37206Sbostic time_t hibit; 80*37206Sbostic struct tm tm, newtm; 81*37206Sbostic 82*37206Sbostic vflag = 0; 83*37206Sbostic cutoff = NULL; 84*37206Sbostic while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 85*37206Sbostic if (c == 'v') 86*37206Sbostic vflag = 1; 87*37206Sbostic else cutoff = optarg; 88*37206Sbostic if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) { 89*37206Sbostic (void) fprintf(stderr, 90*37206Sbostic "%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n", 91*37206Sbostic argv[0], argv[0]); 92*37206Sbostic (void) exit(EXIT_FAILURE); 93*37206Sbostic } 94*37206Sbostic if (cutoff != NULL) 95*37206Sbostic cutyear = atoi(cutoff); 96*37206Sbostic /* 97*37206Sbostic ** VERY approximate. 98*37206Sbostic */ 99*37206Sbostic cuttime = (long) (cutyear - EPOCH_YEAR) * 100*37206Sbostic SECSPERHOUR * HOURSPERDAY * DAYSPERNYEAR; 101*37206Sbostic (void) time(&now); 102*37206Sbostic longest = 0; 103*37206Sbostic for (i = optind; i < argc; ++i) 104*37206Sbostic if (strlen(argv[i]) > longest) 105*37206Sbostic longest = strlen(argv[i]); 106*37206Sbostic for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) 107*37206Sbostic ; 108*37206Sbostic for (i = optind; i < argc; ++i) { 109*37206Sbostic register char ** saveenv; 110*37206Sbostic char * tzequals; 111*37206Sbostic char * fakeenv[2]; 112*37206Sbostic 113*37206Sbostic tzequals = malloc((unsigned) (strlen(argv[i]) + 4)); 114*37206Sbostic if (tzequals == NULL) { 115*37206Sbostic (void) fprintf(stderr, "%s: can't allocate memory\n", 116*37206Sbostic argv[0]); 117*37206Sbostic (void) exit(EXIT_FAILURE); 118*37206Sbostic } 119*37206Sbostic (void) sprintf(tzequals, "TZ=%s", argv[i]); 120*37206Sbostic fakeenv[0] = tzequals; 121*37206Sbostic fakeenv[1] = NULL; 122*37206Sbostic saveenv = environ; 123*37206Sbostic environ = fakeenv; 124*37206Sbostic (void) tzset(); 125*37206Sbostic free(tzequals); 126*37206Sbostic environ = saveenv; 127*37206Sbostic show(argv[i], now, FALSE); 128*37206Sbostic if (!vflag) 129*37206Sbostic continue; 130*37206Sbostic /* 131*37206Sbostic ** Get lowest value of t. 132*37206Sbostic */ 133*37206Sbostic t = hibit; 134*37206Sbostic if (t > 0) /* time_t is unsigned */ 135*37206Sbostic t = 0; 136*37206Sbostic show(argv[i], t, TRUE); 137*37206Sbostic t += SECSPERHOUR * HOURSPERDAY; 138*37206Sbostic show(argv[i], t, TRUE); 139*37206Sbostic tm = *localtime(&t); 140*37206Sbostic for ( ; ; ) { 141*37206Sbostic if (cutoff != NULL && t >= cuttime) 142*37206Sbostic break; 143*37206Sbostic newt = t + SECSPERHOUR * 12; 144*37206Sbostic if (cutoff != NULL && newt >= cuttime) 145*37206Sbostic break; 146*37206Sbostic if (newt <= t) 147*37206Sbostic break; 148*37206Sbostic newtm = *localtime(&newt); 149*37206Sbostic if (delta(&newtm, &tm) != (newt - t) || 150*37206Sbostic newtm.tm_isdst != tm.tm_isdst) 151*37206Sbostic hunt(argv[i], t, newt); 152*37206Sbostic t = newt; 153*37206Sbostic tm = newtm; 154*37206Sbostic } 155*37206Sbostic /* 156*37206Sbostic ** Get highest value of t. 157*37206Sbostic */ 158*37206Sbostic t = ~((time_t) 0); 159*37206Sbostic if (t < 0) /* time_t is signed */ 160*37206Sbostic t &= ~hibit; 161*37206Sbostic t -= SECSPERHOUR * HOURSPERDAY; 162*37206Sbostic show(argv[i], t, TRUE); 163*37206Sbostic t += SECSPERHOUR * HOURSPERDAY; 164*37206Sbostic show(argv[i], t, TRUE); 165*37206Sbostic } 166*37206Sbostic if (fflush(stdout) || ferror(stdout)) { 167*37206Sbostic (void) fprintf(stderr, "%s: Error writing standard output ", 168*37206Sbostic argv[0]); 169*37206Sbostic (void) perror("standard output"); 170*37206Sbostic (void) exit(EXIT_FAILURE); 171*37206Sbostic } 172*37206Sbostic exit(EXIT_SUCCESS); 173*37206Sbostic for ( ; ; ) 174*37206Sbostic ; 175*37206Sbostic } 176*37206Sbostic 177*37206Sbostic static void 178*37206Sbostic hunt(name, lot, hit) 179*37206Sbostic char * name; 180*37206Sbostic time_t lot; 181*37206Sbostic time_t hit; 182*37206Sbostic { 183*37206Sbostic time_t t; 184*37206Sbostic struct tm lotm; 185*37206Sbostic struct tm tm; 186*37206Sbostic 187*37206Sbostic lotm = *localtime(&lot); 188*37206Sbostic while ((hit - lot) >= 2) { 189*37206Sbostic t = lot / 2 + hit / 2; 190*37206Sbostic if (t <= lot) 191*37206Sbostic ++t; 192*37206Sbostic else if (t >= hit) 193*37206Sbostic --t; 194*37206Sbostic tm = *localtime(&t); 195*37206Sbostic if (delta(&tm, &lotm) == (t - lot) && 196*37206Sbostic tm.tm_isdst == lotm.tm_isdst) { 197*37206Sbostic lot = t; 198*37206Sbostic lotm = tm; 199*37206Sbostic } else hit = t; 200*37206Sbostic } 201*37206Sbostic show(name, lot, TRUE); 202*37206Sbostic show(name, hit, TRUE); 203*37206Sbostic } 204*37206Sbostic 205*37206Sbostic static long 206*37206Sbostic delta(newp, oldp) 207*37206Sbostic struct tm * newp; 208*37206Sbostic struct tm * oldp; 209*37206Sbostic { 210*37206Sbostic long result; 211*37206Sbostic 212*37206Sbostic result = newp->tm_hour - oldp->tm_hour; 213*37206Sbostic if (result < 0) 214*37206Sbostic result += HOURSPERDAY; 215*37206Sbostic result *= SECSPERHOUR; 216*37206Sbostic result += (newp->tm_min - oldp->tm_min) * SECSPERMIN; 217*37206Sbostic return result + newp->tm_sec - oldp->tm_sec; 218*37206Sbostic } 219*37206Sbostic 220*37206Sbostic static void 221*37206Sbostic show(zone, t, v) 222*37206Sbostic char * zone; 223*37206Sbostic time_t t; 224*37206Sbostic int v; 225*37206Sbostic { 226*37206Sbostic struct tm * tmp; 227*37206Sbostic extern struct tm * localtime(); 228*37206Sbostic 229*37206Sbostic (void) printf("%-*s ", longest, zone); 230*37206Sbostic if (v) 231*37206Sbostic (void) printf("%.24s GMT = ", asctime(gmtime(&t))); 232*37206Sbostic tmp = localtime(&t); 233*37206Sbostic (void) printf("%.24s", asctime(tmp)); 234*37206Sbostic if (tzname[tmp->tm_isdst] != NULL && 235*37206Sbostic *tzname[tmp->tm_isdst] != '\0') 236*37206Sbostic (void) printf(" %s", tzname[tmp->tm_isdst]); 237*37206Sbostic if (v) { 238*37206Sbostic (void) printf(" isdst=%d", tmp->tm_isdst); 239*37206Sbostic #ifdef TM_GMTOFF 240*37206Sbostic (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); 241*37206Sbostic #endif /* defined TM_GMTOFF */ 242*37206Sbostic } 243*37206Sbostic (void) printf("\n"); 244*37206Sbostic } 245