#include #include #include #define A_MINUTE 60 #define MAXLINE 512 #define MINUTES 59 #define HOURS 23 #define DOMS 31 #define MOYS 12 #define DOWS 7 #define ANY '*' #define NFSEP ',' int too_long = 0; char *crontab = {"crontab"}; FILE *cronfile = 0; char cronline[MAXLINE] = {0}; char *command = 0; char *input = 0; long now = 0; struct time *tm = {0}; int minute[MINUTES+1] = {0}; int hour[HOURS+1] = {0}; int dom[DOMS+2] = {0}; int moy[MOYS+2] = {0}; int dow[DOWS+2] = {0}; int debug = 0; main (argc, argv) int argc; char **argv; { int nada (); int pid; if (fork () != 0) exit (0); signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); if (argc > 1) ++debug; if ((cronfile = fopen (crontab, "r")) == NULL) { fprintf (stderr, "%s: can't access %s\n", argv[0], crontab); exit (1); } signal (SIGALRM, nada); for (;;) { rewind (cronfile); too_long = 0; alarm (A_MINUTE); get_time (); while (get_cron_line () != NULL) if (parse () && nows_the_time ()) do_the_command (); while (wait (&pid) != -1) ; if (!too_long) pause (); } } nada () { ++too_long; signal (SIGALRM, nada); } get_time () { time (&now); tm = localtime (&tm); } get_cron_line () { return (fgets (cronline, MAXLINE, cronfile)); } parse () { register char *p; if (debug) printf ("parsing: %s", cronline); p = cronline; if ((p = get_n_field (p, 0, MINUTES, minute)) == NULL) { p_field_error ("minutes"); return (NULL); } if ((p = get_n_field (p, 0, HOURS, hour)) == NULL) { p_field_error ("hours"); return (NULL); } if ((p = get_n_field (p, 1, DOMS, dom)) == NULL) { p_field_error ("day of month"); return (NULL); } if ((p = get_n_field (p, 1, MOYS, moy)) == NULL) { p_field_error ("month of year"); return (NULL); } if ((p = get_n_field (p, 1, DOWS, dow)) == NULL) { p_field_error ("day of week"); return (NULL); } while (*p == ' ' || *p == '\t') ++p; if (*p == '\n' || *p == '\0') { p_field_error ("command"); return (NULL); } command = p; input = 0; while (*p) { if (*p == '%') { if (input == 0) { *p = '\0'; input = p + 1; } else *p = '\n'; } else if (*p == '\n' && input == 0) *p = '\0'; ++p; } if (debug) { printf ("successful parse: %s", ctime (&now)); p_n_field ("minutes ", 0, MINUTES, minute); p_n_field ("hours ", 0, HOURS, hour); p_n_field ("days of month ", 1, DOMS, dom); p_n_field ("months of year", 1, MOYS, moy); p_n_field ("days of week ", 1, DOWS, dow); printf ("command: %s\n", command); printf ("input: %s", (input) ? input : "--> NONE <--\n"); } } p_n_field (s, low, high, fa) char *s; int low, high; int fa[]; { register int i; register int all; printf ("%s:", s); for (i = low, all = 1; i <= high && all; ++i) if (fa[i] == 0) all = 0; if (all) { printf (" ALL\n"); return; } printf ("\n"); for (i = 0; low <= high; ++low) if (fa[low]) { printf (" %2d", low); if (++i > 30) { printf ("\n"); i = 0; } } if (i) printf ("\n"); printf ("\n"); } get_n_field (p, low, high, fa) char *p; int low, high; int fa[]; { register int i; for (i = low; i <= high; ++i) fa[i] = 0; while (*p == ' ' || *p == '\t') ++p; do { if ((p = get_pat (p, low, high, fa)) == NULL) return (NULL); } while (*p++ == NFSEP); if (*--p != ' ' && *p != '\t') return (NULL); return (p); } get_pat (p, low, high, fa) char *p; int low, high; int fa[]; { register int i; int first; int last; if (*p == ANY) { first = low; last = high; ++p; } else if (isdigit (*p)) { first = last = atoi (p); while (isdigit (*p)) ++p; if (*p == '-' && isdigit (p[1])) { last = atoi (++p); while (isdigit (*p)) ++p; } if (first > last) { i = first; first = last; last = first; } } else return (NULL); if (first < low || high < last) return (NULL); for (i = first; i <= last; ++i) fa[i] = 1; return (p); } atoi (p) register char *p; { register int i; for (i = 0; isdigit (*p); ++p) i = i * 10 + *p - '0'; return (i); } p_field_error (s) char *s; { if (debug) fprintf (stderr, "invalid %s field: %s", s, cronline); } /* ** crontab thinks sunday is day 7, whereas ** localtime thinks sunday is day 0 ** so map it! */ int dow_map[7] = {7, 1, 2, 3, 4, 5, 6}; nows_the_time () { return (minute [tm->minutes ] && hour [tm->hours ] && dom [tm->day_month + 1 ] && moy [tm->month + 1 ] && dow [dow_map[tm->day_week]] ); } do_the_command () { register FILE *f; register int pid; if ((pid = fork ()) == 0) { if ((f = popen (command, "w")) != NULL) { fwrite (input, strlen (input), 1, f); fflush (f); pclose (f); } exit (0); } }