toolbox: add OpenADK toolbox for very small systems, thx Thorsten Glaser
[openadk.git] / package / toolbox / src / date / date.c
blobc4d5ddc82416df3332a9c1e5175231cd8f6d26a4
1 /* $OpenBSD: date.c,v 1.26 2003/10/15 15:58:22 mpech Exp $ */
2 /* $NetBSD: date.c,v 1.11 1995/09/07 06:21:05 jtc Exp $ */
4 /*
5 * Copyright (c) 1985, 1987, 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/time.h>
36 #include <ctype.h>
37 #include <err.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <locale.h>
43 #include <syslog.h>
44 #include <time.h>
45 #include <unistd.h>
47 __COPYRIGHT("@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
48 The Regents of the University of California. All rights reserved.\n");
49 __SCCSID("@(#)date.c 8.2 (Berkeley) 4/28/95");
50 __RCSID("$MirOS: src/bin/date/date.c,v 1.9 2016/01/02 21:32:56 tg Exp $");
52 extern const char *__progname;
54 time_t tval;
55 int retval;
56 int slidetime;
58 #ifndef TM_YEAR_BASE
59 #define TM_YEAR_BASE 1900
60 #endif
62 static void setthetime(char *);
63 static __dead void badformat(void);
64 static __dead void usage(void);
66 int
67 main(int argc, char *argv[])
69 struct timezone tz;
70 int ch, rflag;
71 const char *format = NULL;
72 char buf[1024];
73 int whatformat = 0;
75 tz.tz_dsttime = tz.tz_minuteswest = 0;
76 rflag = 0;
77 while ((ch = getopt(argc, argv, "ad:nRr:ut:")) != -1)
78 switch((char)ch) {
79 case 'a':
80 slidetime++;
81 break;
82 case 'd': /* daylight saving time */
83 tz.tz_dsttime = atoi(optarg) ? 1 : 0;
84 break;
85 case 'n': /* don't set network */
86 break;
87 case 'R': /* RFC 2822 format */
88 whatformat |= 1;
89 break;
90 case 'r': /* user specified seconds */
91 rflag = 1;
92 tval = atoll(optarg);
93 break;
94 case 'u': /* do everything in UTC */
95 if (setenv("TZ", "GMT0", 1) == -1)
96 err(1, "cannot unsetenv TZ");
97 break;
98 case 't': /* minutes west of GMT */
99 /* error check; don't allow "PST" */
100 if (isdigit(*optarg)) {
101 tz.tz_minuteswest = atoi(optarg);
102 break;
104 /* FALLTHROUGH */
105 default:
106 usage();
108 argc -= optind;
109 argv += optind;
112 * If -d or -t, set the timezone or daylight saving time; this
113 * doesn't belong here, the kernel should not know about either.
115 if ((tz.tz_minuteswest || tz.tz_dsttime) &&
116 settimeofday(NULL, &tz))
117 err(1, "settimeofday");
119 if (!rflag && time(&tval) == -1)
120 err(1, "time");
122 /* allow the operands in any order */
123 if (*argv && **argv == '+') {
124 if (*(*argv + 1)) {
125 whatformat |= 2;
126 format = *argv + 1;
128 ++argv;
131 if (*argv) {
132 setthetime(*argv);
133 ++argv;
136 if (*argv && **argv == '+') {
137 whatformat |= 4;
138 format = *argv + 1;
141 if (whatformat == 0)
142 format = "%a %b %e %H:%M:%S %Z %Y";
143 else if (whatformat == 1) {
144 format = "%a, %d %b %Y %H:%M:%S %z";
145 } else if (whatformat != 2 && whatformat != 4)
146 errx(1, "more than one format specified");
148 strftime(buf, sizeof (buf), format, localtime(&tval));
149 printf("%s\n", buf);
150 exit(retval);
153 #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
154 void
155 setthetime(char *p)
157 struct tm *lt;
158 struct timeval tv;
159 char *dot, *t;
160 const char *pc;
161 int bigyear;
162 int yearset = 0;
164 for (t = p, dot = NULL; *t; ++t) {
165 if (isdigit(*t))
166 continue;
167 if (*t == '.' && dot == NULL) {
168 dot = t;
169 continue;
171 badformat();
174 lt = localtime(&tval);
176 lt->tm_isdst = -1; /* correct for DST */
178 if (dot != NULL) { /* .SS */
179 *dot++ = '\0';
180 if (strlen(dot) != 2)
181 badformat();
182 lt->tm_sec = ATOI2(dot);
183 if (lt->tm_sec > 61)
184 badformat();
185 } else
186 lt->tm_sec = 0;
188 switch (strlen(p)) {
189 case 12: /* cc */
190 bigyear = ATOI2(p);
191 lt->tm_year = bigyear * 100 - TM_YEAR_BASE;
192 yearset = 1;
193 /* FALLTHROUGH */
194 case 10: /* yy */
195 if (yearset) {
196 lt->tm_year += ATOI2(p);
197 } else {
198 lt->tm_year = ATOI2(p);
199 if (lt->tm_year < 69) /* hack for 2000 ;-} */
200 lt->tm_year += (2000 - TM_YEAR_BASE);
201 else
202 lt->tm_year += (1900 - TM_YEAR_BASE);
204 /* FALLTHROUGH */
205 case 8: /* mm */
206 lt->tm_mon = ATOI2(p);
207 if ((lt->tm_mon > 12) || !lt->tm_mon)
208 badformat();
209 --lt->tm_mon; /* time struct is 0 - 11 */
210 /* FALLTHROUGH */
211 case 6: /* dd */
212 lt->tm_mday = ATOI2(p);
213 if ((lt->tm_mday > 31) || !lt->tm_mday)
214 badformat();
215 /* FALLTHROUGH */
216 case 4: /* HH */
217 lt->tm_hour = ATOI2(p);
218 if (lt->tm_hour > 23)
219 badformat();
220 /* FALLTHROUGH */
221 case 2: /* MM */
222 lt->tm_min = ATOI2(p);
223 if (lt->tm_min > 59)
224 badformat();
225 break;
226 default:
227 badformat();
230 /* convert broken-down time to UTC clock time */
231 if ((tval = mktime(lt)) < 0)
232 errx(1, "specified date is outside allowed range");
234 /* set the time */
235 if (slidetime) {
236 struct timeval tv_current;
238 if (gettimeofday(&tv_current, NULL) == -1)
239 err(1, "Could not get local time of day");
241 tv.tv_sec = tval - tv_current.tv_sec;
242 tv.tv_usec = 0;
243 if (adjtime(&tv, NULL) == -1)
244 errx(1, "adjtime");
245 } else {
246 tv.tv_sec = tval;
247 tv.tv_usec = 0;
248 if (settimeofday(&tv, NULL))
249 err(1, "settimeofday");
252 if ((pc = getlogin()) == NULL)
253 pc = "???";
254 syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", pc);
257 static void
258 badformat(void)
260 warnx("illegal time format");
261 usage();
264 static void
265 usage(void)
267 fprintf(stderr,
268 "usage:\t%s [-anRu] [-d dst] [-r seconds] [-t west] [+format]\n",
269 __progname);
270 fprintf(stderr, "\t [[[[[[cc]yy]mm]dd]HH]MM[.SS]]\n");
271 exit(1);