date.c revision 1.6 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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 /*static char sccsid[] = "from: @(#)date.c 5.5 (Berkeley) 3/18/91";*/
42 static char rcsid[] = "$Id: date.c,v 1.6 1993/08/16 23:08:52 jtc Exp $";
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/time.h>
47 #include <sys/file.h>
48 #include <syslog.h>
49 #include <unistd.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <ctype.h>
54
55 time_t tval;
56 int retval, nflag;
57
58 main(argc, argv)
59 int argc;
60 char **argv;
61 {
62 extern int optind;
63 extern char *optarg;
64 struct timezone tz;
65 int ch, rflag;
66 char *format, buf[1024];
67
68 tz.tz_dsttime = tz.tz_minuteswest = 0;
69 rflag = 0;
70 while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF)
71 switch((char)ch) {
72 case 'd': /* daylight savings time */
73 tz.tz_dsttime = atoi(optarg) ? 1 : 0;
74 break;
75 case 'n': /* don't set network */
76 nflag = 1;
77 break;
78 case 'r': /* user specified seconds */
79 rflag = 1;
80 tval = atol(optarg);
81 break;
82 case 'u': /* do everything in GMT */
83 (void)setenv("TZ", "GMT0", 1);
84 break;
85 case 't': /* minutes west of GMT */
86 /* error check; don't allow "PST" */
87 if (isdigit(*optarg)) {
88 tz.tz_minuteswest = atoi(optarg);
89 break;
90 }
91 /* FALLTHROUGH */
92 default:
93 usage();
94 }
95 argc -= optind;
96 argv += optind;
97
98 /*
99 * If -d or -t, set the timezone or daylight savings time; this
100 * doesn't belong here, there kernel should not know about either.
101 */
102 if ((tz.tz_minuteswest || tz.tz_dsttime) &&
103 settimeofday((struct timeval *)NULL, &tz)) {
104 perror("date: settimeofday");
105 exit(1);
106 }
107
108 if (!rflag && time(&tval) == -1) {
109 perror("date: time");
110 exit(1);
111 }
112
113 format = "%a %b %e %H:%M:%S %Z %Y";
114
115 /* allow the operands in any order */
116 if (*argv && **argv == '+') {
117 format = *argv + 1;
118 ++argv;
119 }
120
121 if (*argv) {
122 setthetime(*argv);
123 ++argv;
124 }
125
126 if (*argv && **argv == '+')
127 format = *argv + 1;
128
129 (void)strftime(buf, sizeof(buf), format, localtime(&tval));
130 (void)printf("%s\n", buf);
131 exit(retval);
132 }
133
134 #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
135 setthetime(p)
136 register char *p;
137 {
138 register struct tm *lt;
139 struct timeval tv;
140 int dot;
141 char *t;
142
143 for (t = p, dot = 0; *t; ++t)
144 if (!isdigit(*t) && (*t != '.' || dot++))
145 badformat();
146
147 lt = localtime(&tval);
148
149 if (t = index(p, '.')) { /* .ss */
150 *t++ = '\0';
151 lt->tm_sec = ATOI2(t);
152 if (lt->tm_sec > 61)
153 badformat();
154 } else
155 lt->tm_sec = 0;
156
157 for (t = p; *t; ++t)
158 if (!isdigit(*t))
159 badformat();
160
161 switch (strlen(p)) {
162 case 10: /* yy */
163 lt->tm_year = ATOI2(p);
164 if (lt->tm_year < 69) /* hack for 2000 ;-} */
165 lt->tm_year += 100;
166 /* FALLTHROUGH */
167 case 8: /* mm */
168 lt->tm_mon = ATOI2(p);
169 if (lt->tm_mon > 12)
170 badformat();
171 --lt->tm_mon; /* time struct is 0 - 11 */
172 /* FALLTHROUGH */
173 case 6: /* dd */
174 lt->tm_mday = ATOI2(p);
175 if (lt->tm_mday > 31)
176 badformat();
177 /* FALLTHROUGH */
178 case 4: /* hh */
179 lt->tm_hour = ATOI2(p);
180 if (lt->tm_hour > 23)
181 badformat();
182 /* FALLTHROUGH */
183 case 2: /* mm */
184 lt->tm_min = ATOI2(p);
185 if (lt->tm_min > 59)
186 badformat();
187 break;
188 default:
189 badformat();
190 }
191
192 /* convert broken-down time to GMT clock time */
193 if ((tval = mktime(lt)) == -1)
194 badformat();
195
196 if (!(p = getlogin())) /* single-user or no tty */
197 p = "root";
198 syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
199
200 /* set the time */
201 if (nflag || netsettime(tval)) {
202 logwtmp("|", "date", "");
203 tv.tv_sec = tval;
204 tv.tv_usec = 0;
205 if (settimeofday(&tv, (struct timezone *)NULL)) {
206 perror("date: settimeofday");
207 exit(1);
208 }
209 logwtmp("{", "date", "");
210 }
211 }
212
213 badformat()
214 {
215 (void)fprintf(stderr, "date: illegal time format.\n");
216 usage();
217 }
218
219 usage()
220 {
221 (void)fprintf(stderr,
222 "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
223 (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n");
224 exit(1);
225 }
226