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