commit 1d8d5d3eb73db926fa047bf409e2b599dc8f1b8e
parent b9d8303d3e35a6cede12d282c93362177b1ce7e0
Author: Ari Malinen <ari.malinen@gmail.com>
Date: Fri, 6 Feb 2015 19:02:18 +0200
Add fieldtype enum to know the type of field in matchentry() and parsefield()
Diffstat:
M | LICENSE | | | 2 | +- |
M | crond.c | | | 179 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
2 files changed, 120 insertions(+), 61 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -1,6 +1,6 @@
MIT/X Consortium License
-© 2014 Ari Malinen <ari.malinen@gmail.com>
+© 2014-2015 Ari Malinen <ari.malinen@gmail.com>
© 2014 sin <sin@2f30.org>
© 2014 Hiltjo Posthuma <hiltjo@codemadness.org>
diff --git a/crond.c b/crond.c
@@ -8,6 +8,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
@@ -20,12 +21,17 @@
#define LEN(x) (sizeof (x) / sizeof *(x))
+enum fieldtype {
+ error,
+ wildcard,
+ number,
+ range,
+ step
+};
+
struct field {
- /* [low, high] */
- long low;
- long high;
- /* for every `div' units */
- long div;
+ enum fieldtype type;
+ long *val;
};
struct ctabentry {
@@ -232,23 +238,29 @@ matchentry(struct ctabentry *cte, struct tm *tm)
size_t i;
for (i = 0; i < LEN(matchtbl); i++) {
- if (matchtbl[i].f->high == -1) {
- if (matchtbl[i].f->low == -1) {
- continue;
- } else if (matchtbl[i].f->div > 0) {
- if (matchtbl[i].tm > 0) {
- if (matchtbl[i].tm % matchtbl[i].f->div == 0)
- continue;
- } else {
- if (matchtbl[i].len % matchtbl[i].f->div == 0)
- continue;
- }
- } else if (matchtbl[i].f->low == matchtbl[i].tm) {
+ 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 step:
+ 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;
}
- } else if (matchtbl[i].f->low <= matchtbl[i].tm &&
- matchtbl[i].f->high >= matchtbl[i].tm) {
- continue;
+ break;
+ default:
+ break;
}
break;
}
@@ -257,61 +269,109 @@ matchentry(struct ctabentry *cte, struct tm *tm)
return 1;
}
+enum fieldtype getfieldtype(const char *field) {
+ const char *p;
+
+ if (strcmp(field, "*") == 0)
+ return wildcard;
+
+ p = field;
+ while (isdigit(*p))
+ p++;
+ if (*p == '\0')
+ return number;
+
+ p = field;
+ while (isdigit(*p) || *p == '-')
+ p++;
+ if (*p == '\0')
+ return range;
+
+ p = field;
+ while (isdigit(*p) || *p == '*' || *p == '/')
+ p++;
+ if (*p == '\0')
+ return step;
+
+ return error;
+}
+
static int
parsefield(const char *field, long low, long high, struct field *f)
{
- long min, max, div;
char *e1, *e2;
- if (strcmp(field, "*") == 0) {
- f->low = -1;
- f->high = -1;
- return 0;
- }
-
- div = -1;
- max = -1;
- min = strtol(field, &e1, 10);
-
- switch (e1[0]) {
- case '-':
- e1++;
+ f->type = error;
+ switch (getfieldtype(field)) {
+ case wildcard:
+ f->type = wildcard;
+ break;
+ case number:
+ f->val = emalloc(sizeof(*f->val));
errno = 0;
- max = strtol(e1, &e2, 10);
- if (e2[0] != '\0' || errno != 0)
- return -1;
+ 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 '*':
- e1++;
- if (e1[0] != '/')
- return -1;
- e1++;
+ case range:
+ f->val = emalloc(2 * sizeof(*f->val));
errno = 0;
- div = strtol(e1, &e2, 10);
+ 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)
- return -1;
+ break;
+ if (f->val[1] < low || f->val[1] > high)
+ break;
+ f->type = range;
break;
- case '\0':
+ case step:
+ if (strncmp(field, "*/", 2) != 0)
+ return -1;
+ f->val = emalloc(sizeof(*f->val));
+ 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;
break;
default:
return -1;
}
-
- if (min < low || min > high)
+ if (f->type == error) {
+ free(f->val);
return -1;
- if (max != -1)
- if (max < low || max > high)
- return -1;
- if (div != -1)
- if (div < low || div > high)
- return -1;
+ }
- f->low = min;
- f->high = max;
- f->div = div;
return 0;
}
+void freecte(struct ctabentry *cte, int nfields) {
+ switch (nfields) {
+ case 6:
+ free(cte->cmd);
+ case 5:
+ free(cte->wday.val);
+ case 4:
+ free(cte->mon.val);
+ case 3:
+ free(cte->mday.val);
+ case 2:
+ free(cte->hour.val);
+ case 1:
+ free(cte->min.val);
+ }
+ free(cte);
+}
+
static void
unloadentries(void)
{
@@ -320,8 +380,7 @@ unloadentries(void)
for (cte = TAILQ_FIRST(&ctabhead); cte; cte = tmp) {
tmp = TAILQ_NEXT(cte, entry);
TAILQ_REMOVE(&ctabhead, cte, entry);
- free(cte->cmd);
- free(cte);
+ freecte(cte, 6);
}
}
@@ -374,7 +433,7 @@ loadentries(void)
if (!col || parsefield(col, flim[x].min, flim[x].max, flim[x].f) < 0) {
logerr("error: failed to parse `%s' field on line %d\n",
flim[x].name, y + 1);
- free(cte);
+ freecte(cte, x);
r = -1;
break;
}
@@ -387,7 +446,7 @@ loadentries(void)
if (!col) {
logerr("error: missing `cmd' field on line %d\n",
y + 1);
- free(cte);
+ freecte(cte, 6);
r = -1;
break;
}