Contents of /trunk/mkinitrd-magellan/busybox/coreutils/date.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 6608 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years 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 | /* 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 | } |