scron

simple cron daemon
git clone git://git.2f30.org/scron.git
Log | Files | Refs | README | LICENSE

commit d00e7c1889ddc25ef4584556a3fcb209a2890117
parent f5e54befa9ebbb40b40dc184542ea945db4a07e2
Author: Ari Malinen <ari.malinen@gmail.com>
Date:   Fri Feb  6 22:20:52 +0200

Support list items

Diffstat:
README | 2+-
TODO | 1-
crond.c | 56+++++++++++++++++++++++++++++++++++++++++++++++++++-----
scron.1 | 4++--
4 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/README b/README @@ -20,7 +20,7 @@ Separator: Any number of tabs or spaces. Value: - * (wildcard), 30 (number), */N (repeat), or 1-5 (range) + * (wildcard), 30 (number), */N (repeat), 1-5 (range), or 1,3,6 (list) Example of crontab file: # Run updatedb at 6:00 every day diff --git a/TODO b/TODO @@ -1,3 +1,2 @@ -* Support list items: 2,3,5,7,11 * Detect clock changes * DST support? diff --git a/crond.c b/crond.c @@ -27,9 +27,11 @@ struct field { WILDCARD, NUMBER, RANGE, - STEP + REPEAT, + LIST } type; long *val; + int len; }; struct ctabentry { @@ -234,6 +236,7 @@ matchentry(struct ctabentry *cte, struct tm *tm) { .f = &cte->wday, .tm = tm->tm_wday, .len = 7 }, }; size_t i; + int j; for (i = 0; i < LEN(matchtbl); i++) { switch (matchtbl[i].f->type) { @@ -248,7 +251,7 @@ matchentry(struct ctabentry *cte, struct tm *tm) if (matchtbl[i].f->val[1] >= matchtbl[i].tm) continue; break; - case STEP: + case REPEAT: if (matchtbl[i].tm > 0) { if (matchtbl[i].tm % matchtbl[i].f->val[0] == 0) continue; @@ -257,6 +260,13 @@ matchentry(struct ctabentry *cte, struct tm *tm) continue; } 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; } @@ -270,6 +280,7 @@ matchentry(struct ctabentry *cte, struct tm *tm) static int parsefield(const char *field, long low, long high, struct field *f) { + int i; char *e1, *e2; const char *p; @@ -281,45 +292,80 @@ parsefield(const char *field, long low, long high, struct field *f) switch (*p) { case '*': - if (p[1] == '\0') { + if (p[1] == '\0') f->type = WILDCARD; - } else if (p[1] == '/') { + + if (p[1] == '/') { f->val = emalloc(sizeof(*f->val)); + errno = 0; f->val[0] = strtol(field + 2, &e1, 10); if (e1[0] != '\0' || errno != 0) break; if (f->val[0] == 0 || f->val[0] < low || f->val[0] > high) break; - f->type = STEP; + + f->type = REPEAT; } break; case '\0': f->val = emalloc(sizeof(*f->val)); + errno = 0; f->val[0] = strtol(field, &e1, 10); if (e1[0] != '\0' || errno != 0) break; if (f->val[0] < low || f->val[0] > high) break; + f->type = NUMBER; break; case '-': f->val = emalloc(2 * sizeof(*f->val)); + errno = 0; f->val[0] = strtol(field, &e1, 10); if (e1[0] != '-' || errno != 0) break; if (f->val[0] < low || f->val[0] > high) break; + errno = 0; f->val[1] = strtol(e1 + 1, &e2, 10); if (e2[0] != '\0' || errno != 0) break; if (f->val[1] < low || f->val[1] > high) break; + f->type = RANGE; break; + case ',': + i = 1; + while (isdigit(*p) || *p == ',') { + if (*p == ',') + i++; + p++; + } + f->val = emalloc(i * sizeof(*f->val)); + f->len = i; + + errno = 0; + f->val[0] = strtol(field, &e1, 10); + if (f->val[0] < low || f->val[0] > high) + break; + + for (i = 1; *e1 == ',' && errno == 0; i++) { + errno = 0; + f->val[i] = strtol(e1 + 1, &e2, 10); + if (f->val[i] < low || f->val[i] > high) + errno = -1; + e1 = e2; + } + if (e1[0] != '\0' || errno != 0) + break; + + f->type = LIST; + break; default: return -1; } diff --git a/scron.1 b/scron.1 @@ -1,4 +1,4 @@ -.Dd Jan 30, 2015 +.Dd Feb 6, 2015 .Dt SCRON 1 .Os .Sh NAME @@ -32,7 +32,7 @@ Separator: Any number of tabs or spaces. Value: - * (wildcard), 30 (number), */N (repeat), or 1-5 (range) + * (wildcard), 30 (number), */N (repeat), 1-5 (range), or 1,3,6 (list) .Sh EXAMPLE Example of crontab file: # Run updatedb at 6:00 every day