version 1.12, 2002/06/14 21:35:00 |
version 1.13, 2003/02/20 20:38:08 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: parsetime.c,v 1.3 1995/03/25 18:13:36 glass Exp $ */ |
|
|
|
/* |
/* |
* parsetime.c - parse time for at(1) |
* parsetime.c - parse time for at(1) |
|
|
*/ |
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <err.h> |
|
#include <errno.h> |
#include <errno.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <stdio.h> |
#include <stdio.h> |
|
|
#include <tzfile.h> |
#include <tzfile.h> |
#include <unistd.h> |
#include <unistd.h> |
|
|
|
#include "globals.h" |
#include "at.h" |
#include "at.h" |
#include "panic.h" |
|
|
|
|
|
/* Structures and unions */ |
/* Structures and unions */ |
|
|
enum { /* symbols */ |
enum { /* symbols */ |
|
|
/* |
/* |
* init_scanner() sets up the scanner to eat arguments |
* init_scanner() sets up the scanner to eat arguments |
*/ |
*/ |
static void |
static int |
init_scanner(int argc, char **argv) |
init_scanner(int argc, char **argv) |
{ |
{ |
scp = argv; |
scp = argv; |
|
|
while (argc-- > 0) |
while (argc-- > 0) |
sc_len += strlen(*argv++); |
sc_len += strlen(*argv++); |
|
|
if ((sc_token = (char *) malloc(sc_len)) == NULL) |
if ((sc_token = (char *) malloc(sc_len)) == NULL) { |
panic("Insufficient virtual memory"); |
fprintf(stderr, "%s: Insufficient virtual memory\n", |
|
ProgramName); |
|
return (-1); |
|
} |
|
return (0); |
} |
} |
|
|
/* |
/* |
|
|
int idx; |
int idx; |
|
|
for (;;) { |
for (;;) { |
(void)memset(sc_token, 0, sc_len); |
bzero(sc_token, sc_len); |
sc_tokid = EOF; |
sc_tokid = EOF; |
sc_tokplur = 0; |
sc_tokplur = 0; |
idx = 0; |
idx = 0; |
|
|
static void |
static void |
plonk(int tok) |
plonk(int tok) |
{ |
{ |
panic((tok == EOF) ? "incomplete time" : "garbled time"); |
fprintf(stderr, "%s: %s time\n", ProgramName, |
|
(tok == EOF) ? "incomplete" : "garbled"); |
} |
} |
|
|
|
|
/* |
/* |
* expect() gets a token and dies most horribly if it's not the token we want |
* expect() gets a token and returns -1 if it's not the token we want |
*/ |
*/ |
static void |
static int |
expect(int desired) |
expect(int desired) |
{ |
{ |
if (token() != desired) |
if (token() != desired) { |
plonk(sc_tokid); /* and we die here... */ |
plonk(sc_tokid); |
|
return (-1); |
|
} |
|
return (0); |
} |
} |
|
|
|
|
|
|
* at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS] |
* at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS] |
* |
* |
*/ |
*/ |
static void |
static int |
plus(struct tm *tm) |
plus(struct tm *tm) |
{ |
{ |
int delay; |
int delay; |
int expectplur; |
int expectplur; |
|
|
expect(NUMBER); |
if (expect(NUMBER) != 0) |
|
return (-1); |
|
|
delay = atoi(sc_token); |
delay = atoi(sc_token); |
expectplur = (delay != 1) ? 1 : 0; |
expectplur = (delay != 1) ? 1 : 0; |
|
|
delay *= 60; |
delay *= 60; |
case MINUTES: |
case MINUTES: |
if (expectplur != sc_tokplur) |
if (expectplur != sc_tokplur) |
warnx("pluralization is wrong"); |
fprintf(stderr, "%s: pluralization is wrong\n", |
|
ProgramName); |
dateadd(delay, tm); |
dateadd(delay, tm); |
return; |
return (0); |
} |
} |
|
|
plonk(sc_tokid); |
plonk(sc_tokid); |
|
return (-1); |
} |
} |
|
|
|
|
|
|
* tod() computes the time of day |
* tod() computes the time of day |
* [NUMBER [DOT NUMBER] [AM|PM]] |
* [NUMBER [DOT NUMBER] [AM|PM]] |
*/ |
*/ |
static void |
static int |
tod(struct tm *tm) |
tod(struct tm *tm) |
{ |
{ |
int hour, minute = 0; |
int hour, minute = 0; |
|
|
* a HHMM time, otherwise it's HH DOT MM time |
* a HHMM time, otherwise it's HH DOT MM time |
*/ |
*/ |
if (token() == DOT) { |
if (token() == DOT) { |
expect(NUMBER); |
if (expect(NUMBER) != 0) |
|
return (-1); |
minute = atoi(sc_token); |
minute = atoi(sc_token); |
if (minute > 59) |
if (minute > 59) |
panic("garbled time"); |
goto bad; |
token(); |
token(); |
} else if (tlen == 4) { |
} else if (tlen == 4) { |
minute = hour % 100; |
minute = hour % 100; |
if (minute > 59) |
if (minute > 59) |
panic("garbled time"); |
goto bad; |
hour = hour / 100; |
hour = hour / 100; |
} |
} |
|
|
|
|
*/ |
*/ |
if (sc_tokid == AM || sc_tokid == PM) { |
if (sc_tokid == AM || sc_tokid == PM) { |
if (hour > 12) |
if (hour > 12) |
panic("garbled time"); |
goto bad; |
|
|
if (sc_tokid == PM) { |
if (sc_tokid == PM) { |
if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */ |
if (hour != 12) /* 12:xx PM is 12:xx, not 24:xx */ |
|
|
} |
} |
token(); |
token(); |
} else if (hour > 23) |
} else if (hour > 23) |
panic("garbled time"); |
goto bad; |
|
|
/* |
/* |
* if we specify an absolute time, we don't want to bump the day even |
* if we specify an absolute time, we don't want to bump the day even |
|
|
tm->tm_hour = 0; |
tm->tm_hour = 0; |
tm->tm_mday++; |
tm->tm_mday++; |
} |
} |
|
return (0); |
|
bad: |
|
fprintf(stderr, "%s: garbled time\n", ProgramName); |
|
return (-1); |
} |
} |
|
|
|
|
|
|
* |NUMBER [SLASH NUMBER [SLASH NUMBER]]| |
* |NUMBER [SLASH NUMBER [SLASH NUMBER]]| |
* \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/ |
* \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/ |
*/ |
*/ |
static void |
static int |
month(struct tm *tm) |
month(struct tm *tm) |
{ |
{ |
int year = (-1); |
int year = (-1); |
|
|
|
|
switch (sc_tokid) { |
switch (sc_tokid) { |
case PLUS: |
case PLUS: |
plus(tm); |
if (plus(tm) != 0) |
|
return (-1); |
break; |
break; |
|
|
case TOMORROW: |
case TOMORROW: |
|
|
* do month mday [year] |
* do month mday [year] |
*/ |
*/ |
mon = sc_tokid - JAN; |
mon = sc_tokid - JAN; |
expect(NUMBER); |
if (expect(NUMBER) != 0) |
|
return (-1); |
mday = atoi(sc_token); |
mday = atoi(sc_token); |
if (token() == NUMBER) { |
if (token() == NUMBER) { |
year = atoi(sc_token); |
year = atoi(sc_token); |
|
|
int sep; |
int sep; |
|
|
sep = sc_tokid; |
sep = sc_tokid; |
expect(NUMBER); |
if (expect(NUMBER) != 0) |
|
return (-1); |
mday = atoi(sc_token); |
mday = atoi(sc_token); |
if (token() == sep) { |
if (token() == sep) { |
expect(NUMBER); |
if (expect(NUMBER) != 0) |
|
return (-1); |
year = atoi(sc_token); |
year = atoi(sc_token); |
token(); |
token(); |
} |
} |
|
|
mday = mon % 100; |
mday = mon % 100; |
mon /= 100; |
mon /= 100; |
} else |
} else |
panic("garbled time"); |
goto bad; |
|
|
mon--; |
mon--; |
if (mon < 0 || mon > 11 || mday < 1 || mday > 31) |
if (mon < 0 || mon > 11 || mday < 1 || mday > 31) |
panic("garbled time"); |
goto bad; |
|
|
assign_date(tm, mday, mon, year); |
assign_date(tm, mday, mon, year); |
break; |
break; |
} /* case */ |
} |
|
return (0); |
|
bad: |
|
fprintf(stderr, "%s: garbled time\n", ProgramName); |
|
return (-1); |
} |
} |
|
|
|
|
|
|
int hr = 0; |
int hr = 0; |
/* this MUST be initialized to zero for midnight/noon/teatime */ |
/* this MUST be initialized to zero for midnight/noon/teatime */ |
|
|
|
if (argc == 0) |
|
return (-1); |
|
|
nowtimer = time(NULL); |
nowtimer = time(NULL); |
nowtime = *localtime(&nowtimer); |
nowtime = *localtime(&nowtimer); |
|
|
|
|
runtime.tm_sec = 0; |
runtime.tm_sec = 0; |
runtime.tm_isdst = 0; |
runtime.tm_isdst = 0; |
|
|
if (argc == 0) |
if (init_scanner(argc, argv) == -1) |
usage(); |
return (-1); |
|
|
init_scanner(argc, argv); |
|
|
|
switch (token()) { |
switch (token()) { |
case NOW: /* now is optional prefix for PLUS tree */ |
case NOW: /* now is optional prefix for PLUS tree */ |
token(); |
token(); |
|
|
else if (sc_tokid != PLUS) |
else if (sc_tokid != PLUS) |
plonk(sc_tokid); |
plonk(sc_tokid); |
case PLUS: |
case PLUS: |
plus(&runtime); |
if (plus(&runtime) != 0) |
|
return (-1); |
break; |
break; |
|
|
case NUMBER: |
case NUMBER: |
tod(&runtime); |
if (tod(&runtime) != 0 || month(&runtime) != 0) |
month(&runtime); |
return (-1); |
break; |
break; |
|
|
/* |
/* |
|
|
token(); |
token(); |
/* fall through to month setting */ |
/* fall through to month setting */ |
default: |
default: |
month(&runtime); |
if (month(&runtime) != 0) |
|
return (-1); |
break; |
break; |
} /* ugly case statement */ |
} /* ugly case statement */ |
expect(EOF); |
if (expect(EOF) != 0) |
|
return (-1); |
|
|
/* |
/* |
* adjust for daylight savings time |
* adjust for daylight savings time |
|
|
runtimer = mktime(&runtime); |
runtimer = mktime(&runtime); |
} |
} |
|
|
if (runtimer < 0) |
if (runtimer < 0) { |
panic("garbled time"); |
fprintf(stderr, "%s: garbled time\n", ProgramName); |
|
return (-1); |
|
} |
|
|
if (nowtimer > runtimer) |
if (nowtimer > runtimer) { |
panic("Trying to travel back in time"); |
fprintf(stderr, "%s: Trying to travel back in time\n", |
|
ProgramName); |
|
return (-1); |
|
} |
|
|
return (runtimer); |
return (runtimer); |
} |
} |