]> git.saurik.com Git - apple/shell_cmds.git/blob - date/date.c
shell_cmds-81.1.tar.gz
[apple/shell_cmds.git] / date / date.c
1 /* $NetBSD: date.c,v 1.25 1998/07/28 11:41:47 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1985, 1987, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __COPYRIGHT(
39 "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
40 The Regents of the University of California. All rights reserved.\n");
41 #endif /* not lint */
42
43 #ifndef lint
44 #if 0
45 static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
46 #else
47 __RCSID("$NetBSD: date.c,v 1.25 1998/07/28 11:41:47 mycroft Exp $");
48 #endif
49 #endif /* not lint */
50
51 #include <sys/param.h>
52 #include <sys/time.h>
53
54 #include <ctype.h>
55 #include <err.h>
56 #include <fcntl.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <locale.h>
61 #include <syslog.h>
62 #include <time.h>
63 #include <tzfile.h>
64 #include <unistd.h>
65 #include <util.h>
66
67 #include "get_compat.h"
68
69 #include "extern.h"
70
71 time_t tval;
72 int nflag;
73 int retval = 0;
74 int unix2003_std = 0; /* to determine legacy vs std mode */
75
76 int main __P((int, char *[]));
77 static void setthetime __P((char *));
78 static void badformat __P((void));
79 static void badtime __P((void));
80 static void usage __P((void));
81
82 int
83 main(argc, argv)
84 int argc;
85 char *argv[];
86 {
87 extern int optind;
88 extern char *optarg;
89 int ch, rflag;
90 char *format, buf[1024];
91
92 (void)setlocale(LC_ALL, "");
93
94 if (compat_mode("bin/date", "unix2003")) /* Determine the STD */
95 unix2003_std = 1;
96 else
97 unix2003_std = 0;
98
99 rflag = 0;
100 while ((ch = getopt(argc, argv, "nr:u")) != -1)
101 switch((char)ch) {
102 case 'n': /* don't set network */
103 nflag = 1;
104 break;
105 case 'r': /* user specified seconds */
106 rflag = 1;
107 tval = atol(optarg);
108 break;
109 case 'u': /* do everything in GMT */
110 (void)setenv("TZ", "GMT0", 1);
111 break;
112 default:
113 usage();
114 }
115 argc -= optind;
116 argv += optind;
117
118 if (!rflag && time(&tval) == -1)
119 err(1, "time");
120
121 format = "%a %b %e %H:%M:%S %Z %Y";
122
123 /* allow the operands in any order */
124 if (*argv && **argv == '+') {
125 format = *argv + 1;
126 ++argv;
127 }
128
129 if (*argv) {
130 setthetime(*argv);
131 ++argv;
132 }
133
134 if (*argv && **argv == '+')
135 format = *argv + 1;
136
137 (void)strftime(buf, sizeof(buf), format, localtime(&tval));
138 (void)printf("%s\n", buf);
139
140 /* if date/time could not be set/notified in the other hosts as
141 determined by netsetval() a return value 2 is set, which is
142 to be propogated back to shell in the legacy mode.
143 */
144 if( unix2003_std )
145 exit(0); /* set/notify time thru NTPD isn't stds */
146 else
147 exit(retval); /* Propogate the error condition set, if any */
148 }
149
150 #define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
151
152 void
153 setthetime(p)
154 char *p;
155 {
156
157 struct tm *lt;
158 struct timeval tv;
159 const char *dot, *t;
160 int yearset, len;
161
162 char tmp1_p[5] = ""; /* to hold ccyy and reformat */
163 char tmp2_p[16] = ""; /* ccyyMMddhhmm.ss is 15 chars */
164
165 for (t = p, dot = NULL; *t; ++t) {
166 if (isdigit(*t))
167 continue;
168 if (*t == '.' && dot == NULL) {
169 dot = t;
170 continue;
171 }
172 badformat();
173 }
174
175 lt = localtime(&tval);
176
177 lt->tm_isdst = -1; /* Divine correct DST */
178
179 if (dot != NULL) { /* .ss */
180 len = strlen(dot);
181 if (len != 3)
182 badformat();
183 ++dot;
184 lt->tm_sec = ATOI2(dot);
185 } else {
186 len = 0;
187 lt->tm_sec = 0;
188 }
189
190 yearset = 0;
191
192 switch (strlen(p) - len) {
193 case 12: /* cc */
194 if(unix2003_std) {
195 /* The last 4 chars are ccyy;
196 reformat it to be in the first */
197 strncpy(tmp1_p, &p[8], 4);
198 tmp1_p[4] = '\0';
199 p[8] = '\0'; /* .ss already processed; so no harm */
200 strcpy(tmp2_p, p);
201 strcpy(p, tmp1_p);
202 strcat(p, tmp2_p);
203 }
204
205 lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
206 yearset = 1;
207 /* FALLTHROUGH */
208 case 10: /* yy */
209 if(unix2003_std) {
210 /* The last 2 chars are yy; reformat it to be in the
211 first, only if already not done. */
212 if (tmp1_p[0] == '\0') {
213 strncpy(tmp1_p, &p[8], 2);
214 tmp1_p[2] = '\0';
215 p[8] = '\0'; /* .ss done; so no harm */
216 strcpy(tmp2_p, p);
217 strcpy(p, tmp1_p);
218 strcat(p, tmp2_p);
219 } else
220 ; /* do nothing, already reformatted */
221 }
222
223 if (yearset) {
224 lt->tm_year += ATOI2(p);
225 } else {
226 yearset = ATOI2(p);
227 if (yearset < 69)
228 lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
229 else
230 lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
231 }
232 /* FALLTHROUGH */
233 case 8: /* mm */
234 lt->tm_mon = ATOI2(p);
235 --lt->tm_mon; /* time struct is 0 - 11 */
236 /* FALLTHROUGH */
237 case 6: /* dd */
238 lt->tm_mday = ATOI2(p);
239 /* FALLTHROUGH */
240 case 4: /* hh */
241 lt->tm_hour = ATOI2(p);
242 /* FALLTHROUGH */
243 case 2: /* mm */
244 lt->tm_min = ATOI2(p);
245 break;
246 default:
247 badformat();
248 }
249
250 /* convert broken-down time to GMT clock time */
251 if ((tval = mktime(lt)) == -1)
252 badtime();
253
254 /* set the time */
255 if (nflag || netsettime(tval)) {
256 logwtmp("|", "date", "");
257 tv.tv_sec = tval;
258 tv.tv_usec = 0;
259 if (settimeofday(&tv, NULL)) {
260 perror("date: settimeofday");
261 exit(1);
262 }
263 logwtmp("{", "date", "");
264 }
265
266 if ((p = getlogin()) == NULL)
267 p = "???";
268 syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
269 }
270
271 static void
272 badformat()
273 {
274 warnx("illegal time format");
275 usage();
276 }
277
278 static void
279 badtime()
280 {
281 errx(1, "illegal time");
282 }
283
284 static void
285 usage()
286 {
287 (void)fprintf(stderr,
288 "usage: date [-nu] [-r seconds] [+format]\n");
289 if (unix2003_std)
290 (void)fprintf(stderr, " date [-u] mmddhhmm[[cc]yy]\n");
291 else
292 (void)fprintf(stderr, " date [[[[[cc]yy]mm]dd]hh]mm[.ss]\n");
293 exit(1);
294 /* NOTREACHED */
295 }