zdump.c revision 17214
1#ifndef lint 2#ifndef NOID 3static char elsieid[] = "@(#)zdump.c 7.24"; 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#if HAVE_GETTEXT - 0 72#include "locale.h" /* for setlocale */ 73#include "libintl.h" 74#endif /* HAVE_GETTEXT - 0 */ 75 76#ifndef GNUC_or_lint 77#ifdef lint 78#define GNUC_or_lint 79#endif /* defined lint */ 80#ifndef lint 81#ifdef __GNUC__ 82#define GNUC_or_lint 83#endif /* defined __GNUC__ */ 84#endif /* !defined lint */ 85#endif /* !defined GNUC_or_lint */ 86 87#ifndef INITIALIZE 88#ifdef GNUC_or_lint 89#define INITIALIZE(x) ((x) = 0) 90#endif /* defined GNUC_or_lint */ 91#ifndef GNUC_or_lint 92#define INITIALIZE(x) 93#endif /* !defined GNUC_or_lint */ 94#endif /* !defined INITIALIZE */ 95 96/* 97** For the benefit of GNU folk... 98** `_(MSGID)' uses the current locale's message library string for MSGID. 99** The default is to use gettext if available, and use MSGID otherwise. 100*/ 101 102#ifndef _ 103#if HAVE_GETTEXT - 0 104#define _(msgid) gettext(msgid) 105#else /* !(HAVE_GETTEXT - 0) */ 106#define _(msgid) msgid 107#endif /* !(HAVE_GETTEXT - 0) */ 108#endif /* !defined _ */ 109 110#ifndef TZ_DOMAIN 111#define TZ_DOMAIN "tz" 112#endif /* !defined TZ_DOMAIN */ 113 114extern char ** environ; 115extern int getopt(); 116extern char * optarg; 117extern int optind; 118extern time_t time(); 119extern char * tzname[2]; 120 121static char * abbr(); 122static long delta(); 123static time_t hunt(); 124static int longest; 125static char * progname; 126static void show(); 127 128int 129main(argc, argv) 130int argc; 131char * argv[]; 132{ 133 register int i; 134 register int c; 135 register int vflag; 136 register char * cutoff; 137 register int cutyear; 138 register long cuttime; 139 char ** fakeenv; 140 time_t now; 141 time_t t; 142 time_t newt; 143 time_t hibit; 144 struct tm tm; 145 struct tm newtm; 146 147 INITIALIZE(cuttime); 148#if HAVE_GETTEXT - 0 149 (void) setlocale(LC_MESSAGES, ""); 150#ifdef TZ_DOMAINDIR 151 (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); 152#endif /* defined(TEXTDOMAINDIR) */ 153 (void) textdomain(TZ_DOMAIN); 154#endif /* HAVE_GETTEXT - 0 */ 155 progname = argv[0]; 156 vflag = 0; 157 cutoff = NULL; 158 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 159 if (c == 'v') 160 vflag = 1; 161 else cutoff = optarg; 162 if (c != EOF || 163 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 164 (void) fprintf(stderr, 165_("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"), 166 argv[0], argv[0]); 167 (void) exit(EXIT_FAILURE); 168 } 169 if (cutoff != NULL) { 170 int y; 171 172 cutyear = atoi(cutoff); 173 cuttime = 0; 174 for (y = EPOCH_YEAR; y < cutyear; ++y) 175 cuttime += DAYSPERNYEAR + isleap(y); 176 cuttime *= SECSPERHOUR * HOURSPERDAY; 177 } 178 (void) time(&now); 179 longest = 0; 180 for (i = optind; i < argc; ++i) 181 if (strlen(argv[i]) > longest) 182 longest = strlen(argv[i]); 183 for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) 184 continue; 185 { 186 register int from; 187 register int to; 188 189 for (i = 0; environ[i] != NULL; ++i) 190 continue; 191 fakeenv = (char **) malloc((size_t) ((i + 2) * 192 sizeof *fakeenv)); 193 if (fakeenv == NULL || 194 (fakeenv[0] = (char *) malloc((size_t) (longest + 195 4))) == NULL) { 196 (void) perror(progname); 197 (void) exit(EXIT_FAILURE); 198 } 199 to = 0; 200 (void) strcpy(fakeenv[to++], "TZ="); 201 for (from = 0; environ[from] != NULL; ++from) 202 if (strncmp(environ[from], "TZ=", 3) != 0) 203 fakeenv[to++] = environ[from]; 204 fakeenv[to] = NULL; 205 environ = fakeenv; 206 } 207 for (i = optind; i < argc; ++i) { 208 static char buf[MAX_STRING_LENGTH]; 209 210 (void) strcpy(&fakeenv[0][3], argv[i]); 211 if (!vflag) { 212 show(argv[i], now, FALSE); 213 continue; 214 } 215 /* 216 ** Get lowest value of t. 217 */ 218 t = hibit; 219 if (t > 0) /* time_t is unsigned */ 220 t = 0; 221 show(argv[i], t, TRUE); 222 t += SECSPERHOUR * HOURSPERDAY; 223 show(argv[i], t, TRUE); 224 tm = *localtime(&t); 225 (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); 226 for ( ; ; ) { 227 if (cutoff != NULL && t >= cuttime) 228 break; 229 newt = t + SECSPERHOUR * 12; 230 if (cutoff != NULL && newt >= cuttime) 231 break; 232 if (newt <= t) 233 break; 234 newtm = *localtime(&newt); 235 if (delta(&newtm, &tm) != (newt - t) || 236 newtm.tm_isdst != tm.tm_isdst || 237 strcmp(abbr(&newtm), buf) != 0) { 238 newt = hunt(argv[i], t, newt); 239 newtm = *localtime(&newt); 240 (void) strncpy(buf, abbr(&newtm), 241 (sizeof buf) - 1); 242 } 243 t = newt; 244 tm = newtm; 245 } 246 /* 247 ** Get highest value of t. 248 */ 249 t = ~((time_t) 0); 250 if (t < 0) /* time_t is signed */ 251 t &= ~hibit; 252 t -= SECSPERHOUR * HOURSPERDAY; 253 show(argv[i], t, TRUE); 254 t += SECSPERHOUR * HOURSPERDAY; 255 show(argv[i], t, TRUE); 256 } 257 if (fflush(stdout) || ferror(stdout)) { 258 (void) fprintf(stderr, _("%s: Error writing standard output "), 259 argv[0]); 260 (void) perror(_("standard output")); 261 (void) exit(EXIT_FAILURE); 262 } 263 exit(EXIT_SUCCESS); 264 265 /* gcc -Wall pacifier */ 266 for ( ; ; ) 267 continue; 268} 269 270static time_t 271hunt(name, lot, hit) 272char * name; 273time_t lot; 274time_t hit; 275{ 276 time_t t; 277 struct tm lotm; 278 struct tm tm; 279 static char loab[MAX_STRING_LENGTH]; 280 281 lotm = *localtime(&lot); 282 (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); 283 while ((hit - lot) >= 2) { 284 t = lot / 2 + hit / 2; 285 if (t <= lot) 286 ++t; 287 else if (t >= hit) 288 --t; 289 tm = *localtime(&t); 290 if (delta(&tm, &lotm) == (t - lot) && 291 tm.tm_isdst == lotm.tm_isdst && 292 strcmp(abbr(&tm), loab) == 0) { 293 lot = t; 294 lotm = tm; 295 } else hit = t; 296 } 297 show(name, lot, TRUE); 298 show(name, hit, TRUE); 299 return hit; 300} 301 302/* 303** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. 304*/ 305 306static long 307delta(newp, oldp) 308struct tm * newp; 309struct tm * oldp; 310{ 311 long result; 312 int tmy; 313 314 if (newp->tm_year < oldp->tm_year) 315 return -delta(oldp, newp); 316 result = 0; 317 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) 318 result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE); 319 result += newp->tm_yday - oldp->tm_yday; 320 result *= HOURSPERDAY; 321 result += newp->tm_hour - oldp->tm_hour; 322 result *= MINSPERHOUR; 323 result += newp->tm_min - oldp->tm_min; 324 result *= SECSPERMIN; 325 result += newp->tm_sec - oldp->tm_sec; 326 return result; 327} 328 329extern struct tm * localtime(); 330 331static void 332show(zone, t, v) 333char * zone; 334time_t t; 335int v; 336{ 337 struct tm * tmp; 338 339 (void) printf("%-*s ", longest, zone); 340 if (v) 341 (void) printf("%.24s GMT = ", asctime(gmtime(&t))); 342 tmp = localtime(&t); 343 (void) printf("%.24s", asctime(tmp)); 344 if (*abbr(tmp) != '\0') 345 (void) printf(" %s", abbr(tmp)); 346 if (v) { 347 (void) printf(" isdst=%d", tmp->tm_isdst); 348#ifdef TM_GMTOFF 349 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); 350#endif /* defined TM_GMTOFF */ 351 } 352 (void) printf("\n"); 353} 354 355static char * 356abbr(tmp) 357struct tm * tmp; 358{ 359 register char * result; 360 static char nada; 361 362 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) 363 return &nada; 364 result = tzname[tmp->tm_isdst]; 365 return (result == NULL) ? &nada : result; 366} 367