"Fossies" - the Fresh Open Source Software Archive 
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 }