Annotation of src/usr.bin/at/parsetime.c, Revision 1.13
1.13 ! millert 1: /* $OpenBSD: parsetime.c,v 1.12 2002/06/14 21:35:00 todd Exp $ */
1.1 deraadt 2:
3: /*
4: * parsetime.c - parse time for at(1)
1.4 millert 5: * Copyright (C) 1993, 1994 Thomas Koenig
1.1 deraadt 6: *
7: * modifications for english-language times
8: * Copyright (C) 1993 David Parsons
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. The name of the author(s) may not be used to endorse or promote
16: * products derived from this software without specific prior written
17: * permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1.4 millert 22: * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
1.1 deraadt 23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: *
30: * at [NOW] PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS
31: * /NUMBER [DOT NUMBER] [AM|PM]\ /[MONTH NUMBER [NUMBER]] \
32: * |NOON | |[TOMORROW] |
1.4 millert 33: * |MIDNIGHT | |[DAY OF WEEK] |
34: * \TEATIME / |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
35: * \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
1.1 deraadt 36: */
37:
38: #include <sys/types.h>
39: #include <errno.h>
1.11 millert 40: #include <ctype.h>
1.1 deraadt 41: #include <stdio.h>
42: #include <stdlib.h>
43: #include <string.h>
44: #include <time.h>
1.8 alex 45: #include <tzfile.h>
1.1 deraadt 46: #include <unistd.h>
47:
1.13 ! millert 48: #include "globals.h"
1.1 deraadt 49: #include "at.h"
50:
51: /* Structures and unions */
52:
53: enum { /* symbols */
1.4 millert 54: MIDNIGHT, NOON, TEATIME,
55: PM, AM, TOMORROW, TODAY, NOW,
56: MINUTES, HOURS, DAYS, WEEKS,
57: NUMBER, PLUS, DOT, SLASH, ID, JUNK,
58: JAN, FEB, MAR, APR, MAY, JUN,
59: JUL, AUG, SEP, OCT, NOV, DEC,
60: SUN, MON, TUE, WED, THU, FRI, SAT
1.1 deraadt 61: };
62:
63: /*
64: * parse translation table - table driven parsers can be your FRIEND!
65: */
66: struct {
1.4 millert 67: char *name; /* token name */
68: int value; /* token id */
69: int plural; /* is this plural? */
1.1 deraadt 70: } Specials[] = {
1.4 millert 71: { "midnight", MIDNIGHT, 0 }, /* 00:00:00 of today or tomorrow */
72: { "noon", NOON, 0 }, /* 12:00:00 of today or tomorrow */
73: { "teatime", TEATIME, 0 }, /* 16:00:00 of today or tomorrow */
74: { "am", AM, 0 }, /* morning times for 0-12 clock */
75: { "pm", PM, 0 }, /* evening times for 0-12 clock */
76: { "tomorrow", TOMORROW, 0 }, /* execute 24 hours from time */
77: { "today", TODAY, 0 }, /* execute today - don't advance time */
78: { "now", NOW, 0 }, /* opt prefix for PLUS */
79:
80: { "minute", MINUTES, 0 }, /* minutes multiplier */
81: { "min", MINUTES, 0 },
82: { "m", MINUTES, 0 },
83: { "minutes", MINUTES, 1 }, /* (pluralized) */
84: { "hour", HOURS, 0 }, /* hours ... */
85: { "hr", HOURS, 0 }, /* abbreviated */
86: { "h", HOURS, 0 },
87: { "hours", HOURS, 1 }, /* (pluralized) */
88: { "day", DAYS, 0 }, /* days ... */
89: { "d", DAYS, 0 },
90: { "days", DAYS, 1 }, /* (pluralized) */
91: { "week", WEEKS, 0 }, /* week ... */
92: { "w", WEEKS, 0 },
93: { "weeks", WEEKS, 1 }, /* (pluralized) */
94: { "jan", JAN, 0 },
95: { "feb", FEB, 0 },
96: { "mar", MAR, 0 },
97: { "apr", APR, 0 },
98: { "may", MAY, 0 },
99: { "jun", JUN, 0 },
100: { "jul", JUL, 0 },
101: { "aug", AUG, 0 },
102: { "sep", SEP, 0 },
103: { "oct", OCT, 0 },
104: { "nov", NOV, 0 },
105: { "dec", DEC, 0 },
1.7 deraadt 106: { "january", JAN,0 },
107: { "february", FEB,0 },
108: { "march", MAR,0 },
109: { "april", APR,0 },
110: { "may", MAY,0 },
111: { "june", JUN,0 },
112: { "july", JUL,0 },
113: { "august", AUG,0 },
114: { "september", SEP,0 },
115: { "october", OCT,0 },
116: { "november", NOV,0 },
117: { "december", DEC,0 },
1.4 millert 118: { "sunday", SUN, 0 },
119: { "sun", SUN, 0 },
120: { "monday", MON, 0 },
121: { "mon", MON, 0 },
122: { "tuesday", TUE, 0 },
123: { "tue", TUE, 0 },
124: { "wednesday", WED, 0 },
125: { "wed", WED, 0 },
126: { "thursday", THU, 0 },
127: { "thu", THU, 0 },
128: { "friday", FRI, 0 },
129: { "fri", FRI, 0 },
130: { "saturday", SAT, 0 },
131: { "sat", SAT, 0 },
132: };
1.1 deraadt 133:
134: static char **scp; /* scanner - pointer at arglist */
135: static char scc; /* scanner - count of remaining arguments */
136: static char *sct; /* scanner - next char pointer in current argument */
137: static int need; /* scanner - need to advance to next argument */
138: static char *sc_token; /* scanner - token buffer */
1.12 todd 139: static size_t sc_len; /* scanner - length of token buffer */
1.1 deraadt 140: static int sc_tokid; /* scanner - token id */
1.4 millert 141: static int sc_tokplur; /* scanner - is token plural? */
1.1 deraadt 142:
143: #ifndef lint
1.13 ! millert 144: static const char rcsid[] = "$OpenBSD: parsetime.c,v 1.12 2002/06/14 21:35:00 todd Exp $";
1.1 deraadt 145: #endif
146:
147: /*
148: * parse a token, checking if it's something special to us
149: */
150: static int
1.10 millert 151: parse_token(char *arg)
1.1 deraadt 152: {
1.4 millert 153: int i;
1.1 deraadt 154:
1.4 millert 155: for (i=0; i < sizeof(Specials) / sizeof(Specials[0]); i++) {
156: if (strcasecmp(Specials[i].name, arg) == 0) {
157: sc_tokplur = Specials[i].plural;
158: return (sc_tokid = Specials[i].value);
159: }
1.1 deraadt 160: }
161:
1.4 millert 162: /* not special - must be some random id */
163: return (ID);
1.11 millert 164: }
1.1 deraadt 165:
166:
167: /*
168: * init_scanner() sets up the scanner to eat arguments
169: */
1.13 ! millert 170: static int
1.10 millert 171: init_scanner(int argc, char **argv)
1.1 deraadt 172: {
1.4 millert 173: scp = argv;
174: scc = argc;
175: need = 1;
176: sc_len = 1;
177: while (argc-- > 0)
178: sc_len += strlen(*argv++);
179:
1.13 ! millert 180: if ((sc_token = (char *) malloc(sc_len)) == NULL) {
! 181: fprintf(stderr, "%s: Insufficient virtual memory\n",
! 182: ProgramName);
! 183: return (-1);
! 184: }
! 185: return (0);
1.11 millert 186: }
1.1 deraadt 187:
188: /*
189: * token() fetches a token from the input stream
190: */
191: static int
1.10 millert 192: token(void)
1.1 deraadt 193: {
1.4 millert 194: int idx;
1.1 deraadt 195:
1.10 millert 196: for (;;) {
1.13 ! millert 197: bzero(sc_token, sc_len);
1.4 millert 198: sc_tokid = EOF;
199: sc_tokplur = 0;
200: idx = 0;
1.1 deraadt 201:
1.4 millert 202: /*
203: * if we need to read another argument, walk along the
204: * argument list; when we fall off the arglist, we'll
205: * just return EOF forever
206: */
207: if (need) {
208: if (scc < 1)
209: return (sc_tokid);
210: sct = *scp;
211: scp++;
212: scc--;
213: need = 0;
214: }
215: /*
216: * eat whitespace now - if we walk off the end of the argument,
217: * we'll continue, which puts us up at the top of the while loop
218: * to fetch the next argument in
219: */
220: while (isspace(*sct))
221: ++sct;
222: if (!*sct) {
223: need = 1;
224: continue;
225: }
1.1 deraadt 226:
1.4 millert 227: /*
228: * preserve the first character of the new token
229: */
230: sc_token[0] = *sct++;
1.1 deraadt 231:
1.4 millert 232: /*
233: * then see what it is
234: */
235: if (isdigit(sc_token[0])) {
236: while (isdigit(*sct))
237: sc_token[++idx] = *sct++;
238: sc_token[++idx] = 0;
239: return ((sc_tokid = NUMBER));
240: } else if (isalpha(sc_token[0])) {
241: while (isalpha(*sct))
242: sc_token[++idx] = *sct++;
243: sc_token[++idx] = 0;
244: return (parse_token(sc_token));
245: }
246: else if (sc_token[0] == ':' || sc_token[0] == '.')
247: return ((sc_tokid = DOT));
248: else if (sc_token[0] == '+')
249: return ((sc_tokid = PLUS));
250: else if (sc_token[0] == '/')
251: return ((sc_tokid = SLASH));
252: else
253: return ((sc_tokid = JUNK));
1.11 millert 254: }
255: }
1.1 deraadt 256:
257:
258: /*
259: * plonk() gives an appropriate error message if a token is incorrect
260: */
261: static void
1.10 millert 262: plonk(int tok)
1.1 deraadt 263: {
1.13 ! millert 264: fprintf(stderr, "%s: %s time\n", ProgramName,
! 265: (tok == EOF) ? "incomplete" : "garbled");
1.11 millert 266: }
1.1 deraadt 267:
268:
269: /*
1.13 ! millert 270: * expect() gets a token and returns -1 if it's not the token we want
1.1 deraadt 271: */
1.13 ! millert 272: static int
1.10 millert 273: expect(int desired)
1.1 deraadt 274: {
1.13 ! millert 275: if (token() != desired) {
! 276: plonk(sc_tokid);
! 277: return (-1);
! 278: }
! 279: return (0);
1.11 millert 280: }
1.1 deraadt 281:
282:
283: /*
284: * dateadd() adds a number of minutes to a date. It is extraordinarily
285: * stupid regarding day-of-month overflow, and will most likely not
286: * work properly
287: */
288: static void
1.10 millert 289: dateadd(int minutes, struct tm *tm)
1.1 deraadt 290: {
1.4 millert 291: /* increment days */
1.1 deraadt 292:
1.4 millert 293: while (minutes > 24*60) {
294: minutes -= 24*60;
295: tm->tm_mday++;
1.1 deraadt 296: }
297:
1.4 millert 298: /* increment hours */
299: while (minutes > 60) {
300: minutes -= 60;
301: tm->tm_hour++;
302: if (tm->tm_hour > 23) {
303: tm->tm_mday++;
304: tm->tm_hour = 0;
305: }
306: }
307:
308: /* increment minutes */
309: tm->tm_min += minutes;
1.1 deraadt 310:
1.4 millert 311: if (tm->tm_min > 59) {
312: tm->tm_hour++;
313: tm->tm_min -= 60;
314:
315: if (tm->tm_hour > 23) {
316: tm->tm_mday++;
317: tm->tm_hour = 0;
318: }
1.1 deraadt 319: }
1.11 millert 320: }
1.1 deraadt 321:
322:
323: /*
324: * plus() parses a now + time
325: *
326: * at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS]
327: *
328: */
1.13 ! millert 329: static int
1.10 millert 330: plus(struct tm *tm)
1.1 deraadt 331: {
1.4 millert 332: int delay;
333: int expectplur;
334:
1.13 ! millert 335: if (expect(NUMBER) != 0)
! 336: return (-1);
1.1 deraadt 337:
1.4 millert 338: delay = atoi(sc_token);
339: expectplur = (delay != 1) ? 1 : 0;
1.1 deraadt 340:
1.4 millert 341: switch (token()) {
342: case WEEKS:
343: delay *= 7;
344: case DAYS:
345: delay *= 24;
346: case HOURS:
347: delay *= 60;
348: case MINUTES:
349: if (expectplur != sc_tokplur)
1.13 ! millert 350: fprintf(stderr, "%s: pluralization is wrong\n",
! 351: ProgramName);
1.4 millert 352: dateadd(delay, tm);
1.13 ! millert 353: return (0);
1.4 millert 354: }
1.1 deraadt 355:
1.4 millert 356: plonk(sc_tokid);
1.13 ! millert 357: return (-1);
1.11 millert 358: }
1.1 deraadt 359:
360:
361: /*
362: * tod() computes the time of day
363: * [NUMBER [DOT NUMBER] [AM|PM]]
364: */
1.13 ! millert 365: static int
1.10 millert 366: tod(struct tm *tm)
1.1 deraadt 367: {
1.4 millert 368: int hour, minute = 0;
369: size_t tlen;
370:
371: hour = atoi(sc_token);
372: tlen = strlen(sc_token);
373:
374: /*
375: * first pick out the time of day - if it's 4 digits, we assume
376: * a HHMM time, otherwise it's HH DOT MM time
377: */
378: if (token() == DOT) {
1.13 ! millert 379: if (expect(NUMBER) != 0)
! 380: return (-1);
1.4 millert 381: minute = atoi(sc_token);
382: if (minute > 59)
1.13 ! millert 383: goto bad;
1.4 millert 384: token();
385: } else if (tlen == 4) {
386: minute = hour % 100;
387: if (minute > 59)
1.13 ! millert 388: goto bad;
1.4 millert 389: hour = hour / 100;
390: }
1.1 deraadt 391:
1.4 millert 392: /*
393: * check if an AM or PM specifier was given
394: */
395: if (sc_tokid == AM || sc_tokid == PM) {
396: if (hour > 12)
1.13 ! millert 397: goto bad;
1.4 millert 398:
399: if (sc_tokid == PM) {
400: if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */
401: hour += 12;
402: } else {
403: if (hour == 12) /* 12:xx AM is 00:xx, not 12:xx */
404: hour = 0;
405: }
406: token();
407: } else if (hour > 23)
1.13 ! millert 408: goto bad;
1.1 deraadt 409:
1.4 millert 410: /*
411: * if we specify an absolute time, we don't want to bump the day even
412: * if we've gone past that time - but if we're specifying a time plus
413: * a relative offset, it's okay to bump things
414: */
415: if ((sc_tokid == EOF || sc_tokid == PLUS) && tm->tm_hour > hour) {
416: tm->tm_mday++;
417: tm->tm_wday++;
418: }
1.1 deraadt 419:
1.4 millert 420: tm->tm_hour = hour;
421: tm->tm_min = minute;
422: if (tm->tm_hour == 24) {
423: tm->tm_hour = 0;
424: tm->tm_mday++;
425: }
1.13 ! millert 426: return (0);
! 427: bad:
! 428: fprintf(stderr, "%s: garbled time\n", ProgramName);
! 429: return (-1);
1.11 millert 430: }
1.1 deraadt 431:
432:
433: /*
434: * assign_date() assigns a date, wrapping to next year if needed
435: */
436: static void
1.10 millert 437: assign_date(struct tm *tm, int mday, int mon, int year)
1.1 deraadt 438: {
1.9 millert 439:
440: /*
441: * Convert year into tm_year format (year - 1900).
442: * We may be given the year in 2 digit, 4 digit, or tm_year format.
443: */
444: if (year != -1) {
445: if (year >= TM_YEAR_BASE)
446: year -= TM_YEAR_BASE; /* convert from 4 digit year */
447: else if (year < 100) {
448: /* Convert to tm_year assuming current century */
449: year += (tm->tm_year / 100) * 100;
450:
451: if (year == tm->tm_year - 1)
452: year++; /* Common off by one error */
453: else if (year < tm->tm_year)
454: year += 100; /* must be in next century */
455: }
1.4 millert 456: }
457:
458: if (year < 0 &&
459: (tm->tm_mon > mon ||(tm->tm_mon == mon && tm->tm_mday > mday)))
460: year = tm->tm_year + 1;
1.1 deraadt 461:
1.4 millert 462: tm->tm_mday = mday;
463: tm->tm_mon = mon;
1.1 deraadt 464:
1.4 millert 465: if (year >= 0)
466: tm->tm_year = year;
1.11 millert 467: }
1.1 deraadt 468:
469:
470: /*
471: * month() picks apart a month specification
472: *
473: * /[<month> NUMBER [NUMBER]] \
474: * |[TOMORROW] |
1.4 millert 475: * |[DAY OF WEEK] |
1.1 deraadt 476: * |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
477: * \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
478: */
1.13 ! millert 479: static int
1.10 millert 480: month(struct tm *tm)
1.1 deraadt 481: {
1.4 millert 482: int year = (-1);
483: int mday, wday, mon;
484: size_t tlen;
485:
486: switch (sc_tokid) {
487: case PLUS:
1.13 ! millert 488: if (plus(tm) != 0)
! 489: return (-1);
1.4 millert 490: break;
491:
492: case TOMORROW:
493: /* do something tomorrow */
494: tm->tm_mday++;
495: tm->tm_wday++;
496: case TODAY:
497: /* force ourselves to stay in today - no further processing */
1.1 deraadt 498: token();
1.4 millert 499: break;
1.1 deraadt 500:
1.4 millert 501: case JAN: case FEB: case MAR: case APR: case MAY: case JUN:
502: case JUL: case AUG: case SEP: case OCT: case NOV: case DEC:
503: /*
504: * do month mday [year]
505: */
506: mon = sc_tokid - JAN;
1.13 ! millert 507: if (expect(NUMBER) != 0)
! 508: return (-1);
1.4 millert 509: mday = atoi(sc_token);
510: if (token() == NUMBER) {
511: year = atoi(sc_token);
512: token();
1.1 deraadt 513: }
1.4 millert 514: assign_date(tm, mday, mon, year);
515: break;
516:
517: case SUN: case MON: case TUE:
518: case WED: case THU: case FRI:
519: case SAT:
520: /* do a particular day of the week */
521: wday = sc_tokid - SUN;
522:
523: mday = tm->tm_mday;
524:
525: /* if this day is < today, then roll to next week */
526: if (wday < tm->tm_wday)
527: mday += 7 - (tm->tm_wday - wday);
528: else
529: mday += (wday - tm->tm_wday);
530:
531: tm->tm_wday = wday;
532:
533: assign_date(tm, mday, tm->tm_mon, tm->tm_year);
534: break;
1.1 deraadt 535:
1.4 millert 536: case NUMBER:
1.1 deraadt 537: /*
1.4 millert 538: * get numeric MMDDYY, mm/dd/yy, or dd.mm.yy
1.1 deraadt 539: */
1.4 millert 540: tlen = strlen(sc_token);
541: mon = atoi(sc_token);
542: token();
1.1 deraadt 543:
1.4 millert 544: if (sc_tokid == SLASH || sc_tokid == DOT) {
545: int sep;
1.1 deraadt 546:
1.4 millert 547: sep = sc_tokid;
1.13 ! millert 548: if (expect(NUMBER) != 0)
! 549: return (-1);
1.4 millert 550: mday = atoi(sc_token);
551: if (token() == sep) {
1.13 ! millert 552: if (expect(NUMBER) != 0)
! 553: return (-1);
1.4 millert 554: year = atoi(sc_token);
555: token();
556: }
557:
558: /*
559: * flip months and days for european timing
560: */
561: if (sep == DOT) {
562: int x = mday;
563: mday = mon;
564: mon = x;
565: }
566: } else if (tlen == 6 || tlen == 8) {
567: if (tlen == 8) {
1.8 alex 568: year = (mon % 10000) - TM_YEAR_BASE;
1.4 millert 569: mon /= 10000;
570: } else {
571: year = mon % 100;
572: mon /= 100;
573: }
574: mday = mon % 100;
575: mon /= 100;
576: } else
1.13 ! millert 577: goto bad;
1.4 millert 578:
579: mon--;
580: if (mon < 0 || mon > 11 || mday < 1 || mday > 31)
1.13 ! millert 581: goto bad;
1.4 millert 582:
583: assign_date(tm, mday, mon, year);
584: break;
1.13 ! millert 585: }
! 586: return (0);
! 587: bad:
! 588: fprintf(stderr, "%s: garbled time\n", ProgramName);
! 589: return (-1);
1.11 millert 590: }
1.1 deraadt 591:
592:
593: time_t
1.10 millert 594: parsetime(int argc, char **argv)
1.1 deraadt 595: {
1.4 millert 596: /*
597: * Do the argument parsing, die if necessary, and return the
598: * time the job should be run.
599: */
600: time_t nowtimer, runtimer;
601: struct tm nowtime, runtime;
602: int hr = 0;
603: /* this MUST be initialized to zero for midnight/noon/teatime */
604:
1.13 ! millert 605: if (argc == 0)
! 606: return (-1);
! 607:
1.4 millert 608: nowtimer = time(NULL);
609: nowtime = *localtime(&nowtimer);
610:
611: runtime = nowtime;
612: runtime.tm_sec = 0;
613: runtime.tm_isdst = 0;
614:
1.13 ! millert 615: if (init_scanner(argc, argv) == -1)
! 616: return (-1);
1.4 millert 617:
618: switch (token()) {
619: case NOW: /* now is optional prefix for PLUS tree */
1.5 millert 620: token();
621: if (sc_tokid == EOF) {
622: runtime = nowtime;
623: break;
624: }
625: else if (sc_tokid != PLUS)
626: plonk(sc_tokid);
1.4 millert 627: case PLUS:
1.13 ! millert 628: if (plus(&runtime) != 0)
! 629: return (-1);
1.4 millert 630: break;
631:
632: case NUMBER:
1.13 ! millert 633: if (tod(&runtime) != 0 || month(&runtime) != 0)
! 634: return (-1);
1.4 millert 635: break;
636:
637: /*
638: * evil coding for TEATIME|NOON|MIDNIGHT - we've initialised
639: * hr to zero up above, then fall into this case in such a
640: * way so we add +12 +4 hours to it for teatime, +12 hours
641: * to it for noon, and nothing at all for midnight, then
642: * set our runtime to that hour before leaping into the
643: * month scanner
644: */
645: case TEATIME:
646: hr += 4;
647: case NOON:
648: hr += 12;
649: case MIDNIGHT:
650: if (runtime.tm_hour >= hr) {
651: runtime.tm_mday++;
652: runtime.tm_wday++;
653: }
654: runtime.tm_hour = hr;
655: runtime.tm_min = 0;
656: token();
657: /* fall through to month setting */
658: default:
1.13 ! millert 659: if (month(&runtime) != 0)
! 660: return (-1);
1.4 millert 661: break;
662: } /* ugly case statement */
1.13 ! millert 663: if (expect(EOF) != 0)
! 664: return (-1);
1.4 millert 665:
666: /*
667: * adjust for daylight savings time
668: */
669: runtime.tm_isdst = -1;
1.1 deraadt 670: runtimer = mktime(&runtime);
1.4 millert 671: if (runtime.tm_isdst > 0) {
672: runtimer -= 3600;
673: runtimer = mktime(&runtime);
674: }
1.1 deraadt 675:
1.13 ! millert 676: if (runtimer < 0) {
! 677: fprintf(stderr, "%s: garbled time\n", ProgramName);
! 678: return (-1);
! 679: }
1.1 deraadt 680:
1.13 ! millert 681: if (nowtimer > runtimer) {
! 682: fprintf(stderr, "%s: Trying to travel back in time\n",
! 683: ProgramName);
! 684: return (-1);
! 685: }
1.1 deraadt 686:
1.4 millert 687: return (runtimer);
1.11 millert 688: }