00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef lint
00043 static const char rcsid[] =
00044 "$FreeBSD: src/usr.sbin/pw/psdate.c,v 1.6.2.1 2000/06/28 19:19:04 ache Exp $";
00045 #endif
00046
00047 #include <portable_io.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <ctype.h>
00051 #include <parse_date.h>
00052
00053
00054
00055
00056 static int
00057 a2i(char const ** str)
00058
00059
00060
00061
00062 {
00063 int i = 0;
00064 char const *s = *str;
00065
00066 if (isdigit((unsigned char)*s)) {
00067 i = atoi(s);
00068 while (isdigit((unsigned char)*s))
00069 ++s;
00070 *str = s;
00071 }
00072 return i;
00073 }
00074
00075 static int
00076 numerics(char const * str)
00077
00078
00079
00080
00081 {
00082 int rc = isdigit((unsigned char)*str);
00083
00084 if (rc)
00085 while (isdigit((unsigned char)*str) || *str == 'x')
00086 ++str;
00087 return rc && !*str;
00088 }
00089
00090 static int
00091 aindex(char const * arr[], char const ** str, int len)
00092
00093
00094
00095
00096
00097
00098
00099
00100 {
00101 int l, i;
00102 char mystr[32];
00103
00104 mystr[len] = '\0';
00105 l = strlen(strncpy(mystr, *str, len));
00106 for (i = 0; i < l; i++)
00107 mystr[i] = (char) tolower((unsigned char)mystr[i]);
00108 for (i = 0; arr[i] && strcmp(mystr, arr[i]) != 0; i++);
00109 if (arr[i] == NULL)
00110 i = -1;
00111 else {
00112 while (**str && isalpha((unsigned char)**str))
00113 ++(*str);
00114
00115 while (**str && (**str == ',' || isspace((unsigned char)**str)))
00116 ++(*str);
00117 }
00118 return i;
00119 }
00120
00121 static int
00122 weekday(char const ** str)
00123
00124
00125
00126
00127
00128 {
00129 static char const *days[] =
00130 {"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL};
00131
00132 return aindex(days, str, 3);
00133 }
00134
00135 static int
00136 month(char const ** str)
00137
00138
00139
00140
00141
00142 {
00143 static char const *months[] =
00144 {"jan", "feb", "mar", "apr", "may", "jun", "jul",
00145 "aug", "sep", "oct", "nov", "dec", NULL};
00146
00147 return aindex(months, str, 3);
00148 }
00149
00150 static void
00151 parse_time(char const * str, int *hour, int *min, int *sec)
00152
00153
00154
00155
00156 {
00157 *hour = a2i(&str);
00158 if ((str = strchr(str, ':')) == NULL)
00159 *min = *sec = 0;
00160 else {
00161 ++str;
00162 *min = a2i(&str);
00163 *sec = ((str = strchr(str, ':')) == NULL) ? 0 : atoi(++str);
00164 }
00165 }
00166
00167
00168 static void
00169 parse_datesub(char const * str, int *day, int *mon, int *year)
00170
00171
00172
00173
00174 {
00175 int i;
00176
00177 static char const nchrs[] = "0123456789 \t,/-.";
00178
00179 if ((i = month(&str)) != -1) {
00180 *mon = i;
00181 if ((i = a2i(&str)) != 0)
00182 *day = i;
00183 } else if ((i = a2i(&str)) != 0) {
00184 *day = i;
00185 while (*str && strchr(nchrs + 10, *str) != NULL)
00186 ++str;
00187 if ((i = month(&str)) != -1)
00188 *mon = i;
00189 else if ((i = a2i(&str)) != 0)
00190 *mon = i - 1;
00191 } else
00192 return;
00193
00194 while (*str && strchr(nchrs + 10, *str) != NULL)
00195 ++str;
00196 if (isdigit((unsigned char)*str)) {
00197 *year = atoi(str);
00198 if (*year > 1900)
00199 *year -= 1900;
00200 else if (*year < 32)
00201 *year += 100;
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 time_t
00219 parse_date(char const * str, time_t dt)
00220 {
00221 char *p;
00222 int i;
00223 long val;
00224 struct tm *T;
00225
00226
00227
00228
00229
00230
00231 if (dt == 0)
00232 dt = time(NULL);
00233
00234
00235
00236
00237
00238 while (*str && isspace((unsigned char)*str))
00239 ++str;
00240
00241 if (numerics(str)) {
00242
00243
00244
00245
00246
00247 dt = strtol(str, &p, 0);
00248
00249 } else if (*str == '+' || *str == '-') {
00250
00251
00252
00253
00254
00255
00256
00257
00258 val = strtol(str, &p, 0);
00259 switch (*p) {
00260 case 'h':
00261 case 'H':
00262 dt += (val * 3600L);
00263 break;
00264 case '\0':
00265 case 'm':
00266 case 'M':
00267 dt += (val * 60L);
00268 break;
00269 case 's':
00270 case 'S':
00271 dt += val;
00272 break;
00273 case 'd':
00274 case 'D':
00275 dt += (val * 86400L);
00276 break;
00277 case 'w':
00278 case 'W':
00279 dt += (val * 604800L);
00280 break;
00281 case 'o':
00282 case 'O':
00283 T = localtime(&dt);
00284 T->tm_mon += (int) val;
00285 i = T->tm_mday;
00286 goto fixday;
00287 case 'y':
00288 case 'Y':
00289 T = localtime(&dt);
00290 T->tm_year += (int) val;
00291 i = T->tm_mday;
00292 fixday:
00293 dt = mktime(T);
00294 T = localtime(&dt);
00295 if (T->tm_mday != i) {
00296 T->tm_mday = 1;
00297 dt = mktime(T);
00298 dt -= (time_t) 86400L;
00299 }
00300 default:
00301 break;
00302 }
00303 } else {
00304
00305
00306
00307
00308
00309
00310
00311
00312 char *q, tmp[64];
00313
00314
00315
00316
00317 weekday(&str);
00318 str = strncpy(tmp, str, sizeof tmp - 1);
00319 tmp[sizeof tmp - 1] = '\0';
00320 T = localtime(&dt);
00321 T->tm_isdst = -1;
00322
00323
00324
00325
00326 while ((q = strrchr(tmp, ' ')) != NULL) {
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 if (strchr("(+-", q[1]) != NULL)
00337 *q = '\0';
00338 else {
00339 int j = 1;
00340
00341 while (q[j] && isupper((unsigned char)q[j]))
00342 ++j;
00343 if (q[j] == '\0')
00344 *q = '\0';
00345 else
00346 break;
00347 }
00348 }
00349
00350
00351
00352
00353 if ((p = strchr(tmp, ':')) == NULL) {
00354
00355
00356
00357
00358 T->tm_hour = T->tm_min = T->tm_sec = 0;
00359 parse_datesub(tmp, &T->tm_mday, &T->tm_mon, &T->tm_year);
00360
00361 } else {
00362 char datestr[64], timestr[64];
00363
00364
00365
00366
00367 if ((q = strpbrk(p, " \t")) != NULL) {
00368 int l = q - str;
00369
00370 strncpy(timestr, str, l);
00371 timestr[l] = '\0';
00372 strncpy(datestr, q + 1, sizeof datestr);
00373 datestr[sizeof datestr - 1] = '\0';
00374 parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
00375 parse_datesub(datestr, &T->tm_mday, &T->tm_mon, &T->tm_year);
00376 } else if ((q = strrchr(tmp, ' ')) != NULL) {
00377 int l = q - tmp;
00378
00379 strncpy(timestr, q + 1, sizeof timestr);
00380 timestr[sizeof timestr - 1] = '\0';
00381 strncpy(datestr, tmp, l);
00382 datestr[l] = '\0';
00383 } else
00384 return dt;
00385 parse_time(timestr, &T->tm_hour, &T->tm_min, &T->tm_sec);
00386 parse_datesub(datestr, &T->tm_mday, &T->tm_mon, &T->tm_year);
00387 }
00388 dt = mktime(T);
00389 }
00390 return dt;
00391 }
00392