diff options
author | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
commit | cc8ed39b240180b58810784f844e253263594ac3 (patch) | |
tree | 15feebbb4be9a9168209609f48f0b100f9364420 /date.c | |
download | busybox-w32-0_29alpha2.tar.gz busybox-w32-0_29alpha2.tar.bz2 busybox-w32-0_29alpha2.zip |
Initial revision0_29alpha2
Diffstat (limited to 'date.c')
-rw-r--r-- | date.c | 305 |
1 files changed, 305 insertions, 0 deletions
@@ -0,0 +1,305 @@ | |||
1 | #include "internal.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <errno.h> | ||
4 | #include <sys/time.h> | ||
5 | #include <unistd.h> | ||
6 | #include <time.h> | ||
7 | #include <stdio.h> | ||
8 | #include <getopt.h> | ||
9 | |||
10 | |||
11 | /* This 'date' command supports only 2 time setting formats, | ||
12 | all the GNU strftime stuff (its in libc, lets use it), | ||
13 | setting time using UTC and displaying int, as well as | ||
14 | an RFC 822 complient date output for shell scripting | ||
15 | mail commands */ | ||
16 | |||
17 | const char date_usage[] = "date [-uR] [+FORMAT|+%f] [ [-s|-d] MMDDhhmm[[CC]YY]\n | [[[[CCYY.]MM.DD-]hh:mm[:ss]]]] ]"; | ||
18 | |||
19 | static struct option const long_options[] = | ||
20 | { | ||
21 | {"date", required_argument, NULL, 'd'}, | ||
22 | /* {"rfc-822", no_argument, NULL, 'R'}, | ||
23 | {"set", required_argument, NULL, 's'}, | ||
24 | {"uct", no_argument, NULL, 'u'}, | ||
25 | {"utc", no_argument, NULL, 'u'}, | ||
26 | {"universal", no_argument, NULL, 'u'}, */ | ||
27 | {NULL, 0, NULL, 0} | ||
28 | }; | ||
29 | |||
30 | |||
31 | |||
32 | /* Input parsing code is always bulky - used heavy duty libc stuff as | ||
33 | much as possible, missed out a lot of bounds checking */ | ||
34 | |||
35 | /* Default input handling to save suprising some people */ | ||
36 | |||
37 | struct tm * | ||
38 | date_conv_time(struct tm *tm_time, const char *t_string) { | ||
39 | int nr; | ||
40 | |||
41 | nr = sscanf(t_string, "%2d%2d%2d%2d%d", | ||
42 | &(tm_time->tm_mon), | ||
43 | &(tm_time->tm_mday), | ||
44 | &(tm_time->tm_hour), | ||
45 | &(tm_time->tm_min), | ||
46 | &(tm_time->tm_year)); | ||
47 | |||
48 | if(nr < 4 || nr > 5) { | ||
49 | fprintf(stderr, "date: invalid date `%s'\n", t_string); | ||
50 | exit(1); | ||
51 | } | ||
52 | |||
53 | /* correct for century - minor Y2K problem here? */ | ||
54 | if(tm_time->tm_year >= 1900) | ||
55 | tm_time->tm_year -= 1900; | ||
56 | /* adjust date */ | ||
57 | tm_time->tm_mon -= 1; | ||
58 | |||
59 | return(tm_time); | ||
60 | |||
61 | } | ||
62 | |||
63 | |||
64 | /* The new stuff for LRP */ | ||
65 | |||
66 | struct tm * | ||
67 | date_conv_ftime(struct tm *tm_time, const char *t_string) { | ||
68 | struct tm itm_time, jtm_time, ktm_time, \ | ||
69 | ltm_time, mtm_time, ntm_time; | ||
70 | |||
71 | itm_time = *tm_time; | ||
72 | jtm_time = *tm_time; | ||
73 | ktm_time = *tm_time; | ||
74 | ltm_time = *tm_time; | ||
75 | mtm_time = *tm_time; | ||
76 | ntm_time = *tm_time; | ||
77 | |||
78 | /* Parse input and assign appropriately to tm_time */ | ||
79 | |||
80 | if(sscanf(t_string, "%d:%d:%d", | ||
81 | &itm_time.tm_hour, | ||
82 | &itm_time.tm_min, | ||
83 | &itm_time.tm_sec) == 3 ) { | ||
84 | |||
85 | *tm_time = itm_time; | ||
86 | return(tm_time); | ||
87 | |||
88 | } else if (sscanf(t_string, "%d:%d", | ||
89 | &jtm_time.tm_hour, | ||
90 | &jtm_time.tm_min) == 2) { | ||
91 | |||
92 | *tm_time = jtm_time; | ||
93 | return(tm_time); | ||
94 | |||
95 | } else if (sscanf(t_string, "%d.%d-%d:%d:%d", | ||
96 | &ktm_time.tm_mon, | ||
97 | &ktm_time.tm_mday, | ||
98 | &ktm_time.tm_hour, | ||
99 | &ktm_time.tm_min, | ||
100 | &ktm_time.tm_sec) == 5) { | ||
101 | |||
102 | ktm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
103 | *tm_time = ktm_time; | ||
104 | return(tm_time); | ||
105 | |||
106 | } else if (sscanf(t_string, "%d.%d-%d:%d", | ||
107 | <m_time.tm_mon, | ||
108 | <m_time.tm_mday, | ||
109 | <m_time.tm_hour, | ||
110 | <m_time.tm_min) == 4) { | ||
111 | |||
112 | ltm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
113 | *tm_time = ltm_time; | ||
114 | return(tm_time); | ||
115 | |||
116 | } else if (sscanf(t_string, "%d.%d.%d-%d:%d:%d", | ||
117 | &mtm_time.tm_year, | ||
118 | &mtm_time.tm_mon, | ||
119 | &mtm_time.tm_mday, | ||
120 | &mtm_time.tm_hour, | ||
121 | &mtm_time.tm_min, | ||
122 | &mtm_time.tm_sec) == 6) { | ||
123 | |||
124 | mtm_time.tm_year -= 1900; /* Adjust years */ | ||
125 | mtm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
126 | *tm_time = mtm_time; | ||
127 | return(tm_time); | ||
128 | |||
129 | } else if (sscanf(t_string, "%d.%d.%d-%d:%d", | ||
130 | &ntm_time.tm_year, | ||
131 | &ntm_time.tm_mon, | ||
132 | &ntm_time.tm_mday, | ||
133 | &ntm_time.tm_hour, | ||
134 | &ntm_time.tm_min) == 5) { | ||
135 | ntm_time.tm_year -= 1900; /* Adjust years */ | ||
136 | ntm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
137 | *tm_time = ntm_time; | ||
138 | return(tm_time); | ||
139 | |||
140 | } | ||
141 | |||
142 | fprintf(stderr, "date: invalid date `%s'\n", t_string); | ||
143 | |||
144 | exit(1); | ||
145 | |||
146 | } | ||
147 | |||
148 | |||
149 | void | ||
150 | date_err(void) { | ||
151 | fprintf(stderr, "date: only one date argument can be given at a time.\n"); | ||
152 | exit(1); | ||
153 | } | ||
154 | |||
155 | int | ||
156 | date_main(struct FileInfo * i, int argc, char * * argv) | ||
157 | { | ||
158 | char *date_str = NULL; | ||
159 | char *date_fmt = NULL; | ||
160 | char *t_buff; | ||
161 | int set_time = 0; | ||
162 | int rfc822 = 0; | ||
163 | int utc = 0; | ||
164 | int use_arg = 0; | ||
165 | int n_args; | ||
166 | time_t tm; | ||
167 | struct tm tm_time; | ||
168 | char optc; | ||
169 | |||
170 | /* Interpret command line args */ | ||
171 | |||
172 | |||
173 | while ((optc = getopt_long (argc, argv, "d:Rs:u", long_options, NULL)) | ||
174 | != EOF) { | ||
175 | switch (optc) { | ||
176 | case 0: | ||
177 | break; | ||
178 | |||
179 | case 'R': | ||
180 | rfc822 = 1; | ||
181 | break; | ||
182 | |||
183 | case 's': | ||
184 | set_time = 1; | ||
185 | if(date_str != NULL) date_err(); | ||
186 | date_str = optarg; | ||
187 | break; | ||
188 | |||
189 | case 'u': | ||
190 | utc = 1; | ||
191 | if (putenv ("TZ=UTC0") != 0) { | ||
192 | fprintf(stderr,"date: memory exhausted\n"); | ||
193 | return(1); | ||
194 | } | ||
195 | #if LOCALTIME_CACHE | ||
196 | tzset (); | ||
197 | #endif break; | ||
198 | |||
199 | case 'd': | ||
200 | use_arg = 1; | ||
201 | if(date_str != NULL) date_err(); | ||
202 | date_str = optarg; | ||
203 | break; | ||
204 | |||
205 | default: | ||
206 | usage(date_usage); | ||
207 | break; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | |||
212 | n_args = argc - optind; | ||
213 | |||
214 | while (n_args--){ | ||
215 | switch(argv[optind][0]) { | ||
216 | case '+': | ||
217 | /* Date format strings */ | ||
218 | if(date_fmt != NULL) { | ||
219 | fprintf(stderr, "date: only one date format can be given.\n"); | ||
220 | return(1); | ||
221 | } | ||
222 | date_fmt = &argv[optind][1]; | ||
223 | break; | ||
224 | |||
225 | case '\0': | ||
226 | break; | ||
227 | |||
228 | default: | ||
229 | /* Anything left over must be a date string to set the time */ | ||
230 | set_time = 1; | ||
231 | if(date_str != NULL) date_err(); | ||
232 | date_str = argv[optind]; | ||
233 | break; | ||
234 | } | ||
235 | optind++; | ||
236 | } | ||
237 | |||
238 | |||
239 | /* Now we have parsed all the information except the date format | ||
240 | which depends on whether the clock is being set or read */ | ||
241 | |||
242 | time(&tm); | ||
243 | memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); | ||
244 | /* Zero out fields - take her back to midnight!*/ | ||
245 | if(date_str != NULL) { | ||
246 | tm_time.tm_sec = 0; | ||
247 | tm_time.tm_min = 0; | ||
248 | tm_time.tm_hour = 0; | ||
249 | } | ||
250 | |||
251 | /* Process any date input to UNIX time since 1 Jan 1970 */ | ||
252 | if(date_str != NULL) { | ||
253 | |||
254 | if(strchr(date_str, ':') != NULL) { | ||
255 | date_conv_ftime(&tm_time, date_str); | ||
256 | } else { | ||
257 | date_conv_time(&tm_time, date_str); | ||
258 | } | ||
259 | |||
260 | /* Correct any day of week and day of year etc fields */ | ||
261 | tm = mktime(&tm_time); | ||
262 | if (tm < 0 ) { | ||
263 | fprintf(stderr, "date: invalid date `%s'\n", date_str); | ||
264 | exit(1); | ||
265 | } | ||
266 | |||
267 | /* if setting time, set it */ | ||
268 | if(set_time) { | ||
269 | if( stime(&tm) < 0) { | ||
270 | fprintf(stderr, "date: can't set date.\n"); | ||
271 | exit(1); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* Display output */ | ||
277 | |||
278 | /* Deal with format string */ | ||
279 | if(date_fmt == NULL) { | ||
280 | date_fmt = (rfc822 | ||
281 | ? (utc | ||
282 | ? "%a, %_d %b %Y %H:%M:%S GMT" | ||
283 | : "%a, %_d %b %Y %H:%M:%S %z") | ||
284 | : "%a %b %e %H:%M:%S %Z %Y"); | ||
285 | |||
286 | } else if ( *date_fmt == '\0' ) { | ||
287 | /* Imitate what GNU 'date' does with NO format string! */ | ||
288 | printf ("\n"); | ||
289 | return(0); | ||
290 | } | ||
291 | |||
292 | /* Handle special conversions */ | ||
293 | |||
294 | if( strncmp( date_fmt, "%f", 2) == 0 ) { | ||
295 | date_fmt = "%Y.%m.%d-%H:%M:%S"; | ||
296 | } | ||
297 | |||
298 | /* Print OUTPUT (after ALL that!) */ | ||
299 | t_buff = malloc(201); | ||
300 | strftime(t_buff, 200, date_fmt, &tm_time); | ||
301 | printf("%s\n", t_buff); | ||
302 | |||
303 | return(0); | ||
304 | |||
305 | } | ||