From: Nicolas Samberger Subject: newsyslog: refactor date parsing To: Date: Mon, 20 Apr 2026 14:44:35 +0200 Hi all, analogue to rev1.118 [1], I refactored parseDWM() in newsyslog(8) for date parsing. I replaced the manual parsing with strtol(3) by strptime(3). Best regards Nico [1]: https://cvsweb.openbsd.org/log/src/usr.bin/newsyslog/newsyslog.c,v?sort=File#rev1.118 Index: newsyslog.c =================================================================== RCS file: /cvs/src/usr.bin/newsyslog/newsyslog.c,v diff -u -p -r1.120 newsyslog.c --- newsyslog.c 2 Apr 2026 18:22:24 -0000 1.120 +++ newsyslog.c 20 Apr 2026 13:17:33 -0000 @@ -1239,10 +1239,10 @@ time_t parseDWM(char *s) { static int mtab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - int WMseen = 0, Dseen = 0, nd; - struct tm tm; - char *t; - long l; + int nd; + char format[7] = { 0 }; + struct tm tm, now; + char *d, *w, *m; if (localtime_r(&timenow, &tm) == NULL) return -1; @@ -1259,79 +1259,49 @@ parseDWM(char *s) } } tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + memcpy(&now, &tm, sizeof tm); - for (;;) { - switch (*s) { - case 'D': - if (Dseen) - return (-1); - Dseen++; - s++; - l = strtol(s, &t, 10); - if (l < 0 || l > 23) - return (-1); - tm.tm_hour = l; - break; - - case 'W': - if (WMseen) - return (-1); - WMseen++; - s++; - l = strtol(s, &t, 10); - if (l < 0 || l > 6) - return (-1); - if (l != tm.tm_wday) { - int save; - - if (l < tm.tm_wday) { - save = 6 - tm.tm_wday; - save += (l + 1); - } else { - save = l - tm.tm_wday; - } - - tm.tm_mday += save; - - if (tm.tm_mday > nd) { - tm.tm_mon++; - tm.tm_mday = tm.tm_mday - nd; - } - } - break; - - case 'M': - if (WMseen) - return (-1); - WMseen++; - s++; - if (tolower((unsigned char)*s) == 'l') { - tm.tm_mday = nd; - s++; - t = s; - } else { - l = strtol(s, &t, 10); - if (l < 1 || l > 31) - return (-1); - - if (l > nd) - return (-1); - if (l < tm.tm_mday) - tm.tm_mon++; - tm.tm_mday = l; - } - break; - - default: - return (-1); - break; - } + m = strchr(s, 'M'); + w = strchr(s, 'W'); + d = strchr(s, 'D'); + + if (m != NULL && w != NULL) + return -1; - if (*t == '\0' || isspace((unsigned char)*t)) - break; + if ((m != NULL && w == NULL) && s == m) { + if (tolower(m[1]) == 'l') { + tm.tm_mday = nd; + snprintf(format, sizeof format, "M%c", m[1]); + s = d; + } else { + strlcat(format, "M%e", sizeof format); + } + } else if ((w != NULL && m == NULL) && s == w) { + strlcat(format, "W%w", sizeof format); + } else if (d != s) + return (-1); + + if (d != NULL) + strlcat(format, "D%H", sizeof format); + + if (strptime(s, format, &tm) == NULL) + return (-1); + + if (tm.tm_wday != now.tm_wday) { + if (now.tm_wday > tm.tm_wday) + tm.tm_mday += 7 - (now.tm_wday - tm.tm_wday); else - s = t; + tm.tm_mday += tm.tm_wday - now.tm_wday; + + if (tm.tm_mday > nd) { + tm.tm_mday -= nd; + tm.tm_mon++; + } } + + if (now.tm_mday > tm.tm_mday) + tm.tm_mon++; + return (mktime(&tm)); }