447 lines
8.1 KiB
Plaintext
447 lines
8.1 KiB
Plaintext
/* Copyright (c) 1984 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
/* NOTE: this was originally the att1.y code from the 'at' command */
|
|
|
|
%{
|
|
#ident "cmd/wakeupat/parse.y: $Revision: 1.7 $"
|
|
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
#include <sys/syssgi.h>
|
|
|
|
#define dysize(A) (((A)%4) ? 365 : 366)
|
|
|
|
int gmtflag = 0;
|
|
int dflag = 0;
|
|
char *prog;
|
|
char argpbuf[80];
|
|
char pname[80];
|
|
char pname1[80];
|
|
char argbuf[80];
|
|
struct tm *tp, at, rt;
|
|
extern char *argp;
|
|
char now_flag;
|
|
int utc_flag;
|
|
|
|
time_t when, now;
|
|
time_t gtime(struct tm *tptr);
|
|
void atime(struct tm *a, struct tm *b);
|
|
|
|
int mday[12] =
|
|
{
|
|
31,38,31,
|
|
30,31,30,
|
|
31,31,30,
|
|
31,30,31,
|
|
};
|
|
int mtab[12] =
|
|
{
|
|
0, 31, 59,
|
|
90, 120, 151,
|
|
181, 212, 243,
|
|
273, 304, 334,
|
|
};
|
|
int dmsize[12] = {
|
|
31,28,31,30,31,30,31,31,30,31,30,31};
|
|
|
|
|
|
main(int cnt, char **args)
|
|
{
|
|
int i;
|
|
size_t tlen = 0;
|
|
|
|
prog = *args;
|
|
|
|
if(cnt < 2) {
|
|
fprintf(stderr, "Usage: %s date string\n", prog);
|
|
exit(1);
|
|
}
|
|
|
|
for(i=1; i < cnt; i++) {
|
|
tlen += strlen(args[i]) + 1;
|
|
if(tlen >= sizeof(argpbuf)) {
|
|
fprintf(stderr, "%s: date string is too long\n", prog);
|
|
exit(2);
|
|
}
|
|
strcat(argpbuf,args[i]);
|
|
strcat(argpbuf, " ");
|
|
}
|
|
|
|
argp = argpbuf;
|
|
time(&now);
|
|
tp = localtime(&now);
|
|
mday[1] = 28 + leap(tp->tm_year);
|
|
yyparse();
|
|
atime(&at, &rt);
|
|
when = gtime(&at);
|
|
if(!gmtflag) {
|
|
when += timezone;
|
|
if(localtime(&when)->tm_isdst)
|
|
when -= 60 * 60;
|
|
}
|
|
if (utc_flag) {
|
|
if (when < now) when +=24 * 60 * 60; /* add a day */
|
|
}
|
|
if (now_flag == 2/*RIGHT_NOW*/) when = now;
|
|
if((unsigned long)when < (unsigned long)now) {
|
|
fprintf(stderr, "The date \"%s\" is before current time\n", argpbuf);
|
|
exit(3);
|
|
}
|
|
if(syssgi(SGI_SET_AUTOPWRON, when)) {
|
|
if(errno == ENOPKG)
|
|
fprintf(stderr,
|
|
"%s: This system does not support software power on\n",
|
|
prog);
|
|
else
|
|
fprintf(stderr, "%s: Unable to set auto power on time: %s\n",
|
|
prog, strerror(errno));
|
|
exit(4);
|
|
}
|
|
printf("Set power on time for: %s", ctime(&when));
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* return time from time structure
|
|
*/
|
|
time_t
|
|
gtime(struct tm *tptr)
|
|
{
|
|
register i;
|
|
long tv;
|
|
extern int dmsize[];
|
|
|
|
tv = 0;
|
|
for (i = 1970; i < tptr->tm_year+1900; i++)
|
|
tv += dysize(i);
|
|
if (dysize(tptr->tm_year) == 366 && tptr->tm_mon >= 2)
|
|
++tv;
|
|
for (i = 0; i < tptr->tm_mon; ++i)
|
|
tv += dmsize[i];
|
|
tv += tptr->tm_mday - 1;
|
|
tv = 24 * tv + tptr->tm_hour;
|
|
tv = 60 * tv + tptr->tm_min;
|
|
tv = 60 * tv + tptr->tm_sec;
|
|
return tv;
|
|
}
|
|
|
|
yywrap()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
endit(char *err)
|
|
{
|
|
fprintf(stderr, "%s: Unable to convert %s to a valid date", prog,
|
|
argpbuf);
|
|
if(err) fprintf(stderr, ": %s", err);
|
|
fputc('\n', stderr);
|
|
exit(5);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
yyerror(const char *s)
|
|
{
|
|
endit(NULL);
|
|
}
|
|
|
|
/*
|
|
* add time structures logically
|
|
*/
|
|
void
|
|
atime(struct tm *a, struct tm *b)
|
|
{
|
|
if ((a->tm_sec += b->tm_sec) >= 60) {
|
|
b->tm_min += a->tm_sec / 60;
|
|
a->tm_sec %= 60;
|
|
}
|
|
if ((a->tm_min += b->tm_min) >= 60) {
|
|
b->tm_hour += a->tm_min / 60;
|
|
a->tm_min %= 60;
|
|
}
|
|
if ((a->tm_hour += b->tm_hour) >= 24) {
|
|
b->tm_mday += a->tm_hour / 24;
|
|
a->tm_hour %= 24;
|
|
}
|
|
a->tm_year += b->tm_year;
|
|
if ((a->tm_mon += b->tm_mon) >= 12) {
|
|
a->tm_year += a->tm_mon / 12;
|
|
a->tm_mon %= 12;
|
|
}
|
|
a->tm_mday += b->tm_mday;
|
|
while (a->tm_mday > mday[a->tm_mon]) {
|
|
a->tm_mday -= mday[a->tm_mon++];
|
|
if (a->tm_mon > 11) {
|
|
a->tm_mon = 0;
|
|
mday[1] = 28 + leap(++a->tm_year);
|
|
}
|
|
}
|
|
}
|
|
|
|
leap(year)
|
|
{
|
|
return year % 4 == 0;
|
|
}
|
|
|
|
%}
|
|
%{
|
|
|
|
|
|
extern int gmtflag;
|
|
extern int mday[];
|
|
extern struct tm *tp, at, rt;
|
|
extern char now_flag;
|
|
extern int utc_flag;
|
|
%}
|
|
%token TIME
|
|
%token NOW
|
|
%token NOON
|
|
%token MIDNIGHT
|
|
%token MINUTE
|
|
%token HOUR
|
|
%token DAY
|
|
%token WEEK
|
|
%token MONTH
|
|
%token YEAR
|
|
%token UNIT
|
|
%token SUFF
|
|
%token AM
|
|
%token PM
|
|
%token ZULU
|
|
%token NEXT
|
|
%token NUMB
|
|
%token COLON
|
|
%token COMMA
|
|
%token PLUS
|
|
%token TZ_NAME
|
|
%token UTC
|
|
%token UNKNOWN
|
|
%right NUMB
|
|
%%
|
|
|
|
args
|
|
: time date incr {
|
|
if (at.tm_min >= 60 || at.tm_hour >= 24)
|
|
endit("bad minute/hour");
|
|
if (at.tm_mon >= 12 || at.tm_mday > mday[at.tm_mon])
|
|
endit("bad month/day");
|
|
/* Make sure the validity of the year */
|
|
if (!(((at.tm_year >= 0) && (at.tm_year < 38)) ||
|
|
((at.tm_year > 69) && (at.tm_year < 100)) ||
|
|
((at.tm_year > 1969) && (at.tm_year < 2038))))
|
|
{
|
|
endit("bad year");
|
|
}
|
|
if (at.tm_year < 38)
|
|
at.tm_year += 100;
|
|
if (at.tm_year >= 138)
|
|
at.tm_year -= 1900;
|
|
if (at.tm_year < 70 || at.tm_year >= 138)
|
|
{
|
|
endit("bad year");
|
|
}
|
|
return 0;
|
|
}
|
|
| time date incr UNKNOWN {
|
|
yyerror(NULL);
|
|
}
|
|
;
|
|
|
|
time
|
|
: hour opt_suff {
|
|
checksuff: /* NOTE: for action jumping here: the last two */
|
|
/* parameters are used as $1 and $2 */
|
|
at.tm_hour = $1;
|
|
switch ($2) {
|
|
case PM:
|
|
if (at.tm_hour < 1 || at.tm_hour > 12)
|
|
endit("bad hour");
|
|
at.tm_hour %= 12;
|
|
at.tm_hour += 12;
|
|
break;
|
|
case AM:
|
|
if (at.tm_hour < 1 || at.tm_hour > 12)
|
|
endit("bad hour");
|
|
at.tm_hour %= 12;
|
|
break;
|
|
case ZULU:
|
|
if (at.tm_hour == 24 && at.tm_min != 0)
|
|
endit("bad zulu time");
|
|
at.tm_hour %= 24;
|
|
gmtflag = 1;
|
|
}
|
|
}
|
|
| hour opt_tz {
|
|
checktz:
|
|
at.tm_hour = $1;
|
|
switch ($2) {
|
|
case UTC:
|
|
gmtflag = 1;
|
|
utc_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
| hour COLON number opt_suff {
|
|
at.tm_min = $3;
|
|
$3 = $1;
|
|
goto checksuff;
|
|
}
|
|
| hour COLON number opt_tz {
|
|
at.tm_min = $3;
|
|
$3 = $1;
|
|
goto checktz;
|
|
}
|
|
| hour minute opt_suff {
|
|
at.tm_min = $2;
|
|
$2 = $1;
|
|
goto checksuff;
|
|
}
|
|
| hour minute opt_tz {
|
|
at.tm_min = $2;
|
|
$2 = $1;
|
|
goto checktz;
|
|
}
|
|
| hour SUFF TZ_NAME {
|
|
switch ($3) {
|
|
case UTC:
|
|
gmtflag = 1;
|
|
utc_flag = 1;
|
|
break;
|
|
}
|
|
$3 = $2;
|
|
$2 = $1;
|
|
goto checksuff;
|
|
}
|
|
| hour COLON number SUFF TZ_NAME {
|
|
at.tm_min = $3;
|
|
switch ($5) {
|
|
case UTC:
|
|
gmtflag = 1;
|
|
utc_flag = 1;
|
|
break;
|
|
}
|
|
$5 = $4;
|
|
$4 = $1;
|
|
goto checksuff;
|
|
}
|
|
| TIME {
|
|
switch ($1) {
|
|
case NOON:
|
|
at.tm_hour = 12;
|
|
break;
|
|
case MIDNIGHT:
|
|
at.tm_hour = 0;
|
|
break;
|
|
case NOW:
|
|
at.tm_hour = tp->tm_hour;
|
|
at.tm_min = tp->tm_min;
|
|
now_flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
;
|
|
|
|
date
|
|
: /*empty*/ {
|
|
at.tm_mday = tp->tm_mday;
|
|
at.tm_mon = tp->tm_mon;
|
|
at.tm_year = tp->tm_year%100;
|
|
if ((at.tm_hour < tp->tm_hour)
|
|
|| ((at.tm_hour==tp->tm_hour)&&(at.tm_min<tp->tm_min)))
|
|
rt.tm_mday++;
|
|
}
|
|
| MONTH number {
|
|
at.tm_mon = $1;
|
|
at.tm_mday = $2;
|
|
at.tm_year = tp->tm_year%100;
|
|
if (at.tm_mon < tp->tm_mon){
|
|
at.tm_year++;
|
|
at.tm_year = at.tm_year%100;
|
|
mday[1] = 28 + leap(at.tm_year);
|
|
}
|
|
}
|
|
| MONTH number COMMA number {
|
|
at.tm_mon = $1;
|
|
at.tm_mday = $2;
|
|
at.tm_year = $4;
|
|
mday[1] = 28 + leap(at.tm_year);
|
|
}
|
|
| DAY {
|
|
at.tm_mon = tp->tm_mon;
|
|
at.tm_mday = tp->tm_mday;
|
|
at.tm_year = tp->tm_year%100;
|
|
if ($1 < 7) {
|
|
rt.tm_mday = $1 - tp->tm_wday;
|
|
if (rt.tm_mday < 0)
|
|
rt.tm_mday += 7;
|
|
} else if ($1 == 8)
|
|
rt.tm_mday += 1;
|
|
}
|
|
;
|
|
|
|
incr
|
|
: /*empty*/ {
|
|
if (now_flag) now_flag ++; /* right now */
|
|
}
|
|
| NEXT UNIT { addincr:
|
|
switch ($2) {
|
|
case MINUTE:
|
|
rt.tm_min += $1;
|
|
break;
|
|
case HOUR:
|
|
rt.tm_hour += $1;
|
|
break;
|
|
case DAY:
|
|
rt.tm_mday += $1;
|
|
break;
|
|
case WEEK:
|
|
rt.tm_mday += $1 * 7;
|
|
break;
|
|
case MONTH:
|
|
rt.tm_mon += $1;
|
|
break;
|
|
case YEAR:
|
|
rt.tm_year += $1;
|
|
mday[1] = 28 + leap(at.tm_year + rt.tm_year);
|
|
break;
|
|
}
|
|
}
|
|
| PLUS opt_number UNIT { goto addincr; }
|
|
;
|
|
|
|
hour
|
|
: NUMB { $$ = $1; }
|
|
| NUMB NUMB { $$ = 10 * $1 + $2; }
|
|
;
|
|
minute
|
|
: NUMB NUMB { $$ = 10 * $1 + $2; }
|
|
;
|
|
number
|
|
: NUMB { $$ = $1; }
|
|
| number NUMB { $$ = 10 * $1 + $2; }
|
|
;
|
|
opt_number
|
|
: /* empty */ { $$ = 1; }
|
|
| number { $$ = $1; }
|
|
;
|
|
opt_suff
|
|
: /* empty */ { $$ = 0; }
|
|
| SUFF { $$ = $1; }
|
|
;
|
|
opt_tz
|
|
: /* empty */ { $$ = 0; }
|
|
| TZ_NAME { $$ = $1; }
|
|
;
|
|
%%
|