"Fossies" - the Fresh Open Source Software Archive

Member "date.c" (21 Nov 2022, 5469 Bytes) of package /linux/misc/tzcode2022g.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "date.c": 2022f_vs_2022g.

    1 /* Display or set the current time and date.  */
    2 
    3 /* Copyright 1985, 1987, 1988 The Regents of the University of California.
    4    All rights reserved.
    5 
    6    Redistribution and use in source and binary forms, with or without
    7    modification, are permitted provided that the following conditions
    8    are met:
    9    1. Redistributions of source code must retain the above copyright
   10       notice, this list of conditions and the following disclaimer.
   11    2. Redistributions in binary form must reproduce the above copyright
   12       notice, this list of conditions and the following disclaimer in the
   13       documentation and/or other materials provided with the distribution.
   14    3. Neither the name of the University nor the names of its contributors
   15       may be used to endorse or promote products derived from this software
   16       without specific prior written permission.
   17 
   18    THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
   19    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21    ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28    SUCH DAMAGE.  */
   29 
   30 #include "private.h"
   31 #include <locale.h>
   32 #include <stdio.h>
   33 
   34 #if !HAVE_POSIX_DECLS
   35 extern char *       optarg;
   36 extern int      optind;
   37 #endif
   38 
   39 static int      retval = EXIT_SUCCESS;
   40 
   41 static void     display(const char *, time_t);
   42 static void     dogmt(void);
   43 static void     errensure(void);
   44 static void     timeout(FILE *, const char *, const struct tm *);
   45 static ATTRIBUTE_NORETURN void usage(void);
   46 
   47 int
   48 main(const int argc, char *argv[])
   49 {
   50     register const char *   format = "+%+";
   51     register int        ch;
   52     register bool       rflag = false;
   53     time_t          t;
   54     intmax_t        secs;
   55     char *          endarg;
   56 
   57 #ifdef LC_ALL
   58     setlocale(LC_ALL, "");
   59 #endif /* defined(LC_ALL) */
   60 #if HAVE_GETTEXT
   61 # ifdef TZ_DOMAINDIR
   62     bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
   63 # endif /* defined(TEXTDOMAINDIR) */
   64     textdomain(TZ_DOMAIN);
   65 #endif /* HAVE_GETTEXT */
   66     t = time(NULL);
   67     while ((ch = getopt(argc, argv, "ucr:")) != EOF && ch != -1) {
   68         switch (ch) {
   69         default:
   70             usage();
   71         case 'u':       /* do it in UT */
   72         case 'c':
   73             dogmt();
   74             break;
   75         case 'r':       /* seconds since 1970 */
   76             if (rflag) {
   77                 fprintf(stderr,
   78                     _("date: error: multiple -r's used"));
   79                 usage();
   80             }
   81             rflag = true;
   82             errno = 0;
   83             secs = strtoimax(optarg, &endarg, 0);
   84             if (*endarg || optarg == endarg)
   85                 errno = EINVAL;
   86             else if (! (TIME_T_MIN <= secs && secs <= TIME_T_MAX))
   87                 errno = ERANGE;
   88             if (errno) {
   89                 perror(optarg);
   90                 errensure();
   91                 exit(retval);
   92             }
   93             t = secs;
   94             break;
   95         }
   96     }
   97     if (optind < argc) {
   98       if (argc - optind != 1) {
   99         fprintf(stderr,
  100             _("date: error: multiple operands in command line\n"));
  101         usage();
  102       }
  103       format = argv[optind];
  104       if (*format != '+') {
  105         fprintf(stderr, _("date: unknown operand: %s\n"), format);
  106         usage();
  107       }
  108     }
  109 
  110     display(format, t);
  111     return retval;
  112 }
  113 
  114 static void
  115 dogmt(void)
  116 {
  117     static char **  fakeenv;
  118 
  119     if (fakeenv == NULL) {
  120         static char tzeutc0[] = "TZ=UTC0";
  121         ptrdiff_t from, to, n;
  122 
  123         for (n = 0;  environ[n] != NULL;  ++n)
  124             continue;
  125 #if defined ckd_add && defined ckd_mul
  126         if (!ckd_add(&n, n, 2) && !ckd_mul(&n, n, sizeof *fakeenv)
  127             && n <= SIZE_MAX)
  128           fakeenv = malloc(n);
  129 #else
  130         if (n <= min(PTRDIFF_MAX, SIZE_MAX) / sizeof *fakeenv - 2)
  131           fakeenv = malloc((n + 2) * sizeof *fakeenv);
  132 #endif
  133         if (fakeenv == NULL) {
  134             fprintf(stderr, _("date: Memory exhausted\n"));
  135             errensure();
  136             exit(retval);
  137         }
  138         to = 0;
  139         fakeenv[to++] = tzeutc0;
  140         for (from = 1; environ[from] != NULL; ++from)
  141             if (strncmp(environ[from], "TZ=", 3) != 0)
  142                 fakeenv[to++] = environ[from];
  143         fakeenv[to] = NULL;
  144         environ = fakeenv;
  145     }
  146 }
  147 
  148 static void
  149 errensure(void)
  150 {
  151     if (retval == EXIT_SUCCESS)
  152         retval = EXIT_FAILURE;
  153 }
  154 
  155 static void
  156 usage(void)
  157 {
  158     fprintf(stderr,
  159                _("date: usage: date [-u] [-c] [-r seconds]"
  160              " [+format]\n"));
  161     errensure();
  162     exit(retval);
  163 }
  164 
  165 static void
  166 display(char const *format, time_t now)
  167 {
  168     struct tm *tmp;
  169 
  170     tmp = localtime(&now);
  171     if (!tmp) {
  172         fprintf(stderr,
  173             _("date: error: time out of range\n"));
  174         errensure();
  175         return;
  176     }
  177     timeout(stdout, format, tmp);
  178     putchar('\n');
  179     fflush(stdout);
  180     fflush(stderr);
  181     if (ferror(stdout) || ferror(stderr)) {
  182         fprintf(stderr,
  183             _("date: error: couldn't write results\n"));
  184         errensure();
  185     }
  186 }
  187 
  188 static void
  189 timeout(FILE *fp, char const *format, struct tm const *tmp)
  190 {
  191     char *cp = NULL;
  192     ptrdiff_t result;
  193     ptrdiff_t size = 1024 / 2;
  194 
  195     for ( ; ; ) {
  196 #ifdef ckd_mul
  197         bool bigger = !ckd_mul(&size, size, 2) && size <= SIZE_MAX;
  198 #else
  199         bool bigger = (size <= min(PTRDIFF_MAX, SIZE_MAX) / 2
  200                    && (size *= 2, true));
  201 #endif
  202         char *newcp = bigger ? realloc(cp, size) : NULL;
  203         if (!newcp) {
  204             fprintf(stderr,
  205                 _("date: error: can't get memory\n"));
  206             errensure();
  207             exit(retval);
  208         }
  209         cp = newcp;
  210         result = strftime(cp, size, format, tmp);
  211         if (result != 0)
  212             break;
  213     }
  214     fwrite(cp + 1, 1, result - 1, fp);
  215     free(cp);
  216 }