X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fcalendarspec.c;h=19ae8a32335311263b671b92724801e0f2319c22;hp=c2eae3f139cd542241d4cdd978db390fd0be21c4;hb=2822da4fb7f891e5320f02f1d00f64b72221ced4;hpb=660ddc72f65474b4a16bd8a15d8f5cd1860b401b diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index c2eae3f13..19ae8a323 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -24,6 +24,8 @@ #include "calendarspec.h" +#define BITS_WEEKDAYS 127 + static void free_chain(CalendarComponent *c) { CalendarComponent *n; @@ -35,7 +37,9 @@ static void free_chain(CalendarComponent *c) { } void calendar_spec_free(CalendarSpec *c) { - assert(c); + + if (!c) + return; free_chain(c->year); free_chain(c->month); @@ -118,7 +122,7 @@ static void fix_year(CalendarComponent *c) { int calendar_spec_normalize(CalendarSpec *c) { assert(c); - if (c->weekdays_bits <= 0 || c->weekdays_bits >= 127) + if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS) c->weekdays_bits = -1; fix_year(c->year); @@ -133,7 +137,7 @@ int calendar_spec_normalize(CalendarSpec *c) { return 0; } -static bool chain_valid(CalendarComponent *c, int from, int to) { +_pure_ static bool chain_valid(CalendarComponent *c, int from, int to) { if (!c) return true; @@ -149,10 +153,10 @@ static bool chain_valid(CalendarComponent *c, int from, int to) { return true; } -bool calendar_spec_valid(CalendarSpec *c) { +_pure_ bool calendar_spec_valid(CalendarSpec *c) { assert(c); - if (c->weekdays_bits > 127) + if (c->weekdays_bits > BITS_WEEKDAYS) return false; if (!chain_valid(c->year, 1970, 2199)) @@ -192,7 +196,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) { assert(f); assert(c); - assert(c->weekdays_bits > 0 && c->weekdays_bits <= 127); + assert(c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS); for (x = 0, l = -1; x < (int) ELEMENTSOF(days); x++) { @@ -257,7 +261,7 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) { if (!f) return -ENOMEM; - if (c->weekdays_bits > 0 && c->weekdays_bits <= 127) { + if (c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS) { format_weekdays(f, c); fputc(' ', f); } @@ -391,7 +395,7 @@ static int prepend_component(const char **p, CalendarComponent **c) { errno = 0; value = strtoul(*p, &e, 10); - if (errno != 0) + if (errno > 0) return -errno; if (e == *p) return -EINVAL; @@ -400,7 +404,7 @@ static int prepend_component(const char **p, CalendarComponent **c) { if (*e == '/') { repeat = strtoul(e+1, &ee, 10); - if (errno != 0) + if (errno > 0) return -errno; if (ee == e+1) return -EINVAL; @@ -472,7 +476,7 @@ static int const_chain(int value, CalendarComponent **c) { cc->value = value; cc->repeat = 0; - cc->next = NULL; + cc->next = *c; *c = cc; @@ -653,7 +657,23 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (!c) return -ENOMEM; - if (strcasecmp(p, "hourly") == 0) { + if (strcaseeq(p, "minutely")) { + r = const_chain(0, &c->second); + if (r < 0) + goto fail; + + } else if (strcaseeq(p, "hourly")) { + r = const_chain(0, &c->minute); + if (r < 0) + goto fail; + r = const_chain(0, &c->second); + if (r < 0) + goto fail; + + } else if (strcaseeq(p, "daily")) { + r = const_chain(0, &c->hour); + if (r < 0) + goto fail; r = const_chain(0, &c->minute); if (r < 0) goto fail; @@ -661,7 +681,10 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (r < 0) goto fail; - } else if (strcasecmp(p, "daily") == 0) { + } else if (strcaseeq(p, "monthly")) { + r = const_chain(1, &c->day); + if (r < 0) + goto fail; r = const_chain(0, &c->hour); if (r < 0) goto fail; @@ -672,7 +695,13 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (r < 0) goto fail; - } else if (strcasecmp(p, "monthly") == 0) { + } else if (strcaseeq(p, "annually") || + strcaseeq(p, "yearly") || + strcaseeq(p, "anually") /* backwards compatibility */ ) { + + r = const_chain(1, &c->month); + if (r < 0) + goto fail; r = const_chain(1, &c->day); if (r < 0) goto fail; @@ -686,7 +715,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (r < 0) goto fail; - } else if (strcasecmp(p, "weekly") == 0) { + } else if (strcaseeq(p, "weekly")) { c->weekdays_bits = 1; @@ -700,6 +729,57 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { if (r < 0) goto fail; + } else if (strcaseeq(p, "quarterly")) { + + r = const_chain(1, &c->month); + if (r < 0) + goto fail; + r = const_chain(4, &c->month); + if (r < 0) + goto fail; + r = const_chain(7, &c->month); + if (r < 0) + goto fail; + r = const_chain(10, &c->month); + if (r < 0) + goto fail; + r = const_chain(1, &c->day); + if (r < 0) + goto fail; + r = const_chain(0, &c->hour); + if (r < 0) + goto fail; + r = const_chain(0, &c->minute); + if (r < 0) + goto fail; + r = const_chain(0, &c->second); + if (r < 0) + goto fail; + + } else if (strcaseeq(p, "biannually") || + strcaseeq(p, "bi-annually") || + strcaseeq(p, "semiannually") || + strcaseeq(p, "semi-annually")) { + + r = const_chain(1, &c->month); + if (r < 0) + goto fail; + r = const_chain(7, &c->month); + if (r < 0) + goto fail; + r = const_chain(1, &c->day); + if (r < 0) + goto fail; + r = const_chain(0, &c->hour); + if (r < 0) + goto fail; + r = const_chain(0, &c->minute); + if (r < 0) + goto fail; + r = const_chain(0, &c->second); + if (r < 0) + goto fail; + } else { r = parse_weekdays(&p, c); if (r < 0) @@ -802,7 +882,7 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm) { struct tm t; int k; - if (weekdays_bits < 0 || weekdays_bits >= 127) + if (weekdays_bits < 0 || weekdays_bits >= BITS_WEEKDAYS) return true; t = *tm; @@ -921,7 +1001,6 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) if (t == (time_t) -1) return -EINVAL; - *next = (usec_t) t * USEC_PER_SEC; return 0; }