commit 5f6a3dad770e6e57218c3b82f96a8ed9b7a5a23d
Author:     Roberto E. Vargas Caballero <k...@shike2.com>
AuthorDate: Thu Dec 19 12:53:24 2024 +0100
Commit:     Roberto E. Vargas Caballero <k...@shike2.com>
CommitDate: Thu Dec 19 12:53:24 2024 +0100

    cron: Revert to version before 6c8dc15
    
    The changes introduced after 6c8dc15 had some problems and it
    was really hard to follow the chain of changes, and for that
    reason I took the conservative decision of reverting to the
    original code.

diff --git a/cron.c b/cron.c
index bd9f247..77304cc 100644
--- a/cron.c
+++ b/cron.c
@@ -17,13 +17,19 @@
 #include "queue.h"
 #include "util.h"
 
-struct range {
-       long low, high, repeat;
-       TAILQ_ENTRY(range) entry;
+struct field {
+       enum {
+               ERROR,
+               WILDCARD,
+               NUMBER,
+               RANGE,
+               REPEAT,
+               LIST
+       } type;
+       long *val;
+       int len;
 };
 
-TAILQ_HEAD(field, range);
-
 struct ctabentry {
        struct field min;
        struct field hour;
@@ -196,148 +202,141 @@ matchentry(struct ctabentry *cte, struct tm *tm)
                { .f = &cte->wday, .tm = tm->tm_wday, .len = 7  },
        };
        size_t i;
-       int found, t;
-       long low;
-       struct range *r;
+       int j;
 
        for (i = 0; i < LEN(matchtbl); i++) {
-               found = 0;
-               t = matchtbl[i].tm;
-               TAILQ_FOREACH(r, matchtbl[i].f, entry) {
-                       if (r->low <= t && r->high >= t && t % r->repeat == 0) {
-                               found = 1;
-                               break;
+               switch (matchtbl[i].f->type) {
+               case WILDCARD:
+                       continue;
+               case NUMBER:
+                       if (matchtbl[i].f->val[0] == matchtbl[i].tm)
+                               continue;
+                       break;
+               case RANGE:
+                       if (matchtbl[i].f->val[0] <= matchtbl[i].tm)
+                               if (matchtbl[i].f->val[1] >= matchtbl[i].tm)
+                                       continue;
+                       break;
+               case REPEAT:
+                       if (matchtbl[i].tm > 0) {
+                               if (matchtbl[i].tm % matchtbl[i].f->val[0] == 0)
+                                       continue;
+                       } else {
+                               if (matchtbl[i].len % matchtbl[i].f->val[0] == 
0)
+                                       continue;
                        }
-               }
-               if (!found)
                        break;
+               case LIST:
+                       for (j = 0; j < matchtbl[i].f->len; j++)
+                               if (matchtbl[i].f->val[j] == matchtbl[i].tm)
+                                       break;
+                       if (j < matchtbl[i].f->len)
+                               continue;
+                       break;
+               default:
+                       break;
+               }
+               break;
        }
        if (i != LEN(matchtbl))
                return 0;
-
        return 1;
 }
 
-
 static int
-parserange(char *str, long low, long high, struct range *r)
+parsefield(const char *field, long low, long high, struct field *f)
 {
-       /* range = number |
-        * [number] "~" [number] ["/" number] |
-        * number "-" number ["/" number]
-        */
-       char *range, *repeat, *strlow, *strhigh;
-       char *e;
-       int random;
-
-       random = 0;
-
-       range = strsep(&str, "/");
-       repeat = strsep(&str, "/");
-       if (!range || !*range)
-               return -1;
+       int i;
+       char *e1, *e2;
+       const char *p;
+
+       p = field;
+       while (isdigit(*p))
+               p++;
+
+       f->type = ERROR;
+
+       switch (*p) {
+       case '*':
+               if (strcmp(field, "*") == 0) {
+                       f->val = NULL;
+                       f->len = 0;
+                       f->type = WILDCARD;
+               } else if (strncmp(field, "*/", 2) == 0) {
+                       f->val = emalloc(sizeof(*f->val));
+                       f->len = 1;
 
-       switch (*range) {
-       case '~':
-               random = 1;
-       case '*': /* fallthru */
-               if (range[1] != '\0')
-                       return -1;
-               r->low = low;
-               r->high = high;
+                       errno = 0;
+                       f->val[0] = strtol(field + 2, &e1, 10);
+                       if (e1[0] != '\0' || errno != 0 || f->val[0] == 0)
+                               break;
+
+                       f->type = REPEAT;
+               }
                break;
-       ARGNUM:
-               strlow = strsep(&range, "-");
-               strhigh = strsep(&range, "-");
-               if (!*strlow) /* i.e. - */
-                       return -1;
+       case '\0':
+               f->val = emalloc(sizeof(*f->val));
+               f->len = 1;
 
                errno = 0;
-               r->low = strtol(strlow, &e, 10);
-               if ((*e && *e != '~') || errno != 0)
-                       return -1;
-               if (strhigh) {
-                       if (!*strhigh || range != NULL) /* i.e. N- or N-M-... */
-                               return -1;
-                       errno = 0;
-                       r->high = strtol(strhigh, &e, 10);
-                       if (*e || errno != 0)
-                               return -1;
-               } else {
-                       e = strsep(&strlow, "~");
-                       if (!strlow) /* i.e. N */
-                               r->high = r->low;
-                       strhigh = strsep(&strlow, "-");
-                       if (strhigh) {
-                               if (!*strhigh || strlow != NULL) /* i.e. N~ or 
N~M~... */
-                                       return -1;
-                               random = 1;
-
-                               errno = 0;
-                               r->high = strtol(strhigh, &e, 10);
-                               if (*e || errno != 0)
-                                       return -1;
-                       }
-               }
+               f->val[0] = strtol(field, &e1, 10);
+               if (e1[0] != '\0' || errno != 0)
+                       break;
+
+               f->type = NUMBER;
                break;
-       }
+       case '-':
+               f->val = emalloc(2 * sizeof(*f->val));
+               f->len = 2;
 
-       if (repeat) {
-               if (!*repeat || str != NULL)
-                       return -1;
                errno = 0;
-               r->repeat = strtol(repeat, &e, 10);
-               if (*e || errno != 0 || r->repeat == 0)
-                       return -1;
-       } else {
-               r->repeat = 1;
-       }
+               f->val[0] = strtol(field, &e1, 10);
+               if (e1[0] != '-' || errno != 0)
+                       break;
 
-       if (random) {
-               /* random replaces low in matchentry() */
-               r->repeat = r->low; /* so that it doesn't repeat */
-               r->low = random_uniform(r->high - r->low+1) + r->low;
-       }
+               errno = 0;
+               f->val[1] = strtol(e1 + 1, &e2, 10);
+               if (e2[0] != '\0' || errno != 0)
+                       break;
 
-       if (r->low < low || r->low > high || r->high < low || r->high > high || 
r->repeat < low || r->repeat > high) {
-               return -1;
-       }
+               f->type = RANGE;
+               break;
+       case ',':
+               for (i = 1; isdigit(*p) || *p == ','; p++)
+                       if (*p == ',')
+                               i++;
+               f->val = emalloc(i * sizeof(*f->val));
+               f->len = i;
 
-       return 0;
-}
+               errno = 0;
+               f->val[0] = strtol(field, &e1, 10);
+               if (f->val[0] < low || f->val[0] > high)
+                       break;
 
-static int
-parsefield(char *field, long low, long high, struct field *f)
-{
-       char *elem;
-       struct range *r;
-
-       int first = 1;
-       while ((elem = strsep(&field, ",")) != NULL) {
-               if (*elem == '\0')
-                       return -1;
-               first = 0;
-
-               r = emalloc(sizeof(*r));
-               if (parserange(elem, low, high, r))
-                       return -1;
-               TAILQ_INSERT_TAIL(f, r, entry);
-       }
+               for (i = 1; *e1 == ',' && errno == 0; i++) {
+                       errno = 0;
+                       f->val[i] = strtol(e1 + 1, &e2, 10);
+                       e1 = e2;
+               }
+               if (e1[0] != '\0' || errno != 0)
+                       break;
 
-       if (first)
+               f->type = LIST;
+               break;
+       default:
                return -1;
+       }
 
-       return 0;
-}
+       for (i = 0; i < f->len; i++)
+               if (f->val[i] < low || f->val[i] > high)
+                       f->type = ERROR;
 
-static void
-freefield(struct field *f)
-{
-       struct range *r;
-       while ((r = TAILQ_FIRST(f))) {
-               TAILQ_REMOVE(f, r, entry);
-               free(r);
+       if (f->type == ERROR) {
+               free(f->val);
+               return -1;
        }
+
+       return 0;
 }
 
 static void
@@ -347,15 +346,15 @@ freecte(struct ctabentry *cte, int nfields)
        case 6:
                free(cte->cmd);
        case 5:
-               freefield(&cte->wday);
+               free(cte->wday.val);
        case 4:
-               freefield(&cte->mon);
+               free(cte->mon.val);
        case 3:
-               freefield(&cte->mday);
+               free(cte->mday.val);
        case 2:
-               freefield(&cte->hour);
+               free(cte->hour.val);
        case 1:
-               freefield(&cte->min);
+               free(cte->min.val);
        }
        free(cte);
 }
@@ -413,7 +412,6 @@ loadentries(void)
                flim[4].f = &cte->wday;
 
                for (x = 0; x < LEN(flim); x++) {
-                       TAILQ_INIT(flim[x].f);
                        do
                                col = strsep(&p, "\t\n ");
                        while (col && col[0] == '\0');
@@ -527,8 +525,6 @@ main(int argc, char *argv[])
        sigaction(SIGHUP, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
 
-       random_seed();
-
        loadentries();
 
        while (1) {

Reply via email to