--- at-3.1.8.orig/at.c +++ at-3.1.8/at.c @@ -111,7 +111,7 @@ static char rcsid[] = "$Id$"; char *no_export[] = { - "TERM", "DISPLAY", "_", "SHELLOPTS" + "TERM", "DISPLAY", "_", "SHELLOPTS", "BASH_VERSINFO", "EUID", "GROUPS", "PPID", "UID" }; static int send_mail = 0; @@ -235,6 +235,7 @@ /* Install the signal handler for SIGINT; terminate after removing the * spool file if necessary */ + memset(&act, 0, sizeof act); act.sa_handler = sigc; sigemptyset(&(act.sa_mask)); act.sa_flags = 0; @@ -274,8 +275,8 @@ if ((jobno = nextjob()) == EOF) perr("Cannot generate job number"); - sprintf(ppos, "%c%5lx%8lx", queue, - jobno, (unsigned long) (runtimer / 60)); + (void)snprintf(ppos, sizeof(atfile) - (ppos - atfile), + "%c%5lx%8lx", queue, jobno, (unsigned long) (runtimer / 60)); for (ap = ppos; *ap != '\0'; ap++) if (*ap == ' ') @@ -291,7 +292,7 @@ * bit. Yes, this is a kluge. */ cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR); - if ((fd = creat(atfile, O_WRONLY)) == -1) + if ((fd = open(atfile, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR)) == -1) perr("Cannot create atjob file %.500s", atfile); if ((fd2 = dup(fd)) < 0) @@ -461,14 +462,6 @@ close(fd2); - /* POSIX.2 allows the shell specified by the user's SHELL environment - variable, the login shell from the user's password database entry, - or /bin/sh to be the command interpreter that processes the at-job. - It also alows a warning diagnostic to be printed. Because of the - possible variance, we always output the diagnostic. */ - - fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); - runtime = localtime(&runtimer); /* We only use the sick POSIX time format if POSIXLY_CORRECT @@ -546,6 +539,7 @@ long jobno; time_t runtimer; char timestr[TIMESIZE]; + struct passwd *pwd; PRIV_START @@ -581,7 +575,10 @@ } else { strftime(timestr, TIMESIZE, TIMEFORMAT_ISO, runtime); } - printf("%ld\t%s %c\n", jobno, timestr, queue); + if ((pwd = getpwuid(buf.st_uid))) + printf("%ld\t%s %c %s\n", jobno, timestr, queue, pwd->pw_name); + else + printf("%ld\t%s %c\n", jobno, timestr, queue); } PRIV_END } @@ -695,7 +692,7 @@ char *pgm; int program = AT; /* our default program */ - char *options = "q:f:mvldVc"; /* default options for at */ + char *options = "q:f:MmvldhVc"; /* default options for at */ int disp_version = 0; time_t timer; struct passwd *pwe; @@ -726,16 +723,20 @@ */ if (strcmp(pgm, "atq") == 0) { program = ATQ; - options = "q:V"; + options = "hq:V"; } else if (strcmp(pgm, "atrm") == 0) { program = ATRM; - options = "V"; + options = "hV"; } /* process whatever options we can process */ opterr = 1; while ((c = getopt(argc, argv, options)) != EOF) switch (c) { + case 'h': + usage(); + exit (0); + case 'v': /* verify time settings */ atverify = 1; break; @@ -744,6 +745,10 @@ send_mail = 1; break; + case 'M': /* don't send mail, even when job failed */ + send_mail = -1; + break; + case 'f': atinput = optarg; break; @@ -753,7 +758,7 @@ usage(); atqueue = queue = *optarg; - if (!(islower(queue) || isupper(queue))) + if (!(islower(queue) || isupper(queue)) & (queue != '=')) usage(); queue_set = 1; @@ -842,6 +847,15 @@ struct tm *tm = localtime(&timer); fprintf(stderr, "%s\n", asctime(tm)); } + + /* POSIX.2 allows the shell specified by the user's SHELL environment + variable, the login shell from the user's password database entry, + or /bin/sh to be the command interpreter that processes the at-job. + It also alows a warning diagnostic to be printed. Because of the + possible variance, we always output the diagnostic. */ + + fprintf(stderr, "warning: commands will be executed using /bin/sh\n"); + writefile(timer, queue); break; --- at-3.1.8.orig/atd.c +++ at-3.1.8/atd.c @@ -22,6 +22,18 @@ #include "config.h" #endif +/* + * /usr/bin/mail aka /usr/bin/mailx require the subject to be + * specified on the command line instead of reading it from stdin like + * /usr/sbin/sendmail does. For now simply disable MAILC and MAILX, + * + * TODO: Remove tests for MAILC and MAILX from configure.in in the + * next upstream version. + */ +#undef MAILC +#undef MAILX + + /* System Headers */ #include @@ -101,6 +113,8 @@ static char rcsid[] = "$Id$"; static double load_avg = LOADAVG_MX; static time_t now; +static time_t last_chg; +static int nothing_to_do; unsigned int batch_interval; static int run_as_daemon = 0; @@ -121,6 +135,29 @@ return; } +/* SIGCHLD handler - discards completion status of children */ +RETSIGTYPE +release_zombie(int dummy) +{ + int status; + pid_t pid; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { +#ifdef DEBUG_ZOMBIE + if (WIFEXITED(status)) + syslog(LOG_INFO, "pid %ld exited with status %d.", pid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + syslog(LOG_NOTICE, "pid %ld killed with signal %d.", pid, WTERMSIG(status)); + else if (WIFSTOPPED(status)) + syslog(LOG_NOTICE, "pid %ld stopped with signal %d.", pid, WSTOPSIG(status)); + else + syslog(LOG_WARNING, "pid %ld unknown reason for SIGCHLD", pid); +#endif + } + return; +} + + /* Local functions */ static int @@ -255,6 +292,13 @@ fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); + /* + * If the spool directory is mounted via NFS `atd' isn't able to + * read from the job file and will bump out here. The file is + * opened as "root" but it is read as "daemon" which fails over + * NFS and works with local file systems. It's not clear where + * the bug is located. -Joey + */ if (fscanf(stream, "#!/bin/sh\n# atrun uid=%d gid=%d\n# mail %8s %d", &nuid, &ngid, mailbuf, &send_mail) != 4) pabort("File %.500s is in wrong format - aborting", @@ -298,6 +342,8 @@ write_string(fd_out, "Subject: Output from your job "); write_string(fd_out, jobbuf); + write_string(fd_out, "\nTo: "); + write_string(fd_out, mailname); write_string(fd_out, "\n\n"); fstat(fd_out, &buf); size = buf.st_size; @@ -359,6 +405,11 @@ */ close(fd_in); close(fd_out); + + /* We inherited the master's SIGCHLD handler, which does a + non-blocking waitpid. So this blocking one will eventually + return with an ECHILD error. + */ waitpid(pid, (int *) NULL, 0); /* Send mail. Unlink the output file after opening it, so it @@ -376,7 +427,7 @@ unlink(newname); free(newname); - if ((buf.st_size != size) || send_mail) { + if (((send_mail != -1) && (buf.st_size != size)) || (send_mail == 1)) { PRIV_START @@ -436,34 +487,51 @@ * atrun. */ - if ((spool = opendir(".")) == NULL) - perr("Cannot read " ATJOB_DIR); - next_job = now + CHECK_INTERVAL; if (next_batch == 0) next_batch = now; + /* To avoid spinning up the disk unnecessarily, stat the directory and + * return immediately if it hasn't changed since the last time we woke + * up. + */ + + if (stat(".", &buf) == -1) + perr("Cannot stat " ATJOB_DIR); + + if (nothing_to_do && buf.st_mtime <= last_chg) + return next_job; + last_chg = buf.st_mtime; + + if ((spool = opendir(".")) == NULL) + perr("Cannot read " ATJOB_DIR); + run_batch = 0; + nothing_to_do = 1; batch_uid = (uid_t) - 1; batch_gid = (gid_t) - 1; while ((dirent = readdir(spool)) != NULL) { - if (stat(dirent->d_name, &buf) != 0) { - /* Chances are a '=' file has been deleted from under us. - * Ignore. - */ - } + /* Avoid the stat if this doesn't look like a job file */ + if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) + continue; - /* We don't want directories or files which at(1) hasn't yet - * marked executable. + /* Chances are a '=' file has been deleted from under us. + * Ignore. */ - if ((!S_ISREG(buf.st_mode)) || !(buf.st_mode & S_IXUSR)) + if (stat(dirent->d_name, &buf) != 0) continue; - if (sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm) != 3) + if (!S_ISREG(buf.st_mode)) + continue; + + /* We don't want files which at(1) hasn't yet marked executable. */ + if (!(buf.st_mode & S_IXUSR)) { + nothing_to_do = 0; /* it will probably become executable soon */ continue; + } run_time = (time_t) ctm *60; @@ -493,9 +561,18 @@ lock_name[0] = '='; unlink(lock_name); next_job = now; + nothing_to_do = 0; } continue; } + + /* If we got here, then there are jobs of some kind waiting. + * We could try to be smarter and leave nothing_to_do set if + * we end up processing all the jobs, but that's risky (run_file + * might fail and expect the job to be rescheduled), and it doesn't + * gain us much. */ + nothing_to_do = 0; + /* There's a job for later. Note its execution time if it's * the earlierst so far. */ @@ -540,6 +617,7 @@ } } if (run_batch && (next_batch < next_job)) { + nothing_to_do = 0; next_job = next_batch; } return next_job; @@ -631,6 +709,11 @@ if (optind < argc) pabort("non-option arguments - not allowed"); + sigaction(SIGCHLD, NULL, &act); + act.sa_handler = release_zombie; + act.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &act, NULL); + if (!run_as_daemon) { now = time(NULL); run_loop(); @@ -646,10 +729,6 @@ sigaction(SIGHUP, NULL, &act); act.sa_handler = sdummy; sigaction(SIGHUP, &act, NULL); - - sigaction(SIGCHLD, NULL, &act); - act.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &act, NULL); sigaction(SIGTERM, NULL, &act); act.sa_handler = set_term; --- at-3.1.8.orig/panic.c +++ at-3.1.8/panic.c @@ -41,6 +41,7 @@ /* Local headers */ #include "panic.h" +#include "privs.h" #include "at.h" /* File scope variables */ @@ -72,12 +73,15 @@ va_list args; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); perror(buf); - if (fcreated) + if (fcreated) { + PRIV_START unlink(atfile); + PRIV_END + } exit(EXIT_FAILURE); } @@ -88,7 +92,7 @@ /* Print usage and exit. */ fprintf(stderr, "Usage: at [-V] [-q x] [-f file] [-m] time\n" - " atq [-V] [-q x] [-v]\n" + " atq [-V] [-q x]\n" " atrm [-V] [-q x] job ...\n" " batch [-V] [-f file] [-m]\n"); exit(EXIT_FAILURE); --- at-3.1.8.orig/perm.c +++ at-3.1.8/perm.c @@ -43,7 +43,13 @@ /* Macros */ -#define MAXUSERID 10 +#if defined(DEBUG_PERM_C) +#define ETCDIR "../test/etc" +#undef PRIV_START +#define PRIV_START while(0) +#undef PRIV_END +#define PRIV_END while(0) +#endif /* Structures and unions */ @@ -54,66 +60,87 @@ /* Function declarations */ -static int check_for_user(FILE * fp, const char *name); +static int user_in_file(const char *path, const char *name); /* Local functions */ +/* + */ static int -check_for_user(FILE * fp, const char *name) +user_in_file(const char *path, const char *name) { - char *buffer; - size_t len; - int found = 0; - - len = strlen(name); - buffer = mymalloc(len + 2); - - while (fgets(buffer, len + 2, fp) != NULL) { - if ((strncmp(name, buffer, len) == 0) && - (buffer[len] == '\n')) { - found = 1; - break; - } - } - fclose(fp); - free(buffer); - return found; -} -/* Global functions */ -int -check_permission() -{ - FILE *fp; - uid_t uid = geteuid(); - struct passwd *pentry; + FILE *fp; + char buffer[256]; + int found = 0; + int c = '\n'; + + PRIV_START; + fp = fopen( path, "r"); + PRIV_END; + + if ( fp == NULL ) + return -1; + + + while ( !found && fgets(buffer, sizeof(buffer), fp) != NULL) { + size_t llen = strlen(buffer); - if (uid == 0) - return 1; + c = buffer[llen-1]; - if ((pentry = getpwuid(uid)) == NULL) { - perror("Cannot access user database"); - exit(EXIT_FAILURE); - } - PRIV_START + if (c == '\n') + buffer[llen-1] = '\0'; + while (c != '\n' && c != EOF) + c = fgetc(fp); + + found = (strcmp(buffer, name)==0); + } - fp = fopen(ETCDIR "/at.allow", "r"); + fclose(fp); - PRIV_END + if (c == EOF) { + fprintf(stderr, "%s: incomplete last line.\n", path); + } + + return found; +} - if (fp != NULL) { - return check_for_user(fp, pentry->pw_name); - } else { - PRIV_START +/* Global functions */ +int +check_permission() +{ + uid_t uid = geteuid(); + struct passwd *pentry; + int allow = 0, deny = 1; + + if (uid == 0) + return 1; + + if ((pentry = getpwuid(uid)) == NULL) { + perror("Cannot access user database"); + exit(EXIT_FAILURE); + } + + allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); + if (allow==0 || allow==1) + return allow; + + /* There was an error while looking for pw_name in at.allow. + * Check at.deny only when at.allow doesn't exist. + */ + + deny = user_in_file(ETCDIR "/at.deny", pentry->pw_name); + return deny == 0; +} - fp = fopen(ETCDIR "/at.deny", "r"); - PRIV_END +#if defined(DEBUG_PERM_C) - if (fp != NULL) { - return !check_for_user(fp, pentry->pw_name); - } - perror("at.deny"); - } - return 0; +int +main(int argc, char *argv[]) +{ + printf("check_permission() ==> %d\n", check_permission()); + return 0; } + +#endif --- at-3.1.8.orig/daemon.c +++ at-3.1.8/daemon.c @@ -72,7 +72,7 @@ va_list args; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (daemon_debug) { @@ -90,7 +90,7 @@ va_list args; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (daemon_debug) { @@ -127,6 +127,7 @@ } } old_umask = umask(S_IWGRP | S_IWOTH); + (void) setsid(); PRIV_START --- at-3.1.8.orig/y.tab.c +++ at-3.1.8/y.tab.c @@ -1,45 +1,45 @@ -/* A Bison parser, made from parsetime.y with Bison version GNU Bison version 1.22 - */ +/* A Bison parser, made from parsetime.y + by GNU Bison version 1.28 */ #define YYBISON 1 /* Identify Bison output. */ -#define INT 258 -#define NOW 259 -#define AM 260 -#define PM 261 -#define NOON 262 -#define MIDNIGHT 263 -#define TEATIME 264 -#define SUN 265 -#define MON 266 -#define TUE 267 -#define WED 268 -#define THU 269 -#define FRI 270 -#define SAT 271 -#define TODAY 272 -#define TOMORROW 273 -#define NEXT 274 -#define MINUTE 275 -#define HOUR 276 -#define DAY 277 -#define WEEK 278 -#define MONTH 279 -#define YEAR 280 -#define JAN 281 -#define FEB 282 -#define MAR 283 -#define APR 284 -#define MAY 285 -#define JUN 286 -#define JUL 287 -#define AUG 288 -#define SEP 289 -#define OCT 290 -#define NOV 291 -#define DEC 292 -#define WORD 293 +#define INT 257 +#define NOW 258 +#define AM 259 +#define PM 260 +#define NOON 261 +#define MIDNIGHT 262 +#define TEATIME 263 +#define SUN 264 +#define MON 265 +#define TUE 266 +#define WED 267 +#define THU 268 +#define FRI 269 +#define SAT 270 +#define TODAY 271 +#define TOMORROW 272 +#define NEXT 273 +#define MINUTE 274 +#define HOUR 275 +#define DAY 276 +#define WEEK 277 +#define MONTH 278 +#define YEAR 279 +#define JAN 280 +#define FEB 281 +#define MAR 282 +#define APR 283 +#define MAY 284 +#define JUN 285 +#define JUL 286 +#define AUG 287 +#define SEP 288 +#define OCT 289 +#define NOV 290 +#define DEC 291 +#define WORD 292 #line 1 "parsetime.y" @@ -55,30 +55,16 @@ static int isgmt; static int time_only; +extern int yyerror(char *s); +extern int yylex(); + int add_date(int number, int period); -#line 17 "parsetime.y" +#line 20 "parsetime.y" typedef union { char * charval; int intval; } YYSTYPE; - -#ifndef YYLTYPE -typedef - struct yyltype - { - int timestamp; - int first_line; - int first_column; - int last_line; - int last_column; - char *text; - } - yyltype; - -#define YYLTYPE yyltype -#endif - #include #ifndef __cplusplus @@ -89,11 +75,11 @@ -#define YYFINAL 100 +#define YYFINAL 104 #define YYFLAG -32768 #define YYNTBASE 47 -#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 67) +#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 69) static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -121,176 +107,203 @@ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38 + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38 }; #if YYDEBUG != 0 static const short yyprhs[] = { 0, - 0, 2, 5, 8, 12, 15, 19, 21, 23, 26, - 29, 31, 33, 36, 40, 45, 48, 52, 57, 63, - 65, 67, 69, 72, 77, 79, 81, 83, 89, 95, - 99, 102, 106, 112, 116, 119, 122, 126, 128, 130, - 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, - 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, - 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, - 192, 194, 196, 198, 200, 202, 204 + 0, 2, 4, 7, 10, 14, 16, 18, 21, 23, + 25, 27, 28, 30, 33, 37, 42, 45, 49, 54, + 60, 62, 64, 66, 69, 73, 78, 80, 82, 84, + 90, 96, 100, 103, 107, 113, 115, 117, 121, 124, + 127, 131, 133, 135, 137, 139, 141, 143, 145, 147, + 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, + 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, + 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, + 209 }; -static const short yyrhs[] = { 50, - 0, 50, 51, 0, 50, 52, 0, 50, 51, 52, - 0, 50, 53, 0, 50, 51, 53, 0, 48, 0, - 49, 0, 49, 52, 0, 49, 53, 0, 4, 0, - 55, 0, 55, 56, 0, 57, 66, 58, 0, 57, - 66, 58, 56, 0, 57, 59, 0, 57, 59, 56, - 0, 57, 66, 58, 59, 0, 57, 66, 58, 59, - 56, 0, 7, 0, 8, 0, 9, 0, 60, 62, - 0, 60, 62, 39, 63, 0, 64, 0, 17, 0, - 18, 0, 63, 40, 61, 40, 62, 0, 62, 41, - 61, 41, 63, 0, 62, 41, 61, 0, 62, 60, - 0, 62, 60, 63, 0, 61, 42, 62, 42, 63, - 0, 43, 65, 54, 0, 19, 54, 0, 19, 64, - 0, 40, 65, 54, 0, 20, 0, 21, 0, 22, - 0, 23, 0, 24, 0, 25, 0, 3, 0, 38, - 0, 55, 0, 3, 0, 5, 0, 6, 0, 26, - 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, - 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, - 0, 37, 0, 3, 0, 3, 0, 3, 0, 10, - 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, - 0, 16, 0, 3, 0, 44, 0, 45, 0, 41, - 0, 46, 0, 39, 0 +static const short yyrhs[] = { 52, + 0, 51, 0, 51, 52, 0, 50, 53, 0, 50, + 52, 53, 0, 48, 0, 49, 0, 49, 53, 0, + 4, 0, 18, 0, 51, 0, 0, 57, 0, 57, + 58, 0, 59, 68, 60, 0, 59, 68, 60, 58, + 0, 59, 61, 0, 59, 61, 58, 0, 59, 68, + 60, 61, 0, 59, 68, 60, 61, 58, 0, 7, + 0, 8, 0, 9, 0, 62, 64, 0, 62, 64, + 65, 0, 62, 64, 39, 65, 0, 66, 0, 17, + 0, 18, 0, 65, 40, 63, 40, 64, 0, 64, + 41, 63, 41, 65, 0, 64, 41, 63, 0, 64, + 62, 0, 64, 62, 65, 0, 63, 42, 64, 42, + 65, 0, 54, 0, 55, 0, 43, 67, 56, 0, + 19, 56, 0, 19, 66, 0, 40, 67, 56, 0, + 20, 0, 21, 0, 22, 0, 23, 0, 24, 0, + 25, 0, 3, 0, 38, 0, 57, 0, 3, 0, + 5, 0, 6, 0, 26, 0, 27, 0, 28, 0, + 29, 0, 30, 0, 31, 0, 32, 0, 33, 0, + 34, 0, 35, 0, 36, 0, 37, 0, 3, 0, + 3, 0, 3, 0, 10, 0, 11, 0, 12, 0, + 13, 0, 14, 0, 15, 0, 16, 0, 3, 0, + 44, 0, 45, 0, 41, 0, 46, 0, 39, 0 }; #endif #if YYDEBUG != 0 static const short yyrline[] = { 0, - 39, 43, 44, 45, 46, 47, 48, 51, 52, 53, - 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 72, 78, 85, 86, 87, 91, 92, 96, 97, 98, - 99, 100, 101, 104, 108, 112, 118, 124, 125, 126, - 127, 128, 129, 132, 157, 170, 173, 183, 184, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 211, 225, 238, 261, 262, 263, 264, 265, 266, - 267, 270, 280, 281, 282, 283, 284 + 42, 43, 47, 48, 49, 50, 53, 54, 57, 58, + 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 80, 86, 93, 94, 95, 96, 100, 101, 105, + 106, 107, 108, 109, 110, 113, 114, 116, 120, 124, + 130, 136, 137, 138, 139, 140, 141, 144, 215, 228, + 231, 241, 251, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 278, 292, 305, 328, 329, + 330, 331, 332, 333, 334, 337, 347, 348, 349, 350, + 351 }; +#endif + -static const char * const yytname[] = { "$","error","$illegal.","INT","NOW", +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","INT","NOW", "AM","PM","NOON","MIDNIGHT","TEATIME","SUN","MON","TUE","WED","THU","FRI","SAT", "TODAY","TOMORROW","NEXT","MINUTE","HOUR","DAY","WEEK","MONTH","YEAR","JAN", "FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC","WORD","','", -"'-'","'.'","'/'","'+'","':'","'\\''","'h'","timespec","nowspec","now","time", -"date","increment","decrement","inc_period","hr24clock_hr_min","timezone_name", -"hr24clock_hour","minute","am_pm","month_name","month_number","day_number","year_number", -"day_of_week","inc_number","time_sep","" +"'-'","'.'","'/'","'+'","':'","'\\''","'h'","timespec","nowspec","now","time_or_not", +"time","date","inc_or_dec","increment","decrement","inc_period","hr24clock_hr_min", +"timezone_name","hr24clock_hour","minute","am_pm","month_name","month_number", +"day_number","year_number","day_of_week","inc_number","time_sep", NULL }; #endif static const short yyr1[] = { 0, - 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, - 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 47, 47, 47, 47, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 52, 52, 52, 53, 54, 54, 54, - 54, 54, 54, 55, 56, 57, 58, 59, 59, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, - 64, 65, 66, 66, 66, 66, 66 + 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 53, 53, 54, 54, 54, + 55, 56, 56, 56, 56, 56, 56, 57, 58, 59, + 60, 61, 61, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 63, 64, 65, 66, 66, + 66, 66, 66, 66, 66, 67, 68, 68, 68, 68, + 68 }; static const short yyr2[] = { 0, - 1, 2, 2, 3, 2, 3, 1, 1, 2, 2, - 1, 1, 2, 3, 4, 2, 3, 4, 5, 1, - 1, 1, 2, 4, 1, 1, 1, 5, 5, 3, - 2, 3, 5, 3, 2, 2, 3, 1, 1, 1, + 1, 1, 2, 2, 3, 1, 1, 2, 1, 1, + 1, 0, 1, 2, 3, 4, 2, 3, 4, 5, + 1, 1, 1, 2, 3, 4, 1, 1, 1, 5, + 5, 3, 2, 3, 5, 1, 1, 3, 2, 2, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1 + 1 }; -static const short yydefact[] = { 0, - 44, 11, 20, 21, 22, 7, 8, 1, 12, 0, - 0, 0, 0, 9, 10, 63, 65, 66, 67, 68, - 69, 70, 71, 26, 27, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 2, 3, 5, - 0, 0, 0, 0, 25, 45, 13, 48, 49, 77, - 75, 73, 74, 76, 16, 0, 38, 39, 40, 41, - 42, 43, 35, 36, 72, 0, 0, 4, 6, 63, - 23, 0, 0, 31, 0, 17, 47, 14, 37, 34, - 0, 0, 62, 30, 64, 32, 0, 15, 18, 24, - 0, 0, 0, 19, 33, 29, 28, 0, 0, 0 +static const short yydefact[] = { 12, + 48, 9, 21, 22, 23, 69, 70, 71, 72, 73, + 74, 75, 28, 10, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 6, 7, 0, 11, + 1, 13, 0, 0, 0, 0, 0, 27, 0, 0, + 0, 8, 36, 37, 67, 29, 0, 4, 3, 49, + 14, 52, 53, 81, 79, 77, 78, 80, 17, 0, + 67, 24, 0, 0, 33, 0, 42, 43, 44, 45, + 46, 47, 39, 40, 76, 0, 0, 5, 18, 51, + 15, 68, 0, 25, 0, 66, 32, 34, 0, 41, + 38, 16, 19, 26, 0, 0, 0, 20, 35, 31, + 30, 0, 0, 0 }; -static const short yydefgoto[] = { 98, - 6, 7, 8, 38, 14, 15, 63, 9, 47, 10, - 78, 55, 41, 42, 43, 44, 45, 66, 56 +static const short yydefgoto[] = { 102, + 27, 28, 29, 30, 31, 42, 43, 44, 73, 32, + 51, 33, 81, 59, 34, 35, 36, 37, 38, 76, + 60 }; -static const short yypact[] = { 8, --32768,-32768,-32768,-32768,-32768,-32768, -14, 43, -4, 4, - 80, 5, 5,-32768,-32768, -12,-32768,-32768,-32768,-32768, +static const short yypact[] = { 114, + -21,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768,-32768,-32768, -14,-32768,-32768, - 10, -6, 81, -8,-32768,-32768,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768, 9, 48,-32768,-32768,-32768,-32768, --32768,-32768,-32768,-32768,-32768, -2, -2,-32768,-32768,-32768, - 25, 10, 63, 64, 63,-32768,-32768, 1,-32768,-32768, - 64, 26,-32768, 41,-32768,-32768, 44,-32768, 9,-32768, - 64, 64, 10,-32768,-32768,-32768,-32768, 85, 87,-32768 +-32768,-32768,-32768,-32768,-32768,-32768,-32768, -13, 41, 79, +-32768, -4, 4, 22, -14, 142, -8,-32768, 174, 33, + 33,-32768,-32768,-32768, -18,-32768, -13,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 9, 58, +-32768, 0, 22, 59, 61, 59,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768, -5, -5,-32768,-32768,-32768, + 8,-32768, 61,-32768, 23,-32768, 25,-32768, 40,-32768, +-32768,-32768, 9,-32768, 61, 61, 22,-32768,-32768,-32768, +-32768, 83, 85,-32768 }; static const short yypgoto[] = {-32768, --32768,-32768,-32768,-32768, -5, 6, -42,-32768, -51,-32768, --32768, 11, 54, -10, -41, 7, 95, 106,-32768 +-32768,-32768,-32768,-32768, -22, -24,-32768,-32768, -65,-32768, + -55,-32768,-32768, 5, 51, -33, -34, 71, 49, 57, +-32768 }; -#define YYLAST 122 +#define YYLAST 199 -static const short yytable[] = { 71, - -46, -46, 39, 76, 11, 48, 49, 65, 48, 49, - 1, 2, 70, 40, 3, 4, 5, 57, 58, 59, - 60, 61, 62, 79, 80, 12, 88, -64, 13, -62, - 82, 75, 68, 46, -46, 72, -46, 94, 46, -46, - -46, -46, 50, 69, 51, 16, 46, 52, 53, 54, - 77, 97, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 11, 84, 81, 87, 83, 85, 91, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 86, 92, 12, 93, 99, 13, 100, 90, 89, 17, - 18, 19, 20, 21, 22, 23, 74, 95, 96, 57, - 58, 59, 60, 61, 62, 64, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 67, 0, - 0, 73 +static const short yytable[] = { 62, + -50, -50, 82, 79, 48, 39, 47, 49, 52, 53, + 90, 91, 52, 53, 67, 68, 69, 70, 71, 72, + -66, -68, 78, -66, 61, 92, 40, 63, 85, 41, + 87, 66, 89, 50, -50, 75, -50, 98, 83, -50, + -50, -50, 54, 45, 55, 50, 50, 56, 57, 58, + 6, 7, 8, 9, 10, 11, 12, 13, 46, 39, + 80, 86, 101, 82, 95, 96, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, -2, 97, + 40, 45, 103, 41, 104, 93, 65, 74, 6, 7, + 8, 9, 10, 11, 12, 13, 46, 77, 0, 0, + 0, 0, 0, 0, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 1, 2, 0, 0, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 84, 0, 0, 88, 0, 0, 0, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 0, 0, 94, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 99, 100, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, + 0, 0, 64, 6, 7, 8, 9, 10, 11, 12, + 0, 0, 0, 67, 68, 69, 70, 71, 72 }; -static const short yycheck[] = { 41, - 5, 6, 8, 55, 19, 5, 6, 3, 5, 6, - 3, 4, 3, 8, 7, 8, 9, 20, 21, 22, - 23, 24, 25, 66, 67, 40, 78, 40, 43, 42, - 72, 40, 38, 38, 39, 42, 41, 89, 38, 44, - 45, 46, 39, 38, 41, 3, 38, 44, 45, 46, - 3, 93, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 73, 39, 75, 3, 3, 42, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 74, 41, 40, 40, 0, 43, 0, 81, 78, 10, - 11, 12, 13, 14, 15, 16, 43, 91, 92, 20, - 21, 22, 23, 24, 25, 11, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 13, -1, - -1, 41 +static const short yycheck[] = { 34, + 5, 6, 3, 59, 29, 19, 29, 30, 5, 6, + 76, 77, 5, 6, 20, 21, 22, 23, 24, 25, + 42, 40, 47, 42, 3, 81, 40, 42, 63, 43, + 64, 40, 66, 38, 39, 3, 41, 93, 39, 44, + 45, 46, 39, 3, 41, 38, 38, 44, 45, 46, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 3, 3, 97, 3, 42, 41, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 0, 40, + 40, 3, 0, 43, 0, 81, 36, 39, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 41, -1, -1, + -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 3, 4, -1, -1, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 62, -1, -1, 65, -1, -1, -1, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, -1, -1, 83, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 95, 96, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, -1, + -1, -1, 41, 10, 11, 12, 13, 14, 15, 16, + -1, -1, -1, 20, 21, 22, 23, 24, 25 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/lib/bison.simple" +#line 3 "/usr/share/misc/bison.simple" +/* This file comes from bison-1.28. */ /* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 1, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -300,42 +313,66 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ -#ifndef alloca +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ #ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA #include #else /* not sparc */ -#if defined (MSDOS) && !defined (__TURBOC__) +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ #include +#endif #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) -#include +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ #pragma alloca -#else /* not MSDOS, __TURBOC__, or _AIX */ -#ifdef __hpux -#ifdef __cplusplus -extern "C" { -void *alloca (unsigned int); -}; -#else /* not __cplusplus */ -void *alloca (); -#endif /* not __cplusplus */ +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca #endif /* __hpux */ +#endif #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc. */ -#endif /* not GNU C. */ -#endif /* alloca not defined. */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action @@ -345,8 +382,8 @@ #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 -#define YYACCEPT return(0) -#define YYABORT return(1) +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the @@ -375,10 +412,18 @@ #ifdef YYPURE #ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else #define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) #else #define YYLEX yylex(&yylval) #endif +#endif /* not YYLSP_NEEDED */ #endif /* If nonreentrant, generate the variables here */ @@ -419,24 +464,24 @@ #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -int yyparse (void); -#endif +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void -__yy_bcopy (from, to, count) - char *from; +__yy_memcpy (to, from, count) char *to; - int count; + char *from; + unsigned int count; { register char *f = from; register char *t = to; @@ -451,10 +496,10 @@ /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void -__yy_bcopy (char *from, char *to, int count) +__yy_memcpy (char *to, char *from, unsigned int count) { - register char *f = from; register char *t = to; + register char *f = from; register int i = count; while (i-- > 0) @@ -464,9 +509,39 @@ #endif #endif -#line 184 "/usr/lib/bison.simple" +#line 217 "/usr/share/misc/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + int -yyparse() +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL { register int yystate; register int yyn; @@ -492,6 +567,7 @@ #endif int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; #ifdef YYPURE int yychar; @@ -576,18 +652,32 @@ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; - yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); - __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); - yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); - __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); #ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); - __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); #endif #endif /* no yyoverflow */ @@ -747,102 +837,154 @@ switch (yyn) { -case 1: -#line 40 "parsetime.y" +case 2: +#line 44 "parsetime.y" { time_only = 1; ; break;} -case 20: -#line 68 "parsetime.y" +case 10: +#line 59 "parsetime.y" +{ + add_date(1, DAY); + ; + break;} +case 21: +#line 76 "parsetime.y" { exectm.tm_hour = 12; exectm.tm_min = 0; ; break;} -case 21: -#line 73 "parsetime.y" +case 22: +#line 81 "parsetime.y" { exectm.tm_hour = 0; exectm.tm_min = 0; add_date(1, DAY); ; break;} -case 22: -#line 79 "parsetime.y" +case 23: +#line 87 "parsetime.y" { exectm.tm_hour = 16; exectm.tm_min = 0; ; break;} -case 25: -#line 88 "parsetime.y" +case 27: +#line 97 "parsetime.y" { - add_date ((7 + yyvsp[0].intval - exectm.tm_wday) %7 + 1, DAY); + add_date ((6 + yyvsp[0].intval - exectm.tm_wday) %7 + 1, DAY); ; break;} -case 27: -#line 93 "parsetime.y" +case 29: +#line 102 "parsetime.y" { add_date(1, DAY); ; break;} -case 34: -#line 105 "parsetime.y" +case 38: +#line 117 "parsetime.y" { add_date(yyvsp[-1].intval, yyvsp[0].intval); ; break;} -case 35: -#line 109 "parsetime.y" +case 39: +#line 121 "parsetime.y" { add_date(1, yyvsp[0].intval); ; break;} -case 36: -#line 113 "parsetime.y" +case 40: +#line 125 "parsetime.y" { add_date ((6 + yyvsp[0].intval - exectm.tm_wday) %7 +1, DAY); ; break;} -case 37: -#line 119 "parsetime.y" +case 41: +#line 131 "parsetime.y" { add_date(-yyvsp[-1].intval, yyvsp[0].intval); ; break;} -case 38: -#line 124 "parsetime.y" +case 42: +#line 136 "parsetime.y" { yyval.intval = MINUTE ; ; break;} -case 39: -#line 125 "parsetime.y" +case 43: +#line 137 "parsetime.y" { yyval.intval = HOUR ; ; break;} -case 40: -#line 126 "parsetime.y" +case 44: +#line 138 "parsetime.y" { yyval.intval = DAY ; ; break;} -case 41: -#line 127 "parsetime.y" +case 45: +#line 139 "parsetime.y" { yyval.intval = WEEK ; ; break;} -case 42: -#line 128 "parsetime.y" +case 46: +#line 140 "parsetime.y" { yyval.intval = MONTH ; ; break;} -case 43: -#line 129 "parsetime.y" +case 47: +#line 141 "parsetime.y" { yyval.intval = YEAR ; ; break;} -case 44: -#line 133 "parsetime.y" +case 48: +#line 145 "parsetime.y" { - exectm.tm_min = -1; - exectm.tm_hour = -1; if (strlen(yyvsp[0].charval) == 4) { + exectm.tm_min = -1; + exectm.tm_hour = -1; sscanf(yyvsp[0].charval, "%2d %2d", &exectm.tm_hour, &exectm.tm_min); + } else if (strlen(yyvsp[0].charval) >= 5 && strlen(yyvsp[0].charval) <= 8) { + /* Ok, this is a kluge. I hate design errors... -Joey */ + char shallot[5]; + char *onion; + + onion=yyvsp[0].charval; + memset (shallot, 0, sizeof (shallot)); + if (strlen(yyvsp[0].charval) == 5 || strlen(yyvsp[0].charval) == 7) { + strncpy (shallot,onion,1); + onion++; + } else { + strncpy (shallot,onion,2); + onion+=2; + } + sscanf(shallot, "%d", &exectm.tm_mon); + + if (exectm.tm_mon < 1 || exectm.tm_mon > 12) { + yyerror("Error in month number"); + YYERROR; + } + exectm.tm_mon--; + + memset (shallot, 0, sizeof (shallot)); + strncpy (shallot,onion,2); + sscanf(shallot, "%d", &exectm.tm_mday); + if (exectm.tm_mday < 0 || exectm.tm_mday > 31) + { + yyerror("Error in day of month"); + YYERROR; + } + + onion+=2; + memset (shallot, 0, sizeof (shallot)); + strncpy (shallot,onion,4); + if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) { + yyerror("Error in year"); + YYERROR; + } + if (exectm.tm_year < 70) { + exectm.tm_year += 100; + } + else if (exectm.tm_year > 1900) { + exectm.tm_year -= 1900; + } + + free (yyvsp[0].charval); } else { sscanf(yyvsp[0].charval, "%d", &exectm.tm_hour); @@ -855,13 +997,13 @@ YYERROR; } if (exectm.tm_hour > 24 || exectm.tm_hour < 0) { - yyerror("Problem in minutes specification"); + yyerror("Problem in hours specification"); YYERROR; } ; break;} -case 45: -#line 158 "parsetime.y" +case 49: +#line 216 "parsetime.y" { if (strcasecmp(yyvsp[0].charval,"utc") == 0) { isgmt = 1; @@ -873,8 +1015,8 @@ free(yyvsp[0].charval); ; break;} -case 47: -#line 174 "parsetime.y" +case 51: +#line 232 "parsetime.y" { if (sscanf(yyvsp[0].charval, "%d", &exectm.tm_min) != 1) { yyerror("Error in minute"); @@ -883,8 +1025,20 @@ free(yyvsp[0].charval); ; break;} -case 49: -#line 185 "parsetime.y" +case 52: +#line 242 "parsetime.y" +{ + if (exectm.tm_hour > 12) { + yyerror("Hour too large for AM"); + YYERROR; + } + else if (exectm.tm_hour == 12) { + exectm.tm_hour = 0; + } + ; + break;} +case 53: +#line 252 "parsetime.y" { if (exectm.tm_hour > 12) { yyerror("Hour too large for PM"); @@ -895,56 +1049,56 @@ } ; break;} -case 50: -#line 197 "parsetime.y" +case 54: +#line 264 "parsetime.y" { exectm.tm_mon = 0; ; break;} -case 51: -#line 198 "parsetime.y" +case 55: +#line 265 "parsetime.y" { exectm.tm_mon = 1; ; break;} -case 52: -#line 199 "parsetime.y" +case 56: +#line 266 "parsetime.y" { exectm.tm_mon = 2; ; break;} -case 53: -#line 200 "parsetime.y" +case 57: +#line 267 "parsetime.y" { exectm.tm_mon = 3; ; break;} -case 54: -#line 201 "parsetime.y" +case 58: +#line 268 "parsetime.y" { exectm.tm_mon = 4; ; break;} -case 55: -#line 202 "parsetime.y" +case 59: +#line 269 "parsetime.y" { exectm.tm_mon = 5; ; break;} -case 56: -#line 203 "parsetime.y" +case 60: +#line 270 "parsetime.y" { exectm.tm_mon = 6; ; break;} -case 57: -#line 204 "parsetime.y" +case 61: +#line 271 "parsetime.y" { exectm.tm_mon = 7; ; break;} -case 58: -#line 205 "parsetime.y" +case 62: +#line 272 "parsetime.y" { exectm.tm_mon = 8; ; break;} -case 59: -#line 206 "parsetime.y" +case 63: +#line 273 "parsetime.y" { exectm.tm_mon = 9; ; break;} -case 60: -#line 207 "parsetime.y" +case 64: +#line 274 "parsetime.y" { exectm.tm_mon =10; ; break;} -case 61: -#line 208 "parsetime.y" +case 65: +#line 275 "parsetime.y" { exectm.tm_mon =11; ; break;} -case 62: -#line 212 "parsetime.y" +case 66: +#line 279 "parsetime.y" { { int mnum = -1; @@ -959,8 +1113,8 @@ } ; break;} -case 63: -#line 226 "parsetime.y" +case 67: +#line 293 "parsetime.y" { exectm.tm_mday = -1; sscanf(yyvsp[0].charval, "%d", &exectm.tm_mday); @@ -972,8 +1126,8 @@ free(yyvsp[0].charval); ; break;} -case 64: -#line 239 "parsetime.y" +case 68: +#line 306 "parsetime.y" { { int ynum; @@ -994,36 +1148,36 @@ } ; break;} -case 65: -#line 261 "parsetime.y" +case 69: +#line 328 "parsetime.y" { yyval.intval = 0; ; break;} -case 66: -#line 262 "parsetime.y" +case 70: +#line 329 "parsetime.y" { yyval.intval = 1; ; break;} -case 67: -#line 263 "parsetime.y" +case 71: +#line 330 "parsetime.y" { yyval.intval = 2; ; break;} -case 68: -#line 264 "parsetime.y" +case 72: +#line 331 "parsetime.y" { yyval.intval = 3; ; break;} -case 69: -#line 265 "parsetime.y" +case 73: +#line 332 "parsetime.y" { yyval.intval = 4; ; break;} -case 70: -#line 266 "parsetime.y" +case 74: +#line 333 "parsetime.y" { yyval.intval = 5; ; break;} -case 71: -#line 267 "parsetime.y" +case 75: +#line 334 "parsetime.y" { yyval.intval = 6; ; break;} -case 72: -#line 271 "parsetime.y" +case 76: +#line 338 "parsetime.y" { if (sscanf(yyvsp[0].charval, "%d", &yyval.intval) != 1) { yyerror("Unknown increment"); @@ -1034,7 +1188,7 @@ break;} } /* the action file gets copied in in place of this dollarsign */ -#line 465 "/usr/lib/bison.simple" +#line 543 "/usr/share/misc/bison.simple" yyvsp -= yylen; yyssp -= yylen; @@ -1229,8 +1383,32 @@ yystate = yyn; goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; } -#line 287 "parsetime.y" +#line 354 "parsetime.y" @@ -1266,6 +1444,24 @@ } #ifdef TEST_PARSER +/* + +Here are some lines to test: + +./parsetest 7AM Mar 24 2000 +./parsetest 7AM Mar 24 00 +./parsetest 7AM 032400 +./parsetest 7AM 03/24/00 +./parsetest 7AM 24.03.00 +./parsetest 7AM Mar 24 + +./parsetest 03242000 +./parsetest noon 03242000 +./parsetest 5:30 +./parsetest 4pm + 3 days +./parsetest 10am Jul 31 + + */ int main(int argc, char **argv) { --- at-3.1.8.orig/y.tab.h +++ at-3.1.8/y.tab.h @@ -2,42 +2,42 @@ char * charval; int intval; } YYSTYPE; -#define INT 258 -#define NOW 259 -#define AM 260 -#define PM 261 -#define NOON 262 -#define MIDNIGHT 263 -#define TEATIME 264 -#define SUN 265 -#define MON 266 -#define TUE 267 -#define WED 268 -#define THU 269 -#define FRI 270 -#define SAT 271 -#define TODAY 272 -#define TOMORROW 273 -#define NEXT 274 -#define MINUTE 275 -#define HOUR 276 -#define DAY 277 -#define WEEK 278 -#define MONTH 279 -#define YEAR 280 -#define JAN 281 -#define FEB 282 -#define MAR 283 -#define APR 284 -#define MAY 285 -#define JUN 286 -#define JUL 287 -#define AUG 288 -#define SEP 289 -#define OCT 290 -#define NOV 291 -#define DEC 292 -#define WORD 293 +#define INT 257 +#define NOW 258 +#define AM 259 +#define PM 260 +#define NOON 261 +#define MIDNIGHT 262 +#define TEATIME 263 +#define SUN 264 +#define MON 265 +#define TUE 266 +#define WED 267 +#define THU 268 +#define FRI 269 +#define SAT 270 +#define TODAY 271 +#define TOMORROW 272 +#define NEXT 273 +#define MINUTE 274 +#define HOUR 275 +#define DAY 276 +#define WEEK 277 +#define MONTH 278 +#define YEAR 279 +#define JAN 280 +#define FEB 281 +#define MAR 282 +#define APR 283 +#define MAY 284 +#define JUN 285 +#define JUL 286 +#define AUG 287 +#define SEP 288 +#define OCT 289 +#define NOV 290 +#define DEC 291 +#define WORD 292 extern YYSTYPE yylval; --- at-3.1.8.orig/lex.yy.c +++ at-3.1.8/lex.yy.c @@ -1,7 +1,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header$ + * $Header$ */ #define FLEX_SCANNER @@ -126,6 +126,7 @@ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ @@ -235,7 +236,7 @@ #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); @@ -456,6 +457,7 @@ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "parsetime.l" #define INITIAL 0 @@ -491,7 +493,7 @@ result = 1; \ } \ } while(0) -#line 495 "lex.yy.c" +#line 497 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -513,6 +515,10 @@ static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); @@ -641,7 +647,7 @@ #line 36 "parsetime.l" -#line 645 "lex.yy.c" +#line 651 "lex.yy.c" if ( yy_init ) { @@ -919,7 +925,7 @@ #line 77 "parsetime.l" ECHO; YY_BREAK -#line 923 "lex.yy.c" +#line 929 "lex.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -930,6 +936,7 @@ /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { @@ -1075,7 +1082,7 @@ { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { - /* We matched a singled characater, the EOB, so + /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; @@ -1102,7 +1109,7 @@ /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ - yy_n_chars = 0; + yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { @@ -1157,6 +1164,8 @@ /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) @@ -1281,7 +1290,8 @@ yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); - yy_n_chars = yy_current_buffer->yy_buf_size; + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); @@ -1319,19 +1329,31 @@ else { /* need more input */ - yytext_ptr = yy_c_buf_p; + int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + case EOB_ACT_END_OF_FILE: { if ( yywrap() ) - { - yy_c_buf_p = - yytext_ptr + YY_MORE_ADJ; return EOF; - } if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; @@ -1343,17 +1365,8 @@ } case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + yy_c_buf_p = yytext_ptr + offset; break; - - case EOB_ACT_LAST_MATCH: -#ifdef __cplusplus - YY_FATAL_ERROR( - "unexpected last match in yyinput()" ); -#else - YY_FATAL_ERROR( - "unexpected last match in input()" ); -#endif } } } @@ -1517,6 +1530,9 @@ #endif { + if ( ! b ) + return; + b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes @@ -1576,17 +1592,17 @@ #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else -YY_BUFFER_STATE yy_scan_string( str ) -yyconst char *str; +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; #endif { int len; - for ( len = 0; str[len]; ++len ) + for ( len = 0; yy_str[len]; ++len ) ; - return yy_scan_bytes( str, len ); + return yy_scan_bytes( yy_str, len ); } #endif @@ -1707,7 +1723,7 @@ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ @@ -1730,6 +1746,22 @@ register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; } #endif --- at-3.1.8.orig/Makefile.in +++ at-3.1.8/Makefile.in @@ -131,6 +133,7 @@ clean: rm -f subs.sed *.o *.s at atd core a.out *~ $(CLONES) *.bak stamp-built + rm -f parsetest distclean: clean rm -rf at.1 atd.8 atrun.8 config.cache atrun config.h \ @@ -144,6 +147,9 @@ Filelist.asc: Filelist pgp -sba Filelist + +parsetest: lex.yy.c y.tab.c + $(CC) -o parsetest $(CFLAGS) $(DEFS) -DTEST_PARSER -DNEED_YYWRAP lex.yy.c y.tab.c .depend: $(CSRCS) gcc $(CFLAGS) $(DEFS) -MM $(CSRCS) > .depend --- at-3.1.8.orig/parsetime.y +++ at-3.1.8/parsetime.y @@ -11,6 +11,9 @@ static int isgmt; static int time_only; +extern int yyerror(char *s); +extern int yylex(); + int add_date(int number, int period); %} @@ -36,26 +39,31 @@ %start timespec %% -timespec : time +timespec : date + | time { time_only = 1; } | time date - | time increment - | time date increment - | time decrement - | time date decrement + | time_or_not inc_or_dec + | time_or_not date inc_or_dec | nowspec ; nowspec : now - | now increment - | now decrement + | now inc_or_dec ; now : NOW + | TOMORROW + { + add_date(1, DAY); + } ; +time_or_not : time + | + time : hr24clock_hr_min | hr24clock_hr_min timezone_name | hr24clock_hour time_sep minute @@ -83,10 +91,11 @@ ; date : month_name day_number + | month_name day_number year_number | month_name day_number ',' year_number | day_of_week { - add_date ((7 + $1 - exectm.tm_wday) %7 + 1, DAY); + add_date ((6 + $1 - exectm.tm_wday) %7 + 1, DAY); } | TODAY | TOMORROW @@ -101,6 +110,9 @@ | month_number '/' day_number '/' year_number ; +inc_or_dec : increment + | decrement + increment : '+' inc_number inc_period { add_date($2, $3); @@ -131,11 +143,57 @@ hr24clock_hr_min: INT { - exectm.tm_min = -1; - exectm.tm_hour = -1; if (strlen($1) == 4) { + exectm.tm_min = -1; + exectm.tm_hour = -1; sscanf($1, "%2d %2d", &exectm.tm_hour, &exectm.tm_min); + } else if (strlen($1) >= 5 && strlen($1) <= 8) { + /* Ok, this is a kluge. I hate design errors... -Joey */ + char shallot[5]; + char *onion; + + onion=$1; + memset (shallot, 0, sizeof (shallot)); + if (strlen($1) == 5 || strlen($1) == 7) { + strncpy (shallot,onion,1); + onion++; + } else { + strncpy (shallot,onion,2); + onion+=2; + } + sscanf(shallot, "%d", &exectm.tm_mon); + + if (exectm.tm_mon < 1 || exectm.tm_mon > 12) { + yyerror("Error in month number"); + YYERROR; + } + exectm.tm_mon--; + + memset (shallot, 0, sizeof (shallot)); + strncpy (shallot,onion,2); + sscanf(shallot, "%d", &exectm.tm_mday); + if (exectm.tm_mday < 0 || exectm.tm_mday > 31) + { + yyerror("Error in day of month"); + YYERROR; + } + + onion+=2; + memset (shallot, 0, sizeof (shallot)); + strncpy (shallot,onion,4); + if ( sscanf(shallot, "%d", &exectm.tm_year) != 1) { + yyerror("Error in year"); + YYERROR; + } + if (exectm.tm_year < 70) { + exectm.tm_year += 100; + } + else if (exectm.tm_year > 1900) { + exectm.tm_year -= 1900; + } + + free ($1); } else { sscanf($1, "%d", &exectm.tm_hour); @@ -148,7 +206,7 @@ YYERROR; } if (exectm.tm_hour > 24 || exectm.tm_hour < 0) { - yyerror("Problem in minutes specification"); + yyerror("Problem in hours specification"); YYERROR; } } @@ -181,6 +239,15 @@ ; am_pm : AM + { + if (exectm.tm_hour > 12) { + yyerror("Hour too large for AM"); + YYERROR; + } + else if (exectm.tm_hour == 12) { + exectm.tm_hour = 0; + } + } | PM { if (exectm.tm_hour > 12) { @@ -319,6 +386,24 @@ } #ifdef TEST_PARSER +/* + +Here are some lines to test: + +./parsetest 7AM Mar 24 2000 +./parsetest 7AM Mar 24 00 +./parsetest 7AM 032400 +./parsetest 7AM 03/24/00 +./parsetest 7AM 24.03.00 +./parsetest 7AM Mar 24 + +./parsetest 03242000 +./parsetest noon 03242000 +./parsetest 5:30 +./parsetest 4pm + 3 days +./parsetest 10am Jul 31 + + */ int main(int argc, char **argv) {