Commit | Line | Data |
---|---|---|
c9f81cd5 | 1 | /* |
ba5e8546 KB |
2 | * Copyright (c) 1985, 1987, 1988, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
a9ff74ae | 4 | * |
27c71911 | 5 | * %sccs.include.redist.c% |
c9f81cd5 KM |
6 | */ |
7 | ||
8 | #ifndef lint | |
ba5e8546 KB |
9 | static char copyright[] = |
10 | "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\ | |
11 | The Regents of the University of California. All rights reserved.\n"; | |
a9ff74ae | 12 | #endif /* not lint */ |
c9f81cd5 | 13 | |
e1d473bc | 14 | #ifndef lint |
ba5e8546 | 15 | static char sccsid[] = "@(#)date.c 8.1 (Berkeley) %G%"; |
a9ff74ae | 16 | #endif /* not lint */ |
e1d473bc | 17 | |
92463b23 | 18 | #include <sys/param.h> |
72cf2549 | 19 | #include <sys/time.h> |
728c8c42 KB |
20 | |
21 | #include <ctype.h> | |
22 | #include <err.h> | |
23 | #include <fcntl.h> | |
a524e883 | 24 | #include <stdio.h> |
394a151d | 25 | #include <stdlib.h> |
2f339969 | 26 | #include <string.h> |
728c8c42 KB |
27 | #include <syslog.h> |
28 | #include <unistd.h> | |
29 | ||
30 | #include "extern.h" | |
08f42884 | 31 | |
394a151d KB |
32 | time_t tval; |
33 | int retval, nflag; | |
0698cf89 | 34 | |
728c8c42 KB |
35 | static void setthetime __P((char *)); |
36 | static void badformat __P((void)); | |
37 | static void usage __P((void)); | |
38 | ||
39 | int logwtmp __P((char *, char *, char *)); | |
40 | ||
41 | int | |
a9ff74ae KB |
42 | main(argc, argv) |
43 | int argc; | |
44 | char **argv; | |
0698cf89 | 45 | { |
a9ff74ae KB |
46 | extern int optind; |
47 | extern char *optarg; | |
48 | struct timezone tz; | |
8096bea8 | 49 | int ch, rflag; |
394a151d | 50 | char *format, buf[1024]; |
08f42884 | 51 | |
b1290464 | 52 | tz.tz_dsttime = tz.tz_minuteswest = 0; |
8096bea8 | 53 | rflag = 0; |
39ab653e | 54 | while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF) |
a524e883 | 55 | switch((char)ch) { |
a9ff74ae | 56 | case 'd': /* daylight savings time */ |
a524e883 | 57 | tz.tz_dsttime = atoi(optarg) ? 1 : 0; |
f4cd17f6 | 58 | break; |
a9ff74ae | 59 | case 'n': /* don't set network */ |
a524e883 | 60 | nflag = 1; |
f4cd17f6 | 61 | break; |
8096bea8 KB |
62 | case 'r': /* user specified seconds */ |
63 | rflag = 1; | |
39ab653e KB |
64 | tval = atol(optarg); |
65 | break; | |
394a151d | 66 | case 'u': /* do everything in GMT */ |
c002b318 | 67 | (void)setenv("TZ", "GMT0", 1); |
a524e883 | 68 | break; |
a9ff74ae | 69 | case 't': /* minutes west of GMT */ |
394a151d | 70 | /* error check; don't allow "PST" */ |
b1290464 KB |
71 | if (isdigit(*optarg)) { |
72 | tz.tz_minuteswest = atoi(optarg); | |
73 | break; | |
74 | } | |
394a151d | 75 | /* FALLTHROUGH */ |
a524e883 | 76 | default: |
b1290464 | 77 | usage(); |
f4cd17f6 | 78 | } |
a524e883 KB |
79 | argc -= optind; |
80 | argv += optind; | |
81 | ||
394a151d KB |
82 | /* |
83 | * If -d or -t, set the timezone or daylight savings time; this | |
84 | * doesn't belong here, there kernel should not know about either. | |
85 | */ | |
a524e883 | 86 | if ((tz.tz_minuteswest || tz.tz_dsttime) && |
728c8c42 KB |
87 | settimeofday(NULL, &tz)) |
88 | err(1, "settimeofday"); | |
a524e883 | 89 | |
728c8c42 KB |
90 | if (!rflag && time(&tval) == -1) |
91 | err(1, "time"); | |
a524e883 | 92 | |
394a151d | 93 | format = "%a %b %e %H:%M:%S %Z %Y\n"; |
08f42884 | 94 | |
394a151d KB |
95 | /* allow the operands in any order */ |
96 | if (*argv && **argv == '+') { | |
97 | format = *argv + 1; | |
98 | ++argv; | |
08f42884 | 99 | } |
a524e883 | 100 | |
394a151d KB |
101 | if (*argv) { |
102 | setthetime(*argv); | |
103 | ++argv; | |
08f42884 | 104 | } |
08f42884 | 105 | |
394a151d KB |
106 | if (*argv && **argv == '+') |
107 | format = *argv + 1; | |
a524e883 | 108 | |
394a151d KB |
109 | (void)strftime(buf, sizeof(buf), format, localtime(&tval)); |
110 | (void)printf("%s", buf); | |
b2163cc6 | 111 | exit(retval); |
0698cf89 BJ |
112 | } |
113 | ||
394a151d | 114 | #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; |
728c8c42 | 115 | void |
394a151d KB |
116 | setthetime(p) |
117 | register char *p; | |
0698cf89 | 118 | { |
394a151d KB |
119 | register struct tm *lt; |
120 | struct timeval tv; | |
7cbae0a7 KB |
121 | char *dot, *t; |
122 | ||
123 | for (t = p, dot = NULL; *t; ++t) { | |
124 | if (isdigit(*t)) | |
125 | continue; | |
126 | if (*t == '.' && dot == NULL) { | |
127 | dot = t; | |
128 | continue; | |
129 | } | |
130 | badformat(); | |
131 | } | |
394a151d KB |
132 | |
133 | lt = localtime(&tval); | |
134 | ||
7cbae0a7 KB |
135 | if (dot != NULL) { /* .ss */ |
136 | *dot++ = '\0'; | |
137 | if (strlen(dot) != 2) | |
2b1a1ed8 | 138 | badformat(); |
7cbae0a7 | 139 | lt->tm_sec = ATOI2(dot); |
394a151d KB |
140 | if (lt->tm_sec > 61) |
141 | badformat(); | |
142 | } else | |
143 | lt->tm_sec = 0; | |
144 | ||
394a151d KB |
145 | switch (strlen(p)) { |
146 | case 10: /* yy */ | |
147 | lt->tm_year = ATOI2(p); | |
148 | if (lt->tm_year < 69) /* hack for 2000 ;-} */ | |
149 | lt->tm_year += 100; | |
150 | /* FALLTHROUGH */ | |
151 | case 8: /* mm */ | |
152 | lt->tm_mon = ATOI2(p); | |
153 | if (lt->tm_mon > 12) | |
154 | badformat(); | |
f9eecd6d | 155 | --lt->tm_mon; /* time struct is 0 - 11 */ |
394a151d KB |
156 | /* FALLTHROUGH */ |
157 | case 6: /* dd */ | |
158 | lt->tm_mday = ATOI2(p); | |
159 | if (lt->tm_mday > 31) | |
160 | badformat(); | |
161 | /* FALLTHROUGH */ | |
162 | case 4: /* hh */ | |
163 | lt->tm_hour = ATOI2(p); | |
164 | if (lt->tm_hour > 23) | |
165 | badformat(); | |
166 | /* FALLTHROUGH */ | |
167 | case 2: /* mm */ | |
168 | lt->tm_min = ATOI2(p); | |
169 | if (lt->tm_min > 59) | |
170 | badformat(); | |
171 | break; | |
172 | default: | |
173 | badformat(); | |
174 | } | |
175 | ||
176 | /* convert broken-down time to GMT clock time */ | |
177 | if ((tval = mktime(lt)) == -1) | |
178 | badformat(); | |
179 | ||
394a151d KB |
180 | /* set the time */ |
181 | if (nflag || netsettime(tval)) { | |
182 | logwtmp("|", "date", ""); | |
183 | tv.tv_sec = tval; | |
184 | tv.tv_usec = 0; | |
e209f9a8 | 185 | if (settimeofday(&tv, NULL)) { |
394a151d KB |
186 | perror("date: settimeofday"); |
187 | exit(1); | |
a524e883 | 188 | } |
394a151d | 189 | logwtmp("{", "date", ""); |
0698cf89 | 190 | } |
e209f9a8 KB |
191 | |
192 | if ((p = getlogin()) == NULL) | |
193 | p = "???"; | |
194 | syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p); | |
0698cf89 | 195 | } |
08f42884 | 196 | |
728c8c42 | 197 | static void |
394a151d | 198 | badformat() |
f5ae02ee | 199 | { |
728c8c42 | 200 | warnx("illegal time format"); |
394a151d | 201 | usage(); |
f5ae02ee | 202 | } |
b1290464 | 203 | |
728c8c42 | 204 | static void |
b1290464 KB |
205 | usage() |
206 | { | |
394a151d | 207 | (void)fprintf(stderr, |
39ab653e KB |
208 | "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n"); |
209 | (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n"); | |
394a151d | 210 | exit(1); |
b1290464 | 211 | } |