]>
git.saurik.com Git - apple/system_cmds.git/blob - zdump.tproj/zdump.c
7068cdfd73107d5083e11db87035671456c42908
   1 static const char       elsieid
[] = "@(#)zdump.c        7.31"; 
   5 __unused 
static const char rcsid
[] = 
   6   "$FreeBSD: src/usr.sbin/zic/zdump.c,v 1.10 2008/02/19 07:09:19 ru Exp $"; 
  10 ** This code has been made independent of the rest of the time 
  11 ** conversion package to increase confidence in the verification it provides. 
  12 ** You can use this code to help in verifying other implementations. 
  16 #include <stdio.h>      /* for stdout, stderr */ 
  17 #include <stdlib.h>     /* for exit, malloc, atoi */ 
  18 #include <string.h>     /* for strcpy */ 
  19 #include <sys/types.h>  /* for time_t */ 
  20 #include <time.h>       /* for struct tm */ 
  24 #ifndef MAX_STRING_LENGTH 
  25 #define MAX_STRING_LENGTH       1024 
  26 #endif /* !defined MAX_STRING_LENGTH */ 
  30 #endif /* !defined TRUE */ 
  34 #endif /* !defined FALSE */ 
  37 #define EXIT_SUCCESS    0 
  38 #endif /* !defined EXIT_SUCCESS */ 
  41 #define EXIT_FAILURE    1 
  42 #endif /* !defined EXIT_FAILURE */ 
  46 #endif /* !defined SECSPERMIN */ 
  49 #define MINSPERHOUR     60 
  50 #endif /* !defined MINSPERHOUR */ 
  53 #define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR) 
  54 #endif /* !defined SECSPERHOUR */ 
  57 #define HOURSPERDAY     24 
  58 #endif /* !defined HOURSPERDAY */ 
  61 #define EPOCH_YEAR      1970 
  62 #endif /* !defined EPOCH_YEAR */ 
  65 #define TM_YEAR_BASE    1900 
  66 #endif /* !defined TM_YEAR_BASE */ 
  69 #define DAYSPERNYEAR    365 
  70 #endif /* !defined DAYSPERNYEAR */ 
  73 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) 
  74 #endif /* !defined isleap */ 
  77 #include "locale.h"     /* for setlocale */ 
  79 #endif /* HAVE_GETTEXT - 0 */ 
  84 #endif /* defined lint */ 
  88 #endif /* defined __GNUC__ */ 
  89 #endif /* !defined lint */ 
  90 #endif /* !defined GNUC_or_lint */ 
  94 #define INITIALIZE(x)   ((x) = 0) 
  95 #endif /* defined GNUC_or_lint */ 
  98 #endif /* !defined GNUC_or_lint */ 
  99 #endif /* !defined INITIALIZE */ 
 102 ** For the benefit of GNU folk... 
 103 ** `_(MSGID)' uses the current locale's message library string for MSGID. 
 104 ** The default is to use gettext if available, and use MSGID otherwise. 
 109 #define _(msgid) gettext(msgid) 
 110 #else /* !(HAVE_GETTEXT - 0) */ 
 111 #define _(msgid) msgid 
 112 #endif /* !(HAVE_GETTEXT - 0) */ 
 113 #endif /* !defined _ */ 
 116 #define TZ_DOMAIN "tz" 
 117 #endif /* !defined TZ_DOMAIN */ 
 122 #endif /* defined __STDC__ */ 
 125 #endif /* !defined __STDC__ */ 
 126 #endif /* !defined P */ 
 128 extern char **  environ
; 
 129 extern char *   tzname
[2]; 
 131 static char *   abbr 
P((struct tm 
* tmp
)); 
 132 static long     delta 
P((struct tm 
* newp
, struct tm 
* oldp
)); 
 133 static time_t   hunt 
P((char * name
, time_t lot
, time_t hit
)); 
 134 static size_t   longest
; 
 135 static void     show 
P((char * zone
, time_t t
, int v
)); 
 136 static void     usage(void); 
 139 main(int argc
, char *argv
[]) 
 152 // <rdar://problem/6013740> 
 153 // The approach of walking through every day from the minimum 
 154 // possible time_t value to the maximum possible time_t value 
 155 // falls apart with 64-bit time_t (takes too long to iterate, 
 156 // and causes gmtime(3) and localtime(3) to return EOVERFLOW 
 157 // which this code does not anticipate).  Limiting the time_t 
 158 // range to [INT_MIN:INT_MAX] even on LP64. 
 166         (void) setlocale(LC_MESSAGES
, ""); 
 168         (void) bindtextdomain(TZ_DOMAIN
, TZ_DOMAINDIR
); 
 169 #endif /* defined(TEXTDOMAINDIR) */ 
 170         (void) textdomain(TZ_DOMAIN
); 
 171 #endif /* HAVE_GETTEXT - 0 */ 
 172         for (i 
= 1; i 
< argc
; ++i
) 
 173                 if (strcmp(argv
[i
], "--version") == 0) { 
 174                         errx(EXIT_SUCCESS
, "%s", elsieid
); 
 178         while ((c 
= getopt(argc
, argv
, "c:v")) == 'c' || c 
== 'v') 
 181                 else    cutoff 
= optarg
; 
 183                 (optind 
== argc 
- 1 && strcmp(argv
[optind
], "=") == 0)) { 
 186         if (cutoff 
!= NULL
) { 
 189                 cutyear 
= atoi(cutoff
); 
 191                 for (y 
= EPOCH_YEAR
; y 
< cutyear
; ++y
) 
 192                         cuttime 
+= DAYSPERNYEAR 
+ isleap(y
); 
 193                 cuttime 
*= SECSPERHOUR 
* HOURSPERDAY
; 
 197         for (i 
= optind
; i 
< argc
; ++i
) 
 198                 if (strlen(argv
[i
]) > longest
) 
 199                         longest 
= strlen(argv
[i
]); 
 201         for (hibit 
= 1; (hibit 
<< 1) != 0; hibit 
<<= 1) 
 208                 for (i 
= 0;  environ
[i
] != NULL
;  ++i
) 
 210                 fakeenv 
= (char **) malloc((size_t) ((i 
+ 2) * 
 212                 if (fakeenv 
== NULL 
|| 
 213                         (fakeenv
[0] = (char *) malloc((size_t) (longest 
+ 
 216                                              _("malloc() failed")); 
 218                 (void) strcpy(fakeenv
[to
++], "TZ="); 
 219                 for (from 
= 0; environ
[from
] != NULL
; ++from
) 
 220                         if (strncmp(environ
[from
], "TZ=", 3) != 0) 
 221                                 fakeenv
[to
++] = environ
[from
]; 
 225         for (i 
= optind
; i 
< argc
; ++i
) { 
 226                 static char     buf
[MAX_STRING_LENGTH
]; 
 228                 (void) strcpy(&fakeenv
[0][3], argv
[i
]); 
 230                         show(argv
[i
], now
, FALSE
); 
 234                 ** Get lowest value of t. 
 240                 if (t 
> 0)              /* time_t is unsigned */ 
 243                 show(argv
[i
], t
, TRUE
); 
 244                 t 
+= SECSPERHOUR 
* HOURSPERDAY
; 
 245                 show(argv
[i
], t
, TRUE
); 
 247                 (void) strncpy(buf
, abbr(&tm
), (sizeof buf
) - 1); 
 249                         if (cutoff 
!= NULL 
&& t 
>= cuttime
) 
 251                         newt 
= t 
+ SECSPERHOUR 
* 12; 
 252                         if (cutoff 
!= NULL 
&& newt 
>= cuttime
) 
 261                         newtm 
= *localtime(&newt
); 
 262                         if (delta(&newtm
, &tm
) != (newt 
- t
) || 
 263                                 newtm
.tm_isdst 
!= tm
.tm_isdst 
|| 
 264                                 strcmp(abbr(&newtm
), buf
) != 0) { 
 265                                         newt 
= hunt(argv
[i
], t
, newt
); 
 266                                         newtm 
= *localtime(&newt
); 
 267                                         (void) strncpy(buf
, abbr(&newtm
), 
 274                 ** Get highest value of t. 
 280                 if (t 
< 0)              /* time_t is signed */ 
 283                 t 
-= SECSPERHOUR 
* HOURSPERDAY
; 
 284                 show(argv
[i
], t
, TRUE
); 
 285                 t 
+= SECSPERHOUR 
* HOURSPERDAY
; 
 286                 show(argv
[i
], t
, TRUE
); 
 288         if (fflush(stdout
) || ferror(stdout
)) 
 289                 errx(EXIT_FAILURE
, _("error writing standard output")); 
 292         /* gcc -Wall pacifier */ 
 301 _("usage: zdump [--version] [-v] [-c cutoff] zonename ...\n")); 
 306 hunt(char *name
, time_t lot
, time_t hit
) 
 311         static char     loab
[MAX_STRING_LENGTH
]; 
 313         lotm 
= *localtime(&lot
); 
 314         (void) strncpy(loab
, abbr(&lotm
), (sizeof loab
) - 1); 
 315         while ((hit 
- lot
) >= 2) { 
 316                 t 
= lot 
/ 2 + hit 
/ 2; 
 322                 if (delta(&tm
, &lotm
) == (t 
- lot
) && 
 323                         tm
.tm_isdst 
== lotm
.tm_isdst 
&& 
 324                         strcmp(abbr(&tm
), loab
) == 0) { 
 329         show(name
, lot
, TRUE
); 
 330         show(name
, hit
, TRUE
); 
 335 ** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta. 
 339 delta(struct tm 
*newp
, struct tm 
*oldp
) 
 344         if (newp
->tm_year 
< oldp
->tm_year
) 
 345                 return -delta(oldp
, newp
); 
 347         for (tmy 
= oldp
->tm_year
; tmy 
< newp
->tm_year
; ++tmy
) 
 348                 result 
+= DAYSPERNYEAR 
+ isleap(tmy 
+ TM_YEAR_BASE
); 
 349         result 
+= newp
->tm_yday 
- oldp
->tm_yday
; 
 350         result 
*= HOURSPERDAY
; 
 351         result 
+= newp
->tm_hour 
- oldp
->tm_hour
; 
 352         result 
*= MINSPERHOUR
; 
 353         result 
+= newp
->tm_min 
- oldp
->tm_min
; 
 354         result 
*= SECSPERMIN
; 
 355         result 
+= newp
->tm_sec 
- oldp
->tm_sec
; 
 360 show(char *zone
, time_t t
, int v
) 
 364         (void) printf("%-*s  ", (int) longest
, zone
); 
 366                 (void) printf("%.24s UTC = ", asctime(gmtime(&t
))); 
 368         (void) printf("%.24s", asctime(tmp
)); 
 369         if (*abbr(tmp
) != '\0') 
 370                 (void) printf(" %s", abbr(tmp
)); 
 372                 (void) printf(" isdst=%d", tmp
->tm_isdst
); 
 374                 (void) printf(" gmtoff=%ld", tmp
->TM_GMTOFF
); 
 375 #endif /* defined TM_GMTOFF */ 
 386         if (tmp
->tm_isdst 
!= 0 && tmp
->tm_isdst 
!= 1) 
 388         result 
= tzname
[tmp
->tm_isdst
]; 
 389         return (result 
== NULL
) ? &nada 
: result
;