]> git.saurik.com Git - apple/system_cmds.git/blob - zdump.tproj/zdump.c
system_cmds-279.tar.gz
[apple/system_cmds.git] / zdump.tproj / zdump.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 #if defined(LIBC_SCCS) && !defined(lint)
26 #if 0
27 static char elsieid[] = "@(#)zdump.c 7.24";
28 #else
29 static char rcsid[] = "$OpenBSD: zdump.c,v 1.5 1997/01/21 04:52:45 millert Exp $";
30 #endif
31 #endif /* LIBC_SCCS and not lint */
32
33 /*
34 ** This code has been made independent of the rest of the time
35 ** conversion package to increase confidence in the verification it provides.
36 ** You can use this code to help in verifying other implementations.
37 */
38
39 #include "stdio.h" /* for stdout, stderr, perror */
40 #include "string.h" /* for strcpy */
41 #include "sys/types.h" /* for time_t */
42 #include "time.h" /* for struct tm */
43 #include "stdlib.h" /* for exit, malloc, atoi */
44
45 #ifndef MAX_STRING_LENGTH
46 #define MAX_STRING_LENGTH 1024
47 #endif /* !defined MAX_STRING_LENGTH */
48
49 #ifndef TRUE
50 #define TRUE 1
51 #endif /* !defined TRUE */
52
53 #ifndef FALSE
54 #define FALSE 0
55 #endif /* !defined FALSE */
56
57 #ifndef EXIT_SUCCESS
58 #define EXIT_SUCCESS 0
59 #endif /* !defined EXIT_SUCCESS */
60
61 #ifndef EXIT_FAILURE
62 #define EXIT_FAILURE 1
63 #endif /* !defined EXIT_FAILURE */
64
65 #ifndef SECSPERMIN
66 #define SECSPERMIN 60
67 #endif /* !defined SECSPERMIN */
68
69 #ifndef MINSPERHOUR
70 #define MINSPERHOUR 60
71 #endif /* !defined MINSPERHOUR */
72
73 #ifndef SECSPERHOUR
74 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
75 #endif /* !defined SECSPERHOUR */
76
77 #ifndef HOURSPERDAY
78 #define HOURSPERDAY 24
79 #endif /* !defined HOURSPERDAY */
80
81 #ifndef EPOCH_YEAR
82 #define EPOCH_YEAR 1970
83 #endif /* !defined EPOCH_YEAR */
84
85 #ifndef TM_YEAR_BASE
86 #define TM_YEAR_BASE 1900
87 #endif /* !defined TM_YEAR_BASE */
88
89 #ifndef DAYSPERNYEAR
90 #define DAYSPERNYEAR 365
91 #endif /* !defined DAYSPERNYEAR */
92
93 #ifndef isleap
94 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
95 #endif /* !defined isleap */
96
97 #if HAVE_GETTEXT - 0
98 #include "locale.h" /* for setlocale */
99 #include "libintl.h"
100 #endif /* HAVE_GETTEXT - 0 */
101
102 #ifndef GNUC_or_lint
103 #ifdef lint
104 #define GNUC_or_lint
105 #endif /* defined lint */
106 #ifndef lint
107 #ifdef __GNUC__
108 #define GNUC_or_lint
109 #endif /* defined __GNUC__ */
110 #endif /* !defined lint */
111 #endif /* !defined GNUC_or_lint */
112
113 #ifndef INITIALIZE
114 #ifdef GNUC_or_lint
115 #define INITIALIZE(x) ((x) = 0)
116 #endif /* defined GNUC_or_lint */
117 #ifndef GNUC_or_lint
118 #define INITIALIZE(x)
119 #endif /* !defined GNUC_or_lint */
120 #endif /* !defined INITIALIZE */
121
122 /*
123 ** For the benefit of GNU folk...
124 ** `_(MSGID)' uses the current locale's message library string for MSGID.
125 ** The default is to use gettext if available, and use MSGID otherwise.
126 */
127
128 #ifndef _
129 #if HAVE_GETTEXT - 0
130 #define _(msgid) gettext(msgid)
131 #else /* !(HAVE_GETTEXT - 0) */
132 #define _(msgid) msgid
133 #endif /* !(HAVE_GETTEXT - 0) */
134 #endif /* !defined _ */
135
136 #ifndef TZ_DOMAIN
137 #define TZ_DOMAIN "tz"
138 #endif /* !defined TZ_DOMAIN */
139
140 extern char ** environ;
141 extern int getopt();
142 extern char * optarg;
143 extern int optind;
144 extern time_t time();
145 extern char * tzname[2];
146
147 static char * abbr();
148 static long delta();
149 static time_t hunt();
150 static int longest;
151 static char * progname;
152 static void show();
153
154 int
155 main(argc, argv)
156 int argc;
157 char * argv[];
158 {
159 register int i;
160 register int c;
161 register int vflag;
162 register char * cutoff;
163 register int cutyear;
164 register long cuttime;
165 char ** fakeenv;
166 time_t now;
167 time_t t;
168 time_t newt;
169 time_t hibit;
170 struct tm tm;
171 struct tm newtm;
172
173 INITIALIZE(cuttime);
174 #if HAVE_GETTEXT - 0
175 (void) setlocale(LC_MESSAGES, "");
176 #ifdef TZ_DOMAINDIR
177 (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
178 #endif /* defined(TEXTDOMAINDIR) */
179 (void) textdomain(TZ_DOMAIN);
180 #endif /* HAVE_GETTEXT - 0 */
181 progname = argv[0];
182 vflag = 0;
183 cutoff = NULL;
184 while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
185 if (c == 'v')
186 vflag = 1;
187 else cutoff = optarg;
188 if (c != EOF ||
189 (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
190 (void) fprintf(stderr,
191 _("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
192 argv[0], argv[0]);
193 (void) exit(EXIT_FAILURE);
194 }
195 if (cutoff != NULL) {
196 int y;
197
198 cutyear = atoi(cutoff);
199 cuttime = 0;
200 for (y = EPOCH_YEAR; y < cutyear; ++y)
201 cuttime += DAYSPERNYEAR + isleap(y);
202 cuttime *= SECSPERHOUR * HOURSPERDAY;
203 }
204 (void) time(&now);
205 longest = 0;
206 for (i = optind; i < argc; ++i)
207 if (strlen(argv[i]) > longest)
208 longest = strlen(argv[i]);
209 for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
210 continue;
211 {
212 register int from;
213 register int to;
214
215 for (i = 0; environ[i] != NULL; ++i)
216 continue;
217 fakeenv = (char **) malloc((size_t) ((i + 2) *
218 sizeof *fakeenv));
219 if (fakeenv == NULL ||
220 (fakeenv[0] = (char *) malloc((size_t) (longest +
221 4))) == NULL) {
222 (void) perror(progname);
223 (void) exit(EXIT_FAILURE);
224 }
225 to = 0;
226 (void) strcpy(fakeenv[to++], "TZ=");
227 for (from = 0; environ[from] != NULL; ++from)
228 if (strncmp(environ[from], "TZ=", 3) != 0)
229 fakeenv[to++] = environ[from];
230 fakeenv[to] = NULL;
231 environ = fakeenv;
232 }
233 for (i = optind; i < argc; ++i) {
234 static char buf[MAX_STRING_LENGTH];
235
236 (void) strcpy(&fakeenv[0][3], argv[i]);
237 show(argv[i], now, FALSE);
238 if (!vflag)
239 continue;
240 /*
241 ** Get lowest value of t.
242 */
243 t = hibit;
244 if (t > 0) /* time_t is unsigned */
245 t = 0;
246 show(argv[i], t, TRUE);
247 t += SECSPERHOUR * HOURSPERDAY;
248 show(argv[i], t, TRUE);
249 tm = *localtime(&t);
250 (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
251 for ( ; ; ) {
252 if (cutoff != NULL && t >= cuttime)
253 break;
254 newt = t + SECSPERHOUR * 12;
255 if (cutoff != NULL && newt >= cuttime)
256 break;
257 if (newt <= t)
258 break;
259 newtm = *localtime(&newt);
260 if (delta(&newtm, &tm) != (newt - t) ||
261 newtm.tm_isdst != tm.tm_isdst ||
262 strcmp(abbr(&newtm), buf) != 0) {
263 newt = hunt(argv[i], t, newt);
264 newtm = *localtime(&newt);
265 (void) strncpy(buf, abbr(&newtm),
266 (sizeof buf) - 1);
267 }
268 t = newt;
269 tm = newtm;
270 }
271 /*
272 ** Get highest value of t.
273 */
274 t = ~((time_t) 0);
275 if (t < 0) /* time_t is signed */
276 t &= ~hibit;
277 t -= SECSPERHOUR * HOURSPERDAY;
278 show(argv[i], t, TRUE);
279 t += SECSPERHOUR * HOURSPERDAY;
280 show(argv[i], t, TRUE);
281 }
282 if (fflush(stdout) || ferror(stdout)) {
283 (void) fprintf(stderr, _("%s: Error writing standard output "),
284 argv[0]);
285 (void) perror(_("standard output"));
286 (void) exit(EXIT_FAILURE);
287 }
288 exit(EXIT_SUCCESS);
289
290 /* gcc -Wall pacifier */
291 for ( ; ; )
292 continue;
293 }
294
295 static time_t
296 hunt(name, lot, hit)
297 char * name;
298 time_t lot;
299 time_t hit;
300 {
301 time_t t;
302 struct tm lotm;
303 struct tm tm;
304 static char loab[MAX_STRING_LENGTH];
305
306 lotm = *localtime(&lot);
307 (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
308 loab[(sizeof loab) - 1] = '\0';
309 while ((hit - lot) >= 2) {
310 t = lot / 2 + hit / 2;
311 if (t <= lot)
312 ++t;
313 else if (t >= hit)
314 --t;
315 tm = *localtime(&t);
316 if (delta(&tm, &lotm) == (t - lot) &&
317 tm.tm_isdst == lotm.tm_isdst &&
318 strcmp(abbr(&tm), loab) == 0) {
319 lot = t;
320 lotm = tm;
321 } else hit = t;
322 }
323 show(name, lot, TRUE);
324 show(name, hit, TRUE);
325 return hit;
326 }
327
328 /*
329 ** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
330 */
331
332 static long
333 delta(newp, oldp)
334 struct tm * newp;
335 struct tm * oldp;
336 {
337 long result;
338 int tmy;
339
340 if (newp->tm_year < oldp->tm_year)
341 return -delta(oldp, newp);
342 result = 0;
343 for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
344 result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
345 result += newp->tm_yday - oldp->tm_yday;
346 result *= HOURSPERDAY;
347 result += newp->tm_hour - oldp->tm_hour;
348 result *= MINSPERHOUR;
349 result += newp->tm_min - oldp->tm_min;
350 result *= SECSPERMIN;
351 result += newp->tm_sec - oldp->tm_sec;
352 return result;
353 }
354
355 extern struct tm * localtime();
356
357 static void
358 show(zone, t, v)
359 char * zone;
360 time_t t;
361 int v;
362 {
363 struct tm * tmp;
364
365 (void) printf("%-*s ", longest, zone);
366 if (v)
367 (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
368 tmp = localtime(&t);
369 (void) printf("%.24s", asctime(tmp));
370 if (*abbr(tmp) != '\0')
371 (void) printf(" %s", abbr(tmp));
372 if (v) {
373 (void) printf(" isdst=%d", tmp->tm_isdst);
374 #ifdef TM_GMTOFF
375 (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
376 #endif /* defined TM_GMTOFF */
377 }
378 (void) printf("\n");
379 }
380
381 static char *
382 abbr(tmp)
383 struct tm * tmp;
384 {
385 register char * result;
386 static char nada;
387
388 if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
389 return &nada;
390 result = tzname[tmp->tm_isdst];
391 return (result == NULL) ? &nada : result;
392 }