]> git.saurik.com Git - apple/system_cmds.git/blame - zdump.tproj/zdump.c
system_cmds-300.tar.gz
[apple/system_cmds.git] / zdump.tproj / zdump.c
CommitLineData
1815bff5
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
83f6dbe8
A
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.
1815bff5
A
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,
83f6dbe8
A
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.
1815bff5
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#if defined(LIBC_SCCS) && !defined(lint)
26#if 0
27static char elsieid[] = "@(#)zdump.c 7.24";
28#else
29static 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
140extern char ** environ;
141extern int getopt();
142extern char * optarg;
143extern int optind;
144extern time_t time();
145extern char * tzname[2];
146
147static char * abbr();
148static long delta();
149static time_t hunt();
150static int longest;
151static char * progname;
152static void show();
153
154int
155main(argc, argv)
156int argc;
157char * 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
295static time_t
296hunt(name, lot, hit)
297char * name;
298time_t lot;
299time_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
332static long
333delta(newp, oldp)
334struct tm * newp;
335struct 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
355extern struct tm * localtime();
356
357static void
358show(zone, t, v)
359char * zone;
360time_t t;
361int 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
381static char *
382abbr(tmp)
383struct 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}