commit 5f6a3dad770e6e57218c3b82f96a8ed9b7a5a23d
parent 11c53a1739e17c6fe5fb233e187e35d9600e6c60
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 19 Dec 2024 12:53:24 +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.
Diffstat:
M | cron.c | | | 250 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
1 file changed, 123 insertions(+), 127 deletions(-)
diff --git 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) {