+#define ADD_OVERFLOW(a,b) ((a + b) < a) ? (a = ULONG_MAX) : (a = a + b)
+
+/* Convert format time string "XXwXXdXXhXXmXXs" into seconds value
+ * returns the value or ULONG_MAX on integer overflow or incorrect format
+ * Notes:
+ * 1. the order of specifiers is arbitrary (may be: 5w3s or 3s5w)
+ * 2. specifiers may be encountered multiple times (2s3s is 5 seconds)
+ * 3. empty integer value is interpreted as 0
+ */
+
+static unsigned long str2sec(const char* timestr) {
+ const char spec[] = "smhdw";
+ const unsigned long mult[] = {1, 60, 60*60, 24*60*60, 7*24*60*60};
+ unsigned long val = 0;
+ char *tail;
+
+ if (strpbrk(timestr, spec) == NULL) {
+ /* no specifiers inside the time string,
+ should treat it as an integer value */
+ val = strtoul(timestr, &tail, 10);
+ return *tail ? ULONG_MAX : val;
+ }
+
+ /* format string is XXwXXdXXhXXmXXs */
+ while (*timestr) {
+ unsigned long v;
+ int ind;
+ char* ptr;
+
+ v = strtoul(timestr, &tail, 10);
+ if (v == ULONG_MAX || *tail == '\0')
+ /* value too large (ULONG_MAX or more)
+ or missing specifier */
+ goto error;
+
+ ptr = strchr(spec, *tail);
+ if (ptr == NULL)
+ /* unknown specifier */
+ goto error;
+
+ ind = ptr - spec;
+
+ /* check if product will overflow the type */
+ if (!(v < ULONG_MAX / mult[ind]))
+ goto error;
+
+ ADD_OVERFLOW(val, mult[ind] * v);
+ if (val == ULONG_MAX)
+ goto error;
+
+ timestr = tail + 1;
+ }
+
+ return val;
+
+error:
+ return ULONG_MAX;
+}
+