date.c revision 1.14 1 /* $NetBSD: date.c,v 1.14 1997/03/26 20:28:11 cgd 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 #ifndef lint
37 static char copyright[] =
38 "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
39 The Regents of the University of California. All rights reserved.\n";
40 #endif /* not lint */
41
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
45 #else
46 static char rcsid[] = "$NetBSD: date.c,v 1.14 1997/03/26 20:28:11 cgd Exp $";
47 #endif
48 #endif /* not lint */
49
50 #include <sys/param.h>
51 #include <sys/time.h>
52
53 #include <ctype.h>
54 #include <err.h>
55 #include <fcntl.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <locale.h>
60 #include <syslog.h>
61 #include <unistd.h>
62 #include <util.h>
63
64 #include "extern.h"
65
66 time_t tval;
67 int retval, nflag;
68
69 static void setthetime __P((char *));
70 static void badformat __P((void));
71 static void usage __P((void));
72
73 int
74 main(argc, argv)
75 int argc;
76 char **argv;
77 {
78 extern int optind;
79 extern char *optarg;
80 int ch, rflag;
81 char *format, buf[1024];
82
83 setlocale(LC_ALL, "");
84
85 rflag = 0;
86 while ((ch = getopt(argc, argv, "nr:u")) != -1)
87 switch((char)ch) {
88 case 'n': /* don't set network */
89 nflag = 1;
90 break;
91 case 'r': /* user specified seconds */
92 rflag = 1;
93 tval = atol(optarg);
94 break;
95 case 'u': /* do everything in GMT */
96 (void)setenv("TZ", "GMT0", 1);
97 break;
98 default:
99 usage();
100 }
101 argc -= optind;
102 argv += optind;
103
104 if (!rflag && time(&tval) == -1)
105 err(1, "time");
106
107 format = "%a %b %e %H:%M:%S %Z %Y";
108
109 /* allow the operands in any order */
110 if (*argv && **argv == '+') {
111 format = *argv + 1;
112 ++argv;
113 }
114
115 if (*argv) {
116 setthetime(*argv);
117 ++argv;
118 }
119
120 if (*argv && **argv == '+')
121 format = *argv + 1;
122
123 (void)strftime(buf, sizeof(buf), format, localtime(&tval));
124 (void)printf("%s\n", buf);
125 exit(retval);
126 }
127
128 #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
129 void
130 setthetime(p)
131 char *p;
132 {
133 struct tm *lt;
134 struct timeval tv;
135 char *dot, *t;
136
137 for (t = p, dot = NULL; *t; ++t) {
138 if (isdigit(*t))
139 continue;
140 if (*t == '.' && dot == NULL) {
141 dot = t;
142 continue;
143 }
144 badformat();
145 }
146
147 lt = localtime(&tval);
148
149 if (dot != NULL) { /* .ss */
150 *dot++ = '\0';
151 if (strlen(dot) != 2)
152 badformat();
153 lt->tm_sec = ATOI2(dot);
154 if (lt->tm_sec > 61)
155 badformat();
156 } else
157 lt->tm_sec = 0;
158
159 switch (strlen(p)) {
160 case 10: /* yy */
161 lt->tm_year = ATOI2(p);
162 if (lt->tm_year < 69) /* hack for 2000 ;-} */
163 lt->tm_year += 100;
164 /* FALLTHROUGH */
165 case 8: /* mm */
166 lt->tm_mon = ATOI2(p);
167 if (lt->tm_mon > 12)
168 badformat();
169 --lt->tm_mon; /* time struct is 0 - 11 */
170 /* FALLTHROUGH */
171 case 6: /* dd */
172 lt->tm_mday = ATOI2(p);
173 if (lt->tm_mday > 31)
174 badformat();
175 /* FALLTHROUGH */
176 case 4: /* hh */
177 lt->tm_hour = ATOI2(p);
178 if (lt->tm_hour > 23)
179 badformat();
180 /* FALLTHROUGH */
181 case 2: /* mm */
182 lt->tm_min = ATOI2(p);
183 if (lt->tm_min > 59)
184 badformat();
185 break;
186 default:
187 badformat();
188 }
189
190 /* convert broken-down time to GMT clock time */
191 if ((tval = mktime(lt)) == -1)
192 badformat();
193
194 /* set the time */
195 if (nflag || netsettime(tval)) {
196 logwtmp("|", "date", "");
197 tv.tv_sec = tval;
198 tv.tv_usec = 0;
199 if (settimeofday(&tv, NULL)) {
200 perror("date: settimeofday");
201 exit(1);
202 }
203 logwtmp("{", "date", "");
204 }
205
206 if ((p = getlogin()) == NULL)
207 p = "???";
208 syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
209 }
210
211 static void
212 badformat()
213 {
214 warnx("illegal time format");
215 usage();
216 }
217
218 static void
219 usage()
220 {
221 (void)fprintf(stderr,
222 "usage: date [-nu] [-r seconds] [+format]\n");
223 (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n");
224 exit(1);
225 }
226