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