1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1986-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * zdump 7.24 29 * Taken from elsie.nci.nih.gov to replace the existing Solaris zdump, 30 * which was based on an earlier version of the elsie code. 31 * 32 * For zdump 7.24, the following changes were made to the elsie code: 33 * locale/textdomain/messages to match existing Solaris style. 34 * Solaris verbose mode is documented to display the current time first. 35 * cstyle cleaned code. 36 * removed old locale/textdomain code. 37 */ 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 /* static char elsieid[] = "@(#)zdump.c 7.28"; */ 41 42 /* 43 * This code has been made independent of the rest of the time 44 * conversion package to increase confidence in the verification it provides. 45 * You can use this code to help in verifying other implementations. 46 */ 47 48 #include "stdio.h" /* for stdout, stderr, perror */ 49 #include "string.h" /* for strcpy */ 50 #include "sys/types.h" /* for time_t */ 51 #include "time.h" /* for struct tm */ 52 #include "stdlib.h" /* for exit, malloc, atoi */ 53 #include "locale.h" /* for setlocale, textdomain */ 54 #include "libintl.h" 55 #include "tzfile.h" /* for defines */ 56 57 #ifndef MAX_STRING_LENGTH 58 #define MAX_STRING_LENGTH 1024 59 #endif /* !defined MAX_STRING_LENGTH */ 60 61 #ifndef TRUE 62 #define TRUE 1 63 #endif /* !defined TRUE */ 64 65 #ifndef FALSE 66 #define FALSE 0 67 #endif /* !defined FALSE */ 68 69 #ifndef INITIALIZE 70 #ifdef lint 71 #define INITIALIZE(x) ((x) = 0) 72 #endif /* defined lint */ 73 #ifndef lint 74 #define INITIALIZE(x) 75 #endif /* !defined lint */ 76 #endif /* !defined INITIALIZE */ 77 78 extern char ** environ; 79 80 static char * abbr(struct tm *); 81 static long delta(struct tm *, struct tm *); 82 static time_t hunt(char *, time_t, time_t); 83 static size_t longest; 84 static char * progname; 85 static void show(char *, time_t, int); 86 static void usage(char *); 87 88 int 89 main(argc, argv) 90 int argc; 91 char * argv[]; 92 { 93 register int i; 94 register int c; 95 register int vflag; 96 register char * cutoff; 97 register int cutyear; 98 register long cuttime; 99 char ** fakeenv; 100 time_t now; 101 time_t t; 102 time_t newt; 103 time_t hibit; 104 struct tm tm; 105 struct tm newtm; 106 107 INITIALIZE(cuttime); 108 109 (void) setlocale(LC_ALL, ""); 110 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 111 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 112 #endif 113 (void) textdomain(TEXT_DOMAIN); 114 115 progname = argv[0]; 116 vflag = 0; 117 cutoff = NULL; 118 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v') 119 if (c == 'v') 120 vflag = 1; 121 else cutoff = optarg; 122 if (c != EOF || 123 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) { 124 usage(argv[0]); 125 /* NOTREACHED */ 126 } 127 if (cutoff != NULL) { 128 int y; 129 130 cutyear = atoi(cutoff); 131 cuttime = 0; 132 for (y = EPOCH_YEAR; y < cutyear; ++y) 133 cuttime += DAYSPERNYEAR + isleap(y); 134 cuttime *= SECSPERHOUR * HOURSPERDAY; 135 } 136 (void) time(&now); 137 longest = 0; 138 for (i = optind; i < argc; ++i) 139 if (strlen(argv[i]) > longest) 140 longest = strlen(argv[i]); 141 for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) 142 continue; 143 { 144 register int from; 145 register int to; 146 147 for (i = 0; environ[i] != NULL; ++i) 148 continue; 149 fakeenv = (char **) malloc((size_t) ((i + 2) * 150 sizeof (*fakeenv))); 151 if (fakeenv == NULL || 152 (fakeenv[0] = (char *) malloc(longest + 4)) == NULL) { 153 (void) perror(progname); 154 (void) exit(EXIT_FAILURE); 155 } 156 to = 0; 157 (void) strcpy(fakeenv[to++], "TZ="); 158 for (from = 0; environ[from] != NULL; ++from) 159 if (strncmp(environ[from], "TZ=", 3) != 0) 160 fakeenv[to++] = environ[from]; 161 fakeenv[to] = NULL; 162 environ = fakeenv; 163 } 164 for (i = optind; i < argc; ++i) { 165 static char buf[MAX_STRING_LENGTH]; 166 167 (void) strcpy(&fakeenv[0][3], argv[i]); 168 if (!vflag) { 169 show(argv[i], now, FALSE); 170 continue; 171 } 172 173 #if defined(sun) 174 /* 175 * We show the current time first, probably because we froze 176 * the behavior of zdump some time ago and then it got 177 * changed. 178 */ 179 show(argv[i], now, TRUE); 180 #endif 181 182 /* 183 * Get lowest value of t. 184 */ 185 t = hibit; 186 if (t > 0) /* time_t is unsigned */ 187 t = 0; 188 show(argv[i], t, TRUE); 189 t += SECSPERHOUR * HOURSPERDAY; 190 show(argv[i], t, TRUE); 191 tm = *localtime(&t); 192 (void) strncpy(buf, abbr(&tm), (sizeof (buf)) - 1); 193 for (;;) { 194 if (cutoff != NULL && t >= cuttime) 195 break; 196 newt = t + SECSPERHOUR * 12; 197 if (cutoff != NULL && newt >= cuttime) 198 break; 199 if (newt <= t) 200 break; 201 newtm = *localtime(&newt); 202 if (delta(&newtm, &tm) != (newt - t) || 203 newtm.tm_isdst != tm.tm_isdst || 204 strcmp(abbr(&newtm), buf) != 0) { 205 newt = hunt(argv[i], t, newt); 206 newtm = *localtime(&newt); 207 (void) strncpy(buf, abbr(&newtm), 208 (sizeof (buf)) - 1); 209 } 210 t = newt; 211 tm = newtm; 212 } 213 /* 214 * Get highest value of t. 215 */ 216 t = ~((time_t) 0); 217 if (t < 0) /* time_t is signed */ 218 t &= ~hibit; 219 #if defined(sun) 220 show(argv[i], t, TRUE); 221 t -= SECSPERHOUR * HOURSPERDAY; 222 show(argv[i], t, TRUE); 223 #else /* !defined(sun) */ 224 t -= SECSPERHOUR * HOURSPERDAY; 225 show(argv[i], t, TRUE); 226 t += SECSPERHOUR * HOURSPERDAY; 227 show(argv[i], t, TRUE); 228 #endif /* !defined(sun) */ 229 } 230 if (fflush(stdout) || ferror(stdout)) { 231 (void) fprintf(stderr, gettext( 232 "%s: Error writing standard output "), argv[0]); 233 (void) perror(gettext("standard output")); 234 usage(argv[0]); 235 } 236 return (EXIT_SUCCESS); 237 } 238 239 static time_t 240 hunt(name, lot, hit) 241 char * name; 242 time_t lot; 243 time_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 275 static long 276 delta(newp, oldp) 277 struct tm * newp; 278 struct 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 298 static void 299 show(zone, t, v) 300 char * zone; 301 time_t t; 302 int v; 303 { 304 struct tm * tmp; 305 306 (void) printf("%-*s ", (int)longest, zone); 307 if (v) 308 (void) printf("%.24s UTC = ", asctime(gmtime(&t))); 309 tmp = localtime(&t); 310 (void) printf("%.24s", asctime(tmp)); 311 if (*abbr(tmp) != '\0') 312 (void) printf(" %s", abbr(tmp)); 313 if (v) { 314 (void) printf(" isdst=%d", tmp->tm_isdst); 315 } 316 (void) printf("\n"); 317 } 318 319 static char * 320 abbr(tmp) 321 struct tm * tmp; 322 { 323 register char * result; 324 static char nada; 325 326 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1) 327 return (&nada); 328 result = tzname[tmp->tm_isdst]; 329 return ((result == NULL) ? &nada : result); 330 } 331 332 static void 333 usage(char *progname) 334 { 335 (void) fprintf(stderr, gettext( 336 "%s: [ -v ] [ -c cutoffyear ] [ zonename ... ]\n"), progname); 337 (void) exit(EXIT_FAILURE); 338 /* NOTREACHED */ 339 } 340