chiark / gitweb /
Prep v220: Apply "Fixes to user and session saving"
[elogind.git] / src / shared / calendarspec.c
index 3cddb0eed01bccb29d433d3a10f3404ec98e173e..2fde3e107e0a81345cb39350290376554ec52eb3 100644 (file)
@@ -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)
@@ -738,7 +818,7 @@ fail:
 
 static int find_matching_component(const CalendarComponent *c, int *val) {
         const CalendarComponent *n;
-        int d;
+        int d = -1;
         bool d_set = false;
         int r;
 
@@ -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;
 }