Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/coreutils/date.c

Parent Directory Parent Directory | Revision Log 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)
-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     }