Fixed license declaration at spec file
[platform/upstream/tzdata.git] / date.c
1 /*
2  * Copyright (c) 1985, 1987, 1988 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17
18 #include "private.h"
19 #include "locale.h"
20
21 /*
22 ** The two things date knows about time are. . .
23 */
24
25 #ifndef TM_YEAR_BASE
26 #define TM_YEAR_BASE    1900
27 #endif /* !defined TM_YEAR_BASE */
28
29 #ifndef SECSPERMIN
30 #define SECSPERMIN      60
31 #endif /* !defined SECSPERMIN */
32
33 extern char **          environ;
34 extern char *           optarg;
35 extern int              optind;
36 extern char *           tzname[2];
37
38 static int              retval = EXIT_SUCCESS;
39
40 static void             display(const char *, time_t);
41 static void             dogmt(void);
42 static void             errensure(void);
43 static void             timeout(FILE *, const char *, const struct tm *);
44 static void             usage(void);
45
46 int
47 main(const int argc, char *argv[])
48 {
49         register const char *   format;
50         register const char *   cp;
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         format = NULL;
68         while ((ch = getopt(argc, argv, "ucr:")) != EOF && ch != -1) {
69                 switch (ch) {
70                 default:
71                         usage();
72                 case 'u':               /* do it in UT */
73                 case 'c':
74                         dogmt();
75                         break;
76                 case 'r':               /* seconds since 1970 */
77                         if (rflag) {
78                                 fprintf(stderr,
79                                         _("date: error: multiple -r's used"));
80                                 usage();
81                         }
82                         rflag = true;
83                         errno = 0;
84                         secs = strtoimax (optarg, &endarg, 0);
85                         if (*endarg || optarg == endarg)
86                                 errno = EINVAL;
87                         else if (! (time_t_min <= secs && secs <= time_t_max))
88                                 errno = ERANGE;
89                         if (errno) {
90                                 perror(optarg);
91                                 errensure();
92                                 exit(retval);
93                         }
94                         t = secs;
95                         break;
96                 }
97         }
98         while (optind < argc) {
99                 cp = argv[optind++];
100                 if (*cp == '+')
101                         if (format == NULL)
102                                 format = cp + 1;
103                         else {
104                                 fprintf(stderr,
105 _("date: error: multiple formats in command line\n"));
106                                 usage();
107                         }
108                 else {
109                   fprintf(stderr, _("date: unknown operand: %s\n"), cp);
110                   usage();
111                 }
112         }
113
114         display(format, t);
115         return retval;
116 }
117
118 static void
119 dogmt(void)
120 {
121         static char **  fakeenv;
122
123         if (fakeenv == NULL) {
124                 register int    from;
125                 register int    to;
126                 register int    n;
127                 static char     tzegmt0[] = "TZ=GMT0";
128
129                 for (n = 0;  environ[n] != NULL;  ++n)
130                         continue;
131                 fakeenv = malloc((n + 2) * sizeof *fakeenv);
132                 if (fakeenv == NULL) {
133                         perror(_("Memory exhausted"));
134                         errensure();
135                         exit(retval);
136                 }
137                 to = 0;
138                 fakeenv[to++] = tzegmt0;
139                 for (from = 1; environ[from] != NULL; ++from)
140                         if (strncmp(environ[from], "TZ=", 3) != 0)
141                                 fakeenv[to++] = environ[from];
142                 fakeenv[to] = NULL;
143                 environ = fakeenv;
144         }
145 }
146
147 static void
148 errensure(void)
149 {
150         if (retval == EXIT_SUCCESS)
151                 retval = EXIT_FAILURE;
152 }
153
154 static void
155 usage(void)
156 {
157         fprintf(stderr,
158                        _("date: usage: date [-u] [-c] [-r seconds]"
159                          " [+format]\n"));
160         errensure();
161         exit(retval);
162 }
163
164 static void
165 display(char const *format, time_t now)
166 {
167         struct tm *tmp;
168
169         tmp = localtime(&now);
170         if (!tmp) {
171                 fprintf(stderr,
172                         _("date: error: time out of range\n"));
173                 errensure();
174                 return;
175         }
176         timeout(stdout, format ? format : "%+", tmp);
177         putchar('\n');
178         fflush(stdout);
179         fflush(stderr);
180         if (ferror(stdout) || ferror(stderr)) {
181                 fprintf(stderr,
182                         _("date: error: couldn't write results\n"));
183                 errensure();
184         }
185 }
186
187 #define INCR    1024
188
189 static void
190 timeout(FILE *fp, char const *format, struct tm const *tmp)
191 {
192         char *  cp;
193         size_t  result;
194         size_t  size;
195         struct tm tm;
196
197         if (*format == '\0')
198                 return;
199         if (!tmp) {
200                 fprintf(stderr, _("date: error: time out of range\n"));
201                 errensure();
202                 return;
203         }
204         tm = *tmp;
205         tmp = &tm;
206         size = INCR;
207         cp = malloc(size);
208         for ( ; ; ) {
209                 if (cp == NULL) {
210                         fprintf(stderr,
211                                 _("date: error: can't get memory\n"));
212                         errensure();
213                         exit(retval);
214                 }
215                 cp[0] = '\1';
216                 result = strftime(cp, size, format, tmp);
217                 if (result != 0 || cp[0] == '\0')
218                         break;
219                 size += INCR;
220                 cp = realloc(cp, size);
221         }
222         fwrite(cp, 1, result, fp);
223         free(cp);
224 }