Print this page
    
6869 Update zdump to better-handle POSIX timezones
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/zdump/zdump.c
          +++ new/usr/src/cmd/zdump/zdump.c
   1    1  /*
   2    2   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   3    3   * Use is subject to license terms.
   4    4   */
   5    5  
   6      -#pragma ident   "%Z%%M% %I%     %E% SMI"
   7      -
   8    6  /*
   9    7   * zdump 7.24
  10    8   * Taken from elsie.nci.nih.gov to replace the existing Solaris zdump,
  11    9   * which was based on an earlier version of the elsie code.
  12   10   *
  13   11   * For zdump 7.24, the following changes were made to the elsie code:
  14   12   *   locale/textdomain/messages to match existing Solaris style.
  15   13   *   Solaris verbose mode is documented to display the current time first.
  16   14   *   cstyle cleaned code.
  17   15   *   removed old locale/textdomain code.
  18   16   */
  19   17  
  20   18  static char     elsieid[] = "@(#)zdump.c        7.74";
  21   19  
  22   20  /*
  23   21   * This code has been made independent of the rest of the time
  24   22   * conversion package to increase confidence in the verification it provides.
  25   23   * You can use this code to help in verifying other implementations.
  26   24   */
  27   25  
  28   26  #include "stdio.h"      /* for stdout, stderr, perror */
  29   27  #include "string.h"     /* for strcpy */
  30   28  #include "sys/types.h"  /* for time_t */
  31   29  #include "time.h"       /* for struct tm */
  32   30  #include "stdlib.h"     /* for exit, malloc, atoi */
  33   31  #include "locale.h"     /* for setlocale, textdomain */
  34   32  #include "libintl.h"
  35   33  #include <ctype.h>
  36   34  #include "tzfile.h"     /* for defines */
  37   35  #include <limits.h>
  38   36  
  39   37  #ifndef ZDUMP_LO_YEAR
  40   38  #define ZDUMP_LO_YEAR   (-500)
  41   39  #endif /* !defined ZDUMP_LO_YEAR */
  42   40  
  43   41  #ifndef ZDUMP_HI_YEAR
  44   42  #define ZDUMP_HI_YEAR   2500
  45   43  #endif /* !defined ZDUMP_HI_YEAR */
  46   44  
  47   45  #ifndef MAX_STRING_LENGTH
  48   46  #define MAX_STRING_LENGTH       1024
  49   47  #endif /* !defined MAX_STRING_LENGTH */
  50   48  
  51   49  #ifndef TRUE
  52   50  #define TRUE            1
  53   51  #endif /* !defined TRUE */
  54   52  
  55   53  #ifndef FALSE
  56   54  #define FALSE           0
  57   55  #endif /* !defined FALSE */
  58   56  
  59   57  #ifndef isleap_sum
  60   58  /*
  61   59   * See tzfile.h for details on isleap_sum.
  62   60   */
  63   61  #define isleap_sum(a, b)        isleap((a) % 400 + (b) % 400)
  64   62  #endif /* !defined isleap_sum */
  65   63  
  66   64  #ifndef SECSPERDAY
  67   65  #define SECSPERDAY      ((long)SECSPERHOUR * HOURSPERDAY)
  68   66  #endif
  69   67  #define SECSPERNYEAR    (SECSPERDAY * DAYSPERNYEAR)
  70   68  #define SECSPERLYEAR    (SECSPERNYEAR + SECSPERDAY)
  71   69  
  72   70  #ifndef GNUC_or_lint
  73   71  #ifdef lint
  74   72  #define GNUC_or_lint
  75   73  #else /* !defined lint */
  76   74  #ifdef __GNUC__
  77   75  #define GNUC_or_lint
  78   76  #endif /* defined __GNUC__ */
  79   77  #endif /* !defined lint */
  80   78  #endif /* !defined GNUC_or_lint */
  81   79  
  82   80  #ifndef INITIALIZE
  83   81  #ifdef  GNUC_or_lint
  84   82  #define INITIALIZE(x)   ((x) = 0)
  85   83  #else /* !defined GNUC_or_lint */
  86   84  #define INITIALIZE(x)
  87   85  #endif /* !defined GNUC_or_lint */
  88   86  #endif /* !defined INITIALIZE */
  89   87  
  90   88  static time_t   absolute_min_time;
  91   89  static time_t   absolute_max_time;
  92   90  static size_t   longest;
  93   91  static char     *progname;
  94   92  static int      warned;
  95   93  
  96   94  static char     *abbr(struct tm *);
  97   95  static void     abbrok(const char *, const char *);
  98   96  static long     delta(struct tm *, struct tm *);
  99   97  static void     dumptime(const struct tm *);
 100   98  static time_t   hunt(char *, time_t, time_t);
 101   99  static void     setabsolutes(void);
 102  100  static void     show(char *, time_t, int);
 103  101  static void     usage(void);
 104  102  static const char       *tformat(void);
 105  103  static time_t   yeartot(long y);
 106  104  
 107  105  #ifndef TYPECHECK
 108  106  #define my_localtime    localtime
 109  107  #else /* !defined TYPECHECK */
 110  108  static struct tm *
 111  109  my_localtime(tp)
 112  110  time_t *tp;
 113  111  {
 114  112          register struct tm *tmp;
 115  113  
 116  114          tmp = localtime(tp);
 117  115          if (tp != NULL && tmp != NULL) {
 118  116                  struct tm       tm;
 119  117                  register time_t t;
 120  118  
 121  119                  tm = *tmp;
 122  120                  t = mktime(&tm);
 123  121                  if (t - *tp >= 1 || *tp - t >= 1) {
 124  122                          (void) fflush(stdout);
 125  123                          (void) fprintf(stderr, "\n%s: ", progname);
 126  124                          (void) fprintf(stderr, tformat(), *tp);
 127  125                          (void) fprintf(stderr, " ->");
 128  126                          (void) fprintf(stderr, " year=%d", tmp->tm_year);
 129  127                          (void) fprintf(stderr, " mon=%d", tmp->tm_mon);
 130  128                          (void) fprintf(stderr, " mday=%d", tmp->tm_mday);
 131  129                          (void) fprintf(stderr, " hour=%d", tmp->tm_hour);
 132  130                          (void) fprintf(stderr, " min=%d", tmp->tm_min);
 133  131                          (void) fprintf(stderr, " sec=%d", tmp->tm_sec);
 134  132                          (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
  
    | 
      ↓ open down ↓ | 
    117 lines elided | 
    
      ↑ open up ↑ | 
  
 135  133                          (void) fprintf(stderr, " -> ");
 136  134                          (void) fprintf(stderr, tformat(), t);
 137  135                          (void) fprintf(stderr, "\n");
 138  136                  }
 139  137          }
 140  138          return (tmp);
 141  139  }
 142  140  #endif /* !defined TYPECHECK */
 143  141  
 144  142  static void
 145      -abbrok(abbrp, zone)
 146      -const char * const      abbrp;
 147      -const char * const      zone;
      143 +abbrok(const char * const abbrp, const char * const zone)
 148  144  {
 149  145          register const char *cp;
 150  146          int error = 0;
 151  147  
 152  148          if (warned)
 153  149                  return;
 154  150          cp = abbrp;
 155      -        while (isascii(*cp) && isalpha((unsigned char)*cp))
      151 +        while (isalpha(*cp) || isdigit(*cp) || *cp == '-' || *cp == '+')
 156  152                  ++cp;
 157  153          (void) fflush(stdout);
 158      -        if (cp - abbrp == 0) {
 159      -                /*
 160      -                 * TRANSLATION_NOTE
 161      -                 * The first %s prints for the program name (zdump),
 162      -                 * the second %s prints the timezone name, the third
 163      -                 * %s prints the timezone abbreviation (tzname[0] or
 164      -                 * tzname[1]).
 165      -                 */
      154 +        if (cp - abbrp < 3) {
 166  155                  (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
 167      -                    "abbreviation \"%s\" lacks alphabetic at start\n"),
 168      -                    progname, zone, abbrp);
 169      -                error = 1;
 170      -        } else if (cp - abbrp < 3) {
 171      -                (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
 172  156                      "abbreviation \"%s\" has fewer than 3 alphabetics\n"),
 173  157                      progname, zone, abbrp);
 174  158                  error = 1;
 175  159          } else if (cp - abbrp > 6) {
 176  160                  (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
 177      -                    "abbreviation \"%s\" has more than 6 alphabetics\n"),
      161 +                    "abbreviation \"%s\" has more than 6 characters\n"),
 178  162                      progname, zone, abbrp);
 179  163                  error = 1;
      164 +        } else if (*cp != '\0') {
      165 +                (void) fprintf(stderr, gettext("%s: warning: zone \"%s\" "
      166 +                    "abbreviation \"%s\" has characters other than "
      167 +                    "alphanumerics\n"), progname, zone, abbrp);
      168 +                error = 1;
 180  169          }
 181      -        if (error == 0 && (*cp == '+' || *cp == '-')) {
 182      -                ++cp;
 183      -                if (isascii(*cp) && isdigit((unsigned char)*cp))
 184      -                        if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
 185      -                                ++cp;
 186      -                if (*cp != '\0') {
 187      -                        (void) fprintf(stderr, gettext("%s: warning: "
 188      -                            "zone \"%s\" abbreviation \"%s\" differs from "
 189      -                            "POSIX standard\n"), progname, zone, abbrp);
 190      -                        error = 1;
 191      -                }
 192      -        }
 193  170          if (error)
 194  171                  warned = TRUE;
 195  172  }
 196  173  
 197  174  int
 198  175  main(argc, argv)
 199  176  int     argc;
 200  177  char    *argv[];
 201  178  {
 202  179          register int            i;
 203  180          register int            c;
 204  181          register int            vflag;
 205  182          register char           *cutarg;
 206  183          register long           cutloyear = ZDUMP_LO_YEAR;
 207  184          register long           cuthiyear = ZDUMP_HI_YEAR;
 208  185          register time_t         cutlotime;
 209  186          register time_t         cuthitime;
 210  187          time_t                  now;
 211  188          time_t                  t;
 212  189          time_t                  newt;
 213  190          struct tm               tm;
 214  191          struct tm               newtm;
 215  192          register struct tm      *tmp;
 216  193          register struct tm      *newtmp;
 217  194  
 218  195          INITIALIZE(cutlotime);
 219  196          INITIALIZE(cuthitime);
 220  197  
 221  198          (void) setlocale(LC_ALL, "");
 222  199  #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 223  200  #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it weren't */
 224  201  #endif
 225  202          (void) textdomain(TEXT_DOMAIN);
 226  203  
 227  204          progname = argv[0];
 228  205          for (i = 1; i < argc; ++i)
 229  206                  if (strcmp(argv[i], "--version") == 0) {
 230  207                          (void) printf("%s\n", elsieid);
 231  208                          exit(EXIT_SUCCESS);
 232  209                  }
 233  210          vflag = 0;
 234  211          cutarg = NULL;
 235  212          while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
 236  213                  if (c == 'v')
 237  214                          vflag = 1;
 238  215                  else    cutarg = optarg;
 239  216          if (c != EOF ||
 240  217                  (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
 241  218                          usage();
 242  219                          /* NOTREACHED */
 243  220          }
 244  221          if (vflag) {
 245  222                  if (cutarg != NULL) {
 246  223                          long    lo;
 247  224                          long    hi;
 248  225                          char    dummy;
 249  226  
 250  227                          if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
 251  228                                  cuthiyear = hi;
 252  229                          } else if (sscanf(cutarg, "%ld,%ld%c",
 253  230                                  &lo, &hi, &dummy) == 2) {
 254  231                                          cutloyear = lo;
 255  232                                          cuthiyear = hi;
 256  233                          } else {
 257  234  (void) fprintf(stderr, gettext("%s: wild -c argument %s\n"),
 258  235                                          progname, cutarg);
 259  236                                  exit(EXIT_FAILURE);
 260  237                          }
 261  238                  }
 262  239                  setabsolutes();
 263  240                  cutlotime = yeartot(cutloyear);
 264  241                  cuthitime = yeartot(cuthiyear);
 265  242          }
 266  243          (void) time(&now);
 267  244          longest = 0;
 268  245          for (i = optind; i < argc; ++i)
 269  246                  if (strlen(argv[i]) > longest)
 270  247                          longest = strlen(argv[i]);
 271  248  
 272  249          for (i = optind; i < argc; ++i) {
 273  250                  static char     buf[MAX_STRING_LENGTH];
 274  251                  static char     *tzp = NULL;
 275  252  
 276  253                  (void) unsetenv("TZ");
 277  254                  if (tzp != NULL)
 278  255                          free(tzp);
 279  256                  if ((tzp = malloc(3 + strlen(argv[i]) + 1)) == NULL) {
 280  257                          perror(progname);
 281  258                          exit(EXIT_FAILURE);
 282  259                  }
 283  260                  (void) strcpy(tzp, "TZ=");
 284  261                  (void) strcat(tzp, argv[i]);
 285  262                  if (putenv(tzp) != 0) {
 286  263                          perror(progname);
 287  264                          exit(EXIT_FAILURE);
 288  265                  }
 289  266                  if (!vflag) {
 290  267                          show(argv[i], now, FALSE);
 291  268                          continue;
 292  269                  }
 293  270  
 294  271  #if defined(sun)
 295  272                  /*
 296  273                   * We show the current time first, probably because we froze
 297  274                   * the behavior of zdump some time ago and then it got
 298  275                   * changed.
 299  276                   */
 300  277                  show(argv[i], now, TRUE);
 301  278  #endif
 302  279                  warned = FALSE;
 303  280                  t = absolute_min_time;
 304  281                  show(argv[i], t, TRUE);
 305  282                  t += SECSPERHOUR * HOURSPERDAY;
 306  283                  show(argv[i], t, TRUE);
 307  284                  if (t < cutlotime)
 308  285                          t = cutlotime;
 309  286                  tmp = my_localtime(&t);
 310  287                  if (tmp != NULL) {
 311  288                          tm = *tmp;
 312  289                          (void) strncpy(buf, abbr(&tm), sizeof (buf) - 1);
 313  290                  }
 314  291                  for (;;) {
 315  292                          if (t >= cuthitime)
 316  293                                  break;
 317  294                          /* check if newt will overrun maximum time_t value */
 318  295                          if (t > LONG_MAX - (SECSPERHOUR * 12))
 319  296                                  break;
 320  297                          newt = t + SECSPERHOUR * 12;
 321  298                          if (newt >= cuthitime)
 322  299                                  break;
 323  300                          newtmp = localtime(&newt);
 324  301                          if (newtmp != NULL)
 325  302                                  newtm = *newtmp;
 326  303                          if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
 327  304                                  (delta(&newtm, &tm) != (newt - t) ||
 328  305                                  newtm.tm_isdst != tm.tm_isdst ||
 329  306                                  strcmp(abbr(&newtm), buf) != 0)) {
 330  307                                          newt = hunt(argv[i], t, newt);
 331  308                                          newtmp = localtime(&newt);
 332  309                                          if (newtmp != NULL) {
 333  310                                                  newtm = *newtmp;
 334  311                                                  (void) strncpy(buf,
 335  312                                                          abbr(&newtm),
 336  313                                                          sizeof (buf) - 1);
 337  314                                          }
 338  315                          }
 339  316                          t = newt;
 340  317                          tm = newtm;
 341  318                          tmp = newtmp;
 342  319                  }
 343  320                  t = absolute_max_time;
 344  321  #if defined(sun)
 345  322                  show(argv[i], t, TRUE);
 346  323                  t -= SECSPERHOUR * HOURSPERDAY;
 347  324                  show(argv[i], t, TRUE);
 348  325  #else /* !defined(sun) */
 349  326                  t -= SECSPERHOUR * HOURSPERDAY;
 350  327                  show(argv[i], t, TRUE);
 351  328                  t += SECSPERHOUR * HOURSPERDAY;
 352  329                  show(argv[i], t, TRUE);
 353  330  #endif /* !defined(sun) */
 354  331          }
 355  332          if (fflush(stdout) || ferror(stdout)) {
 356  333                  (void) fprintf(stderr, "%s: ", progname);
 357  334                  (void) perror(gettext("Error writing standard output"));
 358  335                  exit(EXIT_FAILURE);
 359  336          }
 360  337          return (EXIT_SUCCESS);
 361  338  }
 362  339  
 363  340  static void
 364  341  setabsolutes()
 365  342  {
 366  343  #if defined(sun)
 367  344          absolute_min_time = LONG_MIN;
 368  345          absolute_max_time = LONG_MAX;
 369  346  #else
 370  347          if (0.5 == (time_t)0.5) {
 371  348                  /*
 372  349                   * time_t is floating.
 373  350                   */
 374  351                  if (sizeof (time_t) == sizeof (float)) {
 375  352                          absolute_min_time = (time_t)-FLT_MAX;
 376  353                          absolute_max_time = (time_t)FLT_MAX;
 377  354                  } else if (sizeof (time_t) == sizeof (double)) {
 378  355                          absolute_min_time = (time_t)-DBL_MAX;
 379  356                          absolute_max_time = (time_t)DBL_MAX;
 380  357                  } else {
 381  358                          (void) fprintf(stderr, gettext("%s: use of -v on "
 382  359                              "system with floating time_t other than float "
 383  360                              "or double\n"), progname);
 384  361                          exit(EXIT_FAILURE);
 385  362                  }
 386  363          } else
 387  364          /*CONSTANTCONDITION*/
 388  365          if (0 > (time_t)-1) {
 389  366                  /*
 390  367                   * time_t is signed.
 391  368                   */
 392  369                  register time_t hibit;
 393  370  
 394  371                  for (hibit = 1; (hibit * 2) != 0; hibit *= 2)
 395  372                          continue;
 396  373                  absolute_min_time = hibit;
 397  374                  absolute_max_time = -(hibit + 1);
 398  375          } else {
 399  376                  /*
 400  377                   * time_t is unsigned.
 401  378                   */
 402  379                  absolute_min_time = 0;
 403  380                  absolute_max_time = absolute_min_time - 1;
 404  381          }
 405  382  #endif
 406  383  }
 407  384  
 408  385  static time_t
 409  386  yeartot(y)
 410  387  const long      y;
 411  388  {
 412  389          register long   myy;
 413  390          register long   seconds;
 414  391          register time_t t;
 415  392  
 416  393          myy = EPOCH_YEAR;
 417  394          t = 0;
 418  395          while (myy != y) {
 419  396                  if (myy < y) {
 420  397                          seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
 421  398                          ++myy;
 422  399                          if (t > absolute_max_time - seconds) {
 423  400                                  t = absolute_max_time;
 424  401                                  break;
 425  402                          }
 426  403                          t += seconds;
 427  404                  } else {
 428  405                          --myy;
 429  406                          seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
 430  407                          if (t < absolute_min_time + seconds) {
 431  408                                  t = absolute_min_time;
 432  409                                  break;
 433  410                          }
 434  411                          t -= seconds;
 435  412                  }
 436  413          }
 437  414          return (t);
 438  415  }
 439  416  
 440  417  static time_t
 441  418  hunt(name, lot, hit)
 442  419  char    *name;
 443  420  time_t  lot;
 444  421  time_t  hit;
 445  422  {
 446  423          time_t                  t;
 447  424          long                    diff;
 448  425          struct tm               lotm;
 449  426          register struct tm      *lotmp;
 450  427          struct tm               tm;
 451  428          register struct tm      *tmp;
 452  429          char                    loab[MAX_STRING_LENGTH];
 453  430  
 454  431          lotmp = my_localtime(&lot);
 455  432          if (lotmp != NULL) {
 456  433                  lotm = *lotmp;
 457  434                  (void) strncpy(loab, abbr(&lotm), sizeof (loab) - 1);
 458  435          }
 459  436          for (;;) {
 460  437                  diff = (long)(hit - lot);
 461  438                  if (diff < 2)
 462  439                          break;
 463  440                  t = lot;
 464  441                  t += diff / 2;
 465  442                  if (t <= lot)
 466  443                          ++t;
 467  444                  else if (t >= hit)
 468  445                          --t;
 469  446                  tmp = my_localtime(&t);
 470  447                  if (tmp != NULL)
 471  448                          tm = *tmp;
 472  449                  if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
 473  450                          (delta(&tm, &lotm) == (t - lot) &&
 474  451                          tm.tm_isdst == lotm.tm_isdst &&
 475  452                          strcmp(abbr(&tm), loab) == 0)) {
 476  453                                  lot = t;
 477  454                                  lotm = tm;
 478  455                                  lotmp = tmp;
 479  456                  } else  hit = t;
 480  457          }
 481  458          show(name, lot, TRUE);
 482  459          show(name, hit, TRUE);
 483  460          return (hit);
 484  461  }
 485  462  
 486  463  /*
 487  464   * Thanks to Paul Eggert for logic used in delta.
 488  465   */
 489  466  
 490  467  static long
 491  468  delta(newp, oldp)
 492  469  struct tm       *newp;
 493  470  struct tm       *oldp;
 494  471  {
 495  472          register long   result;
 496  473          register int    tmy;
 497  474  
 498  475          if (newp->tm_year < oldp->tm_year)
 499  476                  return (-delta(oldp, newp));
 500  477          result = 0;
 501  478          for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
 502  479                  result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
 503  480          result += newp->tm_yday - oldp->tm_yday;
 504  481          result *= HOURSPERDAY;
 505  482          result += newp->tm_hour - oldp->tm_hour;
 506  483          result *= MINSPERHOUR;
 507  484          result += newp->tm_min - oldp->tm_min;
 508  485          result *= SECSPERMIN;
 509  486          result += newp->tm_sec - oldp->tm_sec;
 510  487          return (result);
 511  488  }
 512  489  
 513  490  static void
 514  491  show(zone, t, v)
 515  492  char    *zone;
 516  493  time_t  t;
 517  494  int     v;
 518  495  {
 519  496          register struct tm      *tmp;
 520  497  
 521  498          (void) printf("%-*s  ", (int)longest, zone);
 522  499          if (v) {
 523  500                  tmp = gmtime(&t);
 524  501                  if (tmp == NULL) {
 525  502                          (void) printf(tformat(), t);
 526  503                  } else {
 527  504                          dumptime(tmp);
 528  505                          (void) printf(" UTC");
 529  506                  }
 530  507                  (void) printf(" = ");
 531  508          }
 532  509          tmp = my_localtime(&t);
 533  510          dumptime(tmp);
 534  511          if (tmp != NULL) {
 535  512                  if (*abbr(tmp) != '\0')
 536  513                          (void) printf(" %s", abbr(tmp));
 537  514                  if (v) {
 538  515                          (void) printf(" isdst=%d", tmp->tm_isdst);
 539  516  #ifdef TM_GMTOFF
 540  517                          (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
 541  518  #endif /* defined TM_GMTOFF */
 542  519                  }
 543  520          }
 544  521          (void) printf("\n");
 545  522          if (tmp != NULL && *abbr(tmp) != '\0')
 546  523                  abbrok(abbr(tmp), zone);
 547  524  }
 548  525  
 549  526  static char *
 550  527  abbr(tmp)
 551  528  struct tm       *tmp;
 552  529  {
 553  530          register char   *result;
 554  531          static char     nada;
 555  532  
 556  533          if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
 557  534                  return (&nada);
 558  535          result = tzname[tmp->tm_isdst];
 559  536          return ((result == NULL) ? &nada : result);
 560  537  }
 561  538  
 562  539  /*
 563  540   * The code below can fail on certain theoretical systems;
 564  541   * it works on all known real-world systems as of 2004-12-30.
 565  542   */
 566  543  
 567  544  static const char *
 568  545  tformat()
 569  546  {
 570  547  #if defined(sun)
 571  548          /* time_t is signed long */
 572  549          return ("%ld");
 573  550  #else
 574  551          /*CONSTANTCONDITION*/
 575  552          if (0.5 == (time_t)0.5) {       /* floating */
 576  553                  /*CONSTANTCONDITION*/
 577  554                  if (sizeof (time_t) > sizeof (double))
 578  555                          return ("%Lg");
 579  556                  return ("%g");
 580  557          }
 581  558          /*CONSTANTCONDITION*/
 582  559          if (0 > (time_t)-1) {           /* signed */
 583  560                  /*CONSTANTCONDITION*/
 584  561                  if (sizeof (time_t) > sizeof (long))
 585  562                          return ("%lld");
 586  563                  /*CONSTANTCONDITION*/
 587  564                  if (sizeof (time_t) > sizeof (int))
 588  565                          return ("%ld");
 589  566                  return ("%d");
 590  567          }
 591  568          /*CONSTANTCONDITION*/
 592  569          if (sizeof (time_t) > sizeof (unsigned long))
 593  570                  return ("%llu");
 594  571          /*CONSTANTCONDITION*/
 595  572          if (sizeof (time_t) > sizeof (unsigned int))
 596  573                  return ("%lu");
 597  574          return ("%u");
 598  575  #endif
 599  576  }
 600  577  
 601  578  static void
 602  579  dumptime(timeptr)
 603  580  register const struct tm        *timeptr;
 604  581  {
 605  582          static const char       wday_name[][3] = {
 606  583                  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 607  584          };
 608  585          static const char       mon_name[][3] = {
 609  586                  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 610  587                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 611  588          };
 612  589          register const char     *wn;
 613  590          register const char     *mn;
 614  591          register int            lead;
 615  592          register int            trail;
 616  593  
 617  594          if (timeptr == NULL) {
 618  595                  (void) printf("NULL");
 619  596                  return;
 620  597          }
 621  598          /*
 622  599           * The packaged versions of localtime and gmtime never put out-of-range
 623  600           * values in tm_wday or tm_mon, but since this code might be compiled
 624  601           * with other (perhaps experimental) versions, paranoia is in order.
 625  602           */
 626  603          if (timeptr->tm_wday < 0 || timeptr->tm_wday >=
 627  604                  (int)(sizeof (wday_name) / sizeof (wday_name[0])))
 628  605                          wn = "???";
 629  606          else            wn = wday_name[timeptr->tm_wday];
 630  607          if (timeptr->tm_mon < 0 || timeptr->tm_mon >=
 631  608                  (int)(sizeof (mon_name) / sizeof (mon_name[0])))
 632  609                          mn = "???";
 633  610          else            mn = mon_name[timeptr->tm_mon];
 634  611          (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
 635  612                  wn, mn,
 636  613                  timeptr->tm_mday, timeptr->tm_hour,
 637  614                  timeptr->tm_min, timeptr->tm_sec);
 638  615  #define DIVISOR 10
 639  616          trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
 640  617          lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
 641  618                  trail / DIVISOR;
 642  619          trail %= DIVISOR;
 643  620          if (trail < 0 && lead > 0) {
 644  621                  trail += DIVISOR;
 645  622                  --lead;
 646  623          } else if (lead < 0 && trail > 0) {
 647  624                  trail -= DIVISOR;
 648  625                  ++lead;
 649  626          }
 650  627          if (lead == 0)
 651  628                  (void) printf("%d", trail);
 652  629          else
 653  630                  (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
 654  631  }
 655  632  
 656  633  static void
 657  634  usage()
 658  635  {
 659  636          (void) fprintf(stderr, gettext(
 660  637              "%s: [ --version ] [ -v ] [ -c [loyear,]hiyear ] zonename ...\n"),
 661  638                  progname);
 662  639          exit(EXIT_FAILURE);
 663  640          /* NOTREACHED */
 664  641  }
  
    | 
      ↓ open down ↓ | 
    462 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX