Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/date.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 6608 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 6608 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * Mini date implementation for busybox | ||
4 | * | ||
5 | * by Matthew Grant <grantma@anathoth.gen.nz> | ||
6 | * | ||
7 | * iso-format handling added by Robert Griebl <griebl@gmx.de> | ||
8 | * bugfixes and cleanup by Bernhard Fischer | ||
9 | * | ||
10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
11 | */ | ||
12 | |||
13 | #include "busybox.h" | ||
14 | |||
15 | /* This 'date' command supports only 2 time setting formats, | ||
16 | all the GNU strftime stuff (its in libc, lets use it), | ||
17 | setting time using UTC and displaying it, as well as | ||
18 | an RFC 2822 compliant date output for shell scripting | ||
19 | mail commands */ | ||
20 | |||
21 | /* Input parsing code is always bulky - used heavy duty libc stuff as | ||
22 | much as possible, missed out a lot of bounds checking */ | ||
23 | |||
24 | /* Default input handling to save surprising some people */ | ||
25 | |||
26 | |||
27 | #define DATE_OPT_RFC2822 0x01 | ||
28 | #define DATE_OPT_SET 0x02 | ||
29 | #define DATE_OPT_UTC 0x04 | ||
30 | #define DATE_OPT_DATE 0x08 | ||
31 | #define DATE_OPT_REFERENCE 0x10 | ||
32 | #define DATE_OPT_TIMESPEC 0x20 | ||
33 | #define DATE_OPT_HINT 0x40 | ||
34 | |||
35 | static void xputenv(char *s) | ||
36 | { | ||
37 | if (putenv(s) != 0) | ||
38 | bb_error_msg_and_die(bb_msg_memory_exhausted); | ||
39 | } | ||
40 | |||
41 | static void maybe_set_utc(int opt) | ||
42 | { | ||
43 | if (opt & DATE_OPT_UTC) | ||
44 | xputenv("TZ=UTC0"); | ||
45 | } | ||
46 | |||
47 | int date_main(int argc, char **argv) | ||
48 | { | ||
49 | time_t tm; | ||
50 | struct tm tm_time; | ||
51 | unsigned opt; | ||
52 | int ifmt = -1; | ||
53 | char *date_str = NULL; | ||
54 | char *date_fmt = NULL; | ||
55 | char *filename = NULL; | ||
56 | char *isofmt_arg; | ||
57 | char *hintfmt_arg; | ||
58 | |||
59 | opt_complementary = "?:d--s:s--d" | ||
60 | USE_FEATURE_DATE_ISOFMT(":R--I:I--R"); | ||
61 | opt = getopt32(argc, argv, "Rs:ud:r:" | ||
62 | USE_FEATURE_DATE_ISOFMT("I::D:"), | ||
63 | &date_str, &date_str, &filename | ||
64 | USE_FEATURE_DATE_ISOFMT(, &isofmt_arg, &hintfmt_arg)); | ||
65 | maybe_set_utc(opt); | ||
66 | |||
67 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_TIMESPEC)) { | ||
68 | if (!isofmt_arg) { | ||
69 | ifmt = 0; /* default is date */ | ||
70 | } else { | ||
71 | const char * const isoformats[] = | ||
72 | {"date", "hours", "minutes", "seconds"}; | ||
73 | |||
74 | for (ifmt = 0; ifmt < 4; ifmt++) | ||
75 | if (!strcmp(isofmt_arg, isoformats[ifmt])) { | ||
76 | break; | ||
77 | } | ||
78 | if (ifmt == 4) /* parse error */ | ||
79 | bb_show_usage(); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* XXX, date_fmt == NULL from this always */ | ||
84 | if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) { | ||
85 | date_fmt = &argv[optind][1]; /* Skip over the '+' */ | ||
86 | } else if (date_str == NULL) { | ||
87 | opt |= DATE_OPT_SET; | ||
88 | date_str = argv[optind]; | ||
89 | } | ||
90 | |||
91 | /* Now we have parsed all the information except the date format | ||
92 | which depends on whether the clock is being set or read */ | ||
93 | |||
94 | if (filename) { | ||
95 | struct stat statbuf; | ||
96 | xstat(filename, &statbuf); | ||
97 | tm = statbuf.st_mtime; | ||
98 | } else | ||
99 | time(&tm); | ||
100 | memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); | ||
101 | /* Zero out fields - take her back to midnight! */ | ||
102 | if (date_str != NULL) { | ||
103 | tm_time.tm_sec = 0; | ||
104 | tm_time.tm_min = 0; | ||
105 | tm_time.tm_hour = 0; | ||
106 | |||
107 | /* Process any date input to UNIX time since 1 Jan 1970 */ | ||
108 | if (ENABLE_FEATURE_DATE_ISOFMT && (opt & DATE_OPT_HINT)) { | ||
109 | strptime(date_str, hintfmt_arg, &tm_time); | ||
110 | } else if (strchr(date_str, ':') != NULL) { | ||
111 | /* Parse input and assign appropriately to tm_time */ | ||
112 | |||
113 | if (sscanf(date_str, "%d:%d:%d", &tm_time.tm_hour, &tm_time.tm_min, | ||
114 | &tm_time.tm_sec) == 3) { | ||
115 | /* no adjustments needed */ | ||
116 | } else if (sscanf(date_str, "%d:%d", &tm_time.tm_hour, | ||
117 | &tm_time.tm_min) == 2) { | ||
118 | /* no adjustments needed */ | ||
119 | } else if (sscanf(date_str, "%d.%d-%d:%d:%d", &tm_time.tm_mon, | ||
120 | &tm_time.tm_mday, &tm_time.tm_hour, | ||
121 | &tm_time.tm_min, &tm_time.tm_sec) == 5) { | ||
122 | /* Adjust dates from 1-12 to 0-11 */ | ||
123 | tm_time.tm_mon -= 1; | ||
124 | } else if (sscanf(date_str, "%d.%d-%d:%d", &tm_time.tm_mon, | ||
125 | &tm_time.tm_mday, | ||
126 | &tm_time.tm_hour, &tm_time.tm_min) == 4) { | ||
127 | /* Adjust dates from 1-12 to 0-11 */ | ||
128 | tm_time.tm_mon -= 1; | ||
129 | } else if (sscanf(date_str, "%d.%d.%d-%d:%d:%d", &tm_time.tm_year, | ||
130 | &tm_time.tm_mon, &tm_time.tm_mday, | ||
131 | &tm_time.tm_hour, &tm_time.tm_min, | ||
132 | &tm_time.tm_sec) == 6) { | ||
133 | tm_time.tm_year -= 1900; /* Adjust years */ | ||
134 | tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
135 | } else if (sscanf(date_str, "%d.%d.%d-%d:%d", &tm_time.tm_year, | ||
136 | &tm_time.tm_mon, &tm_time.tm_mday, | ||
137 | &tm_time.tm_hour, &tm_time.tm_min) == 5) { | ||
138 | tm_time.tm_year -= 1900; /* Adjust years */ | ||
139 | tm_time.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ | ||
140 | } else { | ||
141 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
142 | } | ||
143 | } else { | ||
144 | int nr; | ||
145 | char *cp; | ||
146 | |||
147 | nr = sscanf(date_str, "%2d%2d%2d%2d%d", &tm_time.tm_mon, | ||
148 | &tm_time.tm_mday, &tm_time.tm_hour, &tm_time.tm_min, | ||
149 | &tm_time.tm_year); | ||
150 | |||
151 | if (nr < 4 || nr > 5) { | ||
152 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
153 | } | ||
154 | |||
155 | cp = strchr(date_str, '.'); | ||
156 | if (cp) { | ||
157 | nr = sscanf(cp + 1, "%2d", &tm_time.tm_sec); | ||
158 | if (nr != 1) { | ||
159 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* correct for century - minor Y2K problem here? */ | ||
164 | if (tm_time.tm_year >= 1900) { | ||
165 | tm_time.tm_year -= 1900; | ||
166 | } | ||
167 | /* adjust date */ | ||
168 | tm_time.tm_mon -= 1; | ||
169 | } | ||
170 | |||
171 | /* Correct any day of week and day of year etc. fields */ | ||
172 | tm_time.tm_isdst = -1; /* Be sure to recheck dst. */ | ||
173 | tm = mktime(&tm_time); | ||
174 | if (tm < 0) { | ||
175 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | ||
176 | } | ||
177 | maybe_set_utc(opt); | ||
178 | |||
179 | /* if setting time, set it */ | ||
180 | if ((opt & DATE_OPT_SET) && stime(&tm) < 0) { | ||
181 | bb_perror_msg("cannot set date"); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* Display output */ | ||
186 | |||
187 | /* Deal with format string */ | ||
188 | |||
189 | if (date_fmt == NULL) { | ||
190 | int i; | ||
191 | date_fmt = xzalloc(32); | ||
192 | if (ENABLE_FEATURE_DATE_ISOFMT && ifmt >= 0) { | ||
193 | strcpy(date_fmt, "%Y-%m-%d"); | ||
194 | if (ifmt > 0) { | ||
195 | i = 8; | ||
196 | date_fmt[i++] = 'T'; | ||
197 | date_fmt[i++] = '%'; | ||
198 | date_fmt[i++] = 'H'; | ||
199 | if (ifmt > 1) { | ||
200 | date_fmt[i++] = ':'; | ||
201 | date_fmt[i++] = '%'; | ||
202 | date_fmt[i++] = 'M'; | ||
203 | } | ||
204 | if (ifmt > 2) { | ||
205 | date_fmt[i++] = ':'; | ||
206 | date_fmt[i++] = '%'; | ||
207 | date_fmt[i++] = 'S'; | ||
208 | } | ||
209 | format_utc: | ||
210 | date_fmt[i++] = '%'; | ||
211 | date_fmt[i] = (opt & DATE_OPT_UTC) ? 'Z' : 'z'; | ||
212 | } | ||
213 | } else if (opt & DATE_OPT_RFC2822) { | ||
214 | /* Undo busybox.c for date -R */ | ||
215 | if (ENABLE_LOCALE_SUPPORT) | ||
216 | setlocale(LC_TIME, "C"); | ||
217 | strcpy(date_fmt, "%a, %d %b %Y %H:%M:%S "); | ||
218 | i = 22; | ||
219 | goto format_utc; | ||
220 | } else /* default case */ | ||
221 | date_fmt = "%a %b %e %H:%M:%S %Z %Y"; | ||
222 | } | ||
223 | |||
224 | if (*date_fmt == '\0') { | ||
225 | /* With no format string, just print a blank line */ | ||
226 | *bb_common_bufsiz1 = 0; | ||
227 | } else { | ||
228 | /* Handle special conversions */ | ||
229 | |||
230 | if (strncmp(date_fmt, "%f", 2) == 0) { | ||
231 | date_fmt = "%Y.%m.%d-%H:%M:%S"; | ||
232 | } | ||
233 | |||
234 | /* Generate output string */ | ||
235 | strftime(bb_common_bufsiz1, 200, date_fmt, &tm_time); | ||
236 | } | ||
237 | puts(bb_common_bufsiz1); | ||
238 | |||
239 | return EXIT_SUCCESS; | ||
240 | } |