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