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
main(argc,argv)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
hunt(name,lot,hit)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
delta(newp,oldp)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
show(zone,t,v)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 *
ecpyalloc(string)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