1c39934eaSBrian Somers /*- 2c39934eaSBrian Somers * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 3c39934eaSBrian Somers * All rights reserved. 4c39934eaSBrian Somers * 5c39934eaSBrian Somers * Redistribution and use in source and binary forms, with or without 6c39934eaSBrian Somers * modification, are permitted provided that the following conditions 7c39934eaSBrian Somers * are met: 8c39934eaSBrian Somers * 1. Redistributions of source code must retain the above copyright 9c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer. 10c39934eaSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 11c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer in the 12c39934eaSBrian Somers * documentation and/or other materials provided with the distribution. 13c39934eaSBrian Somers * 14c39934eaSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15c39934eaSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16c39934eaSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17c39934eaSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18c39934eaSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19c39934eaSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20c39934eaSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21c39934eaSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22c39934eaSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23c39934eaSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24c39934eaSBrian Somers * SUCH DAMAGE. 25c39934eaSBrian Somers */ 26c39934eaSBrian Somers 27cbf6f7d3SPhilippe Charnier #ifndef lint 28cbf6f7d3SPhilippe Charnier static const char rcsid[] = 292a456239SPeter Wemm "$FreeBSD$"; 30cbf6f7d3SPhilippe Charnier #endif /* not lint */ 31cbf6f7d3SPhilippe Charnier 329afa09cdSMark Murray #include <sys/cdefs.h> 336e4cd31dSBrian Somers #include <err.h> 347ca215a6SBrian Somers #include <time.h> 357ca215a6SBrian Somers #include <string.h> 367ca215a6SBrian Somers #include <stdlib.h> 377ca215a6SBrian Somers #include "vary.h" 387ca215a6SBrian Somers 397ca215a6SBrian Somers struct trans { 407ca215a6SBrian Somers int val; 419afa09cdSMark Murray const char *str; 427ca215a6SBrian Somers }; 437ca215a6SBrian Somers 447ca215a6SBrian Somers static struct trans trans_mon[] = { 457ca215a6SBrian Somers { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" }, 463b006d8eSAlfred Perlstein { 5, "may"}, { 6, "june" }, { 7, "july" }, { 8, "august" }, 473b006d8eSAlfred Perlstein { 9, "september" }, { 10, "october" }, { 11, "november" }, { 12, "december" }, 487ca215a6SBrian Somers { -1, NULL } 497ca215a6SBrian Somers }; 507ca215a6SBrian Somers 517ca215a6SBrian Somers static struct trans trans_wday[] = { 527ca215a6SBrian Somers { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" }, 537ca215a6SBrian Somers { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" }, 547ca215a6SBrian Somers { -1, NULL } 557ca215a6SBrian Somers }; 567ca215a6SBrian Somers 577ca215a6SBrian Somers static char digits[] = "0123456789"; 589263db41SBrian Somers static int adjhour(struct tm *, char, int, int); 59a625bfecSBrian Somers 60a625bfecSBrian Somers static int 61a625bfecSBrian Somers domktime(struct tm *t, char type) 62a625bfecSBrian Somers { 639263db41SBrian Somers time_t ret; 64a625bfecSBrian Somers 659263db41SBrian Somers while ((ret = mktime(t)) == -1 && t->tm_year > 68 && t->tm_year < 138) 669263db41SBrian Somers /* While mktime() fails, adjust by an hour */ 679263db41SBrian Somers adjhour(t, type == '-' ? type : '+', 1, 0); 68a625bfecSBrian Somers 69a625bfecSBrian Somers return ret; 70a625bfecSBrian Somers } 717ca215a6SBrian Somers 727ca215a6SBrian Somers static int 737ca215a6SBrian Somers trans(const struct trans t[], const char *arg) 747ca215a6SBrian Somers { 757ca215a6SBrian Somers int f; 767ca215a6SBrian Somers 777ca215a6SBrian Somers for (f = 0; t[f].val != -1; f++) 78698f86e4SBrian Somers if (!strncasecmp(t[f].str, arg, 3) || 79698f86e4SBrian Somers !strncasecmp(t[f].str, arg, strlen(t[f].str))) 807ca215a6SBrian Somers return t[f].val; 817ca215a6SBrian Somers 827ca215a6SBrian Somers return -1; 837ca215a6SBrian Somers } 847ca215a6SBrian Somers 857ca215a6SBrian Somers struct vary * 86698f86e4SBrian Somers vary_append(struct vary *v, char *arg) 877ca215a6SBrian Somers { 887ca215a6SBrian Somers struct vary *result, **nextp; 897ca215a6SBrian Somers 907ca215a6SBrian Somers if (v) { 917ca215a6SBrian Somers result = v; 927ca215a6SBrian Somers while (v->next) 937ca215a6SBrian Somers v = v->next; 947ca215a6SBrian Somers nextp = &v->next; 957ca215a6SBrian Somers } else 967ca215a6SBrian Somers nextp = &result; 977ca215a6SBrian Somers 986e4cd31dSBrian Somers if ((*nextp = (struct vary *)malloc(sizeof(struct vary))) == NULL) 996e4cd31dSBrian Somers err(1, "malloc"); 1007ca215a6SBrian Somers (*nextp)->arg = arg; 1017ca215a6SBrian Somers (*nextp)->next = NULL; 1027ca215a6SBrian Somers return result; 1037ca215a6SBrian Somers } 1047ca215a6SBrian Somers 1057ca215a6SBrian Somers static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 1067ca215a6SBrian Somers 1077ca215a6SBrian Somers static int 1087ca215a6SBrian Somers daysinmonth(const struct tm *t) 1097ca215a6SBrian Somers { 1107ca215a6SBrian Somers int year; 1117ca215a6SBrian Somers 1127ca215a6SBrian Somers year = t->tm_year + 1900; 1137ca215a6SBrian Somers 1147ca215a6SBrian Somers if (t->tm_mon == 1) 1157ca215a6SBrian Somers if (!(year % 400)) 1167ca215a6SBrian Somers return 29; 1177ca215a6SBrian Somers else if (!(year % 100)) 1187ca215a6SBrian Somers return 28; 1197ca215a6SBrian Somers else if (!(year % 4)) 1207ca215a6SBrian Somers return 29; 1217ca215a6SBrian Somers else 1227ca215a6SBrian Somers return 28; 1237ca215a6SBrian Somers else if (t->tm_mon >= 0 && t->tm_mon < 12) 1247ca215a6SBrian Somers return mdays[t->tm_mon]; 1257ca215a6SBrian Somers 1267ca215a6SBrian Somers return 0; 1277ca215a6SBrian Somers } 1287ca215a6SBrian Somers 1297ca215a6SBrian Somers 1307ca215a6SBrian Somers static int 1319263db41SBrian Somers adjyear(struct tm *t, char type, int val, int mk) 1327ca215a6SBrian Somers { 1337ca215a6SBrian Somers switch (type) { 1347ca215a6SBrian Somers case '+': 1357ca215a6SBrian Somers t->tm_year += val; 1367ca215a6SBrian Somers break; 1377ca215a6SBrian Somers case '-': 1387ca215a6SBrian Somers t->tm_year -= val; 1397ca215a6SBrian Somers break; 1407ca215a6SBrian Somers default: 1417ca215a6SBrian Somers t->tm_year = val; 1427ca215a6SBrian Somers if (t->tm_year < 69) 1437ca215a6SBrian Somers t->tm_year += 100; /* as per date.c */ 1447ca215a6SBrian Somers else if (t->tm_year > 1900) 1457ca215a6SBrian Somers t->tm_year -= 1900; /* struct tm holds years since 1900 */ 1467ca215a6SBrian Somers break; 1477ca215a6SBrian Somers } 1489263db41SBrian Somers return !mk || domktime(t, type) != -1; 1497ca215a6SBrian Somers } 1507ca215a6SBrian Somers 1517ca215a6SBrian Somers static int 1529263db41SBrian Somers adjmon(struct tm *t, char type, int val, int istext, int mk) 1537ca215a6SBrian Somers { 1547ca215a6SBrian Somers if (val < 0) 1557ca215a6SBrian Somers return 0; 1567ca215a6SBrian Somers 1577ca215a6SBrian Somers switch (type) { 1587ca215a6SBrian Somers case '+': 159426e9c1dSWarner Losh if (istext) { 1607ca215a6SBrian Somers if (val <= t->tm_mon) 1617ca215a6SBrian Somers val += 11 - t->tm_mon; /* early next year */ 1627ca215a6SBrian Somers else 1637ca215a6SBrian Somers val -= t->tm_mon + 1; /* later this year */ 164426e9c1dSWarner Losh } 165a625bfecSBrian Somers if (val) { 1669263db41SBrian Somers if (!adjyear(t, '+', (t->tm_mon + val) / 12, 0)) 1677ca215a6SBrian Somers return 0; 1687ca215a6SBrian Somers val %= 12; 1697ca215a6SBrian Somers t->tm_mon += val; 1707ca215a6SBrian Somers if (t->tm_mon > 11) 1717ca215a6SBrian Somers t->tm_mon -= 12; 172a625bfecSBrian Somers } 1737ca215a6SBrian Somers break; 1747ca215a6SBrian Somers 1757ca215a6SBrian Somers case '-': 176426e9c1dSWarner Losh if (istext) { 1777ca215a6SBrian Somers if (val-1 > t->tm_mon) 1787ca215a6SBrian Somers val = 13 - val + t->tm_mon; /* later last year */ 1797ca215a6SBrian Somers else 1807ca215a6SBrian Somers val = t->tm_mon - val + 1; /* early this year */ 181426e9c1dSWarner Losh } 182a625bfecSBrian Somers if (val) { 1839263db41SBrian Somers if (!adjyear(t, '-', val / 12, 0)) 1847ca215a6SBrian Somers return 0; 1857ca215a6SBrian Somers val %= 12; 1867ca215a6SBrian Somers if (val > t->tm_mon) { 1879263db41SBrian Somers if (!adjyear(t, '-', 1, 0)) 1887ca215a6SBrian Somers return 0; 1897ca215a6SBrian Somers val -= 12; 1907ca215a6SBrian Somers } 1917ca215a6SBrian Somers t->tm_mon -= val; 192a625bfecSBrian Somers } 1937ca215a6SBrian Somers break; 1947ca215a6SBrian Somers 1957ca215a6SBrian Somers default: 1967ca215a6SBrian Somers if (val > 12 || val < 1) 1977ca215a6SBrian Somers return 0; 1987ca215a6SBrian Somers t->tm_mon = --val; 1997ca215a6SBrian Somers } 2007ca215a6SBrian Somers 2019263db41SBrian Somers return !mk || domktime(t, type) != -1; 2027ca215a6SBrian Somers } 2037ca215a6SBrian Somers 2047ca215a6SBrian Somers static int 2059263db41SBrian Somers adjday(struct tm *t, char type, int val, int mk) 2067ca215a6SBrian Somers { 2079afa09cdSMark Murray int lmdays; 208a625bfecSBrian Somers 2097ca215a6SBrian Somers switch (type) { 2107ca215a6SBrian Somers case '+': 2117ca215a6SBrian Somers while (val) { 2129afa09cdSMark Murray lmdays = daysinmonth(t); 2139afa09cdSMark Murray if (val > lmdays - t->tm_mday) { 2149afa09cdSMark Murray val -= lmdays - t->tm_mday + 1; 2157ca215a6SBrian Somers t->tm_mday = 1; 2169263db41SBrian Somers if (!adjmon(t, '+', 1, 0, 0)) 2177ca215a6SBrian Somers return 0; 2187ca215a6SBrian Somers } else { 2197ca215a6SBrian Somers t->tm_mday += val; 2207ca215a6SBrian Somers val = 0; 2217ca215a6SBrian Somers } 2227ca215a6SBrian Somers } 2237ca215a6SBrian Somers break; 2247ca215a6SBrian Somers case '-': 2257ca215a6SBrian Somers while (val) 2267ca215a6SBrian Somers if (val >= t->tm_mday) { 2277ca215a6SBrian Somers val -= t->tm_mday; 2287ca215a6SBrian Somers t->tm_mday = 1; 2299263db41SBrian Somers if (!adjmon(t, '-', 1, 0, 0)) 2307ca215a6SBrian Somers return 0; 2317ca215a6SBrian Somers t->tm_mday = daysinmonth(t); 2327ca215a6SBrian Somers } else { 2337ca215a6SBrian Somers t->tm_mday -= val; 2347ca215a6SBrian Somers val = 0; 2357ca215a6SBrian Somers } 2367ca215a6SBrian Somers break; 2377ca215a6SBrian Somers default: 2387ca215a6SBrian Somers if (val > 0 && val <= daysinmonth(t)) 2397ca215a6SBrian Somers t->tm_mday = val; 2407ca215a6SBrian Somers else 2417ca215a6SBrian Somers return 0; 2427ca215a6SBrian Somers break; 2437ca215a6SBrian Somers } 2447ca215a6SBrian Somers 2459263db41SBrian Somers return !mk || domktime(t, type) != -1; 2467ca215a6SBrian Somers } 2477ca215a6SBrian Somers 2487ca215a6SBrian Somers static int 2499263db41SBrian Somers adjwday(struct tm *t, char type, int val, int istext, int mk) 2507ca215a6SBrian Somers { 2517ca215a6SBrian Somers if (val < 0) 2527ca215a6SBrian Somers return 0; 2537ca215a6SBrian Somers 254698f86e4SBrian Somers switch (type) { 2557ca215a6SBrian Somers case '+': 2567ca215a6SBrian Somers if (istext) 2577ca215a6SBrian Somers if (val < t->tm_wday) 2587ca215a6SBrian Somers val = 7 - t->tm_wday + val; /* early next week */ 2597ca215a6SBrian Somers else 2607ca215a6SBrian Somers val -= t->tm_wday; /* later this week */ 2617ca215a6SBrian Somers else 262a625bfecSBrian Somers val *= 7; /* "-v+5w" == "5 weeks in the future" */ 2637ecff35bSBrian Somers return !val || adjday(t, '+', val, mk); 2647ca215a6SBrian Somers case '-': 265a625bfecSBrian Somers if (istext) { 2667ca215a6SBrian Somers if (val > t->tm_wday) 2677ca215a6SBrian Somers val = 7 - val + t->tm_wday; /* later last week */ 2687ca215a6SBrian Somers else 2697ca215a6SBrian Somers val = t->tm_wday - val; /* early this week */ 270a625bfecSBrian Somers } else 271a625bfecSBrian Somers val *= 7; /* "-v-5w" == "5 weeks ago" */ 2727ecff35bSBrian Somers return !val || adjday(t, '-', val, mk); 2737ca215a6SBrian Somers default: 2747ca215a6SBrian Somers if (val < t->tm_wday) 2757ecff35bSBrian Somers return adjday(t, '-', t->tm_wday - val, mk); 2767ca215a6SBrian Somers else if (val > 6) 2777ca215a6SBrian Somers return 0; 2787ca215a6SBrian Somers else if (val > t->tm_wday) 2797ecff35bSBrian Somers return adjday(t, '+', val - t->tm_wday, mk); 2807ca215a6SBrian Somers } 2817ca215a6SBrian Somers return 1; 2827ca215a6SBrian Somers } 2837ca215a6SBrian Somers 2847ca215a6SBrian Somers static int 2859263db41SBrian Somers adjhour(struct tm *t, char type, int val, int mk) 2867ca215a6SBrian Somers { 287698f86e4SBrian Somers if (val < 0) 288698f86e4SBrian Somers return 0; 289698f86e4SBrian Somers 290698f86e4SBrian Somers switch (type) { 2917ca215a6SBrian Somers case '+': 292a625bfecSBrian Somers if (val) { 293a625bfecSBrian Somers int days; 294a625bfecSBrian Somers 295a625bfecSBrian Somers days = (t->tm_hour + val) / 24; 296698f86e4SBrian Somers val %= 24; 297698f86e4SBrian Somers t->tm_hour += val; 298a625bfecSBrian Somers t->tm_hour %= 24; 2999263db41SBrian Somers if (!adjday(t, '+', days, 0)) 300a625bfecSBrian Somers return 0; 301a625bfecSBrian Somers } 302698f86e4SBrian Somers break; 303698f86e4SBrian Somers 3047ca215a6SBrian Somers case '-': 305a625bfecSBrian Somers if (val) { 306a625bfecSBrian Somers int days; 307a625bfecSBrian Somers 308a625bfecSBrian Somers days = val / 24; 309698f86e4SBrian Somers val %= 24; 310698f86e4SBrian Somers if (val > t->tm_hour) { 311a625bfecSBrian Somers days++; 312698f86e4SBrian Somers val -= 24; 3137ca215a6SBrian Somers } 314698f86e4SBrian Somers t->tm_hour -= val; 3159263db41SBrian Somers if (!adjday(t, '-', days, 0)) 316a625bfecSBrian Somers return 0; 317a625bfecSBrian Somers } 318698f86e4SBrian Somers break; 319698f86e4SBrian Somers 320698f86e4SBrian Somers default: 321698f86e4SBrian Somers if (val > 23) 322698f86e4SBrian Somers return 0; 323698f86e4SBrian Somers t->tm_hour = val; 324698f86e4SBrian Somers } 325698f86e4SBrian Somers 3269263db41SBrian Somers return !mk || domktime(t, type) != -1; 327698f86e4SBrian Somers } 328698f86e4SBrian Somers 329698f86e4SBrian Somers static int 3309263db41SBrian Somers adjmin(struct tm *t, char type, int val, int mk) 331698f86e4SBrian Somers { 332698f86e4SBrian Somers if (val < 0) 333698f86e4SBrian Somers return 0; 334698f86e4SBrian Somers 335698f86e4SBrian Somers switch (type) { 336698f86e4SBrian Somers case '+': 337a625bfecSBrian Somers if (val) { 3389263db41SBrian Somers if (!adjhour(t, '+', (t->tm_min + val) / 60, 0)) 339698f86e4SBrian Somers return 0; 340698f86e4SBrian Somers val %= 60; 341698f86e4SBrian Somers t->tm_min += val; 342698f86e4SBrian Somers if (t->tm_min > 59) 343698f86e4SBrian Somers t->tm_min -= 60; 344a625bfecSBrian Somers } 345698f86e4SBrian Somers break; 346698f86e4SBrian Somers 347698f86e4SBrian Somers case '-': 348a625bfecSBrian Somers if (val) { 3499263db41SBrian Somers if (!adjhour(t, '-', val / 60, 0)) 350698f86e4SBrian Somers return 0; 351698f86e4SBrian Somers val %= 60; 352698f86e4SBrian Somers if (val > t->tm_min) { 3539263db41SBrian Somers if (!adjhour(t, '-', 1, 0)) 354698f86e4SBrian Somers return 0; 355698f86e4SBrian Somers val -= 60; 356698f86e4SBrian Somers } 357698f86e4SBrian Somers t->tm_min -= val; 358a625bfecSBrian Somers } 359698f86e4SBrian Somers break; 360698f86e4SBrian Somers 361698f86e4SBrian Somers default: 362698f86e4SBrian Somers if (val > 59) 363698f86e4SBrian Somers return 0; 364698f86e4SBrian Somers t->tm_min = val; 365698f86e4SBrian Somers } 366698f86e4SBrian Somers 3679263db41SBrian Somers return !mk || domktime(t, type) != -1; 3687ca215a6SBrian Somers } 3697ca215a6SBrian Somers 370269dfbeeSBrian Somers static int 3719263db41SBrian Somers adjsec(struct tm *t, char type, int val, int mk) 372269dfbeeSBrian Somers { 373269dfbeeSBrian Somers if (val < 0) 374269dfbeeSBrian Somers return 0; 375269dfbeeSBrian Somers 376269dfbeeSBrian Somers switch (type) { 377269dfbeeSBrian Somers case '+': 378a625bfecSBrian Somers if (val) { 3799263db41SBrian Somers if (!adjmin(t, '+', (t->tm_sec + val) / 60, 0)) 380269dfbeeSBrian Somers return 0; 381269dfbeeSBrian Somers val %= 60; 382269dfbeeSBrian Somers t->tm_sec += val; 383269dfbeeSBrian Somers if (t->tm_sec > 59) 384269dfbeeSBrian Somers t->tm_sec -= 60; 385a625bfecSBrian Somers } 386269dfbeeSBrian Somers break; 387269dfbeeSBrian Somers 388269dfbeeSBrian Somers case '-': 389a625bfecSBrian Somers if (val) { 3909263db41SBrian Somers if (!adjmin(t, '-', val / 60, 0)) 391269dfbeeSBrian Somers return 0; 392269dfbeeSBrian Somers val %= 60; 393269dfbeeSBrian Somers if (val > t->tm_sec) { 3949263db41SBrian Somers if (!adjmin(t, '-', 1, 0)) 395269dfbeeSBrian Somers return 0; 396269dfbeeSBrian Somers val -= 60; 397269dfbeeSBrian Somers } 398269dfbeeSBrian Somers t->tm_sec -= val; 399a625bfecSBrian Somers } 400269dfbeeSBrian Somers break; 401269dfbeeSBrian Somers 402269dfbeeSBrian Somers default: 403269dfbeeSBrian Somers if (val > 59) 404269dfbeeSBrian Somers return 0; 405269dfbeeSBrian Somers t->tm_sec = val; 406269dfbeeSBrian Somers } 407269dfbeeSBrian Somers 4089263db41SBrian Somers return !mk || domktime(t, type) != -1; 409269dfbeeSBrian Somers } 410269dfbeeSBrian Somers 4117ca215a6SBrian Somers const struct vary * 4127ca215a6SBrian Somers vary_apply(const struct vary *v, struct tm *t) 4137ca215a6SBrian Somers { 414698f86e4SBrian Somers char type; 415698f86e4SBrian Somers char which; 416698f86e4SBrian Somers char *arg; 4179afa09cdSMark Murray size_t len; 418698f86e4SBrian Somers int val; 419698f86e4SBrian Somers 4207ca215a6SBrian Somers for (; v; v = v->next) { 421698f86e4SBrian Somers type = *v->arg; 422698f86e4SBrian Somers arg = v->arg; 423698f86e4SBrian Somers if (type == '+' || type == '-') 424698f86e4SBrian Somers arg++; 425698f86e4SBrian Somers else 426698f86e4SBrian Somers type = '\0'; 427698f86e4SBrian Somers len = strlen(arg); 428698f86e4SBrian Somers if (len < 2) 4297ca215a6SBrian Somers return v; 430698f86e4SBrian Somers 4319263db41SBrian Somers if (type == '\0') 4329263db41SBrian Somers t->tm_isdst = -1; 4339263db41SBrian Somers 434698f86e4SBrian Somers if (strspn(arg, digits) != len-1) { 435698f86e4SBrian Somers val = trans(trans_wday, arg); 436698f86e4SBrian Somers if (val != -1) { 4379263db41SBrian Somers if (!adjwday(t, type, val, 1, 1)) 4387ca215a6SBrian Somers return v; 439698f86e4SBrian Somers } else { 440698f86e4SBrian Somers val = trans(trans_mon, arg); 441698f86e4SBrian Somers if (val != -1) { 4429263db41SBrian Somers if (!adjmon(t, type, val, 1, 1)) 443698f86e4SBrian Somers return v; 444698f86e4SBrian Somers } else 445698f86e4SBrian Somers return v; 446698f86e4SBrian Somers } 447698f86e4SBrian Somers } else { 448698f86e4SBrian Somers val = atoi(arg); 449698f86e4SBrian Somers which = arg[len-1]; 450698f86e4SBrian Somers 451698f86e4SBrian Somers switch (which) { 452269dfbeeSBrian Somers case 'S': 4539263db41SBrian Somers if (!adjsec(t, type, val, 1)) 454269dfbeeSBrian Somers return v; 455269dfbeeSBrian Somers break; 4567ca215a6SBrian Somers case 'M': 4579263db41SBrian Somers if (!adjmin(t, type, val, 1)) 4587ca215a6SBrian Somers return v; 4597ca215a6SBrian Somers break; 460698f86e4SBrian Somers case 'H': 4619263db41SBrian Somers if (!adjhour(t, type, val, 1)) 462698f86e4SBrian Somers return v; 463698f86e4SBrian Somers break; 464698f86e4SBrian Somers case 'd': 4659263db41SBrian Somers t->tm_isdst = -1; 4669263db41SBrian Somers if (!adjday(t, type, val, 1)) 467698f86e4SBrian Somers return v; 468698f86e4SBrian Somers break; 469698f86e4SBrian Somers case 'w': 4709263db41SBrian Somers t->tm_isdst = -1; 4719263db41SBrian Somers if (!adjwday(t, type, val, 0, 1)) 472698f86e4SBrian Somers return v; 473698f86e4SBrian Somers break; 474698f86e4SBrian Somers case 'm': 4759263db41SBrian Somers t->tm_isdst = -1; 4769263db41SBrian Somers if (!adjmon(t, type, val, 0, 1)) 477698f86e4SBrian Somers return v; 478698f86e4SBrian Somers break; 479698f86e4SBrian Somers case 'y': 4809263db41SBrian Somers t->tm_isdst = -1; 4819263db41SBrian Somers if (!adjyear(t, type, val, 1)) 4827ca215a6SBrian Somers return v; 4837ca215a6SBrian Somers break; 4847ca215a6SBrian Somers default: 4857ca215a6SBrian Somers return v; 4867ca215a6SBrian Somers } 4877ca215a6SBrian Somers } 488698f86e4SBrian Somers } 4897ca215a6SBrian Somers return 0; 4907ca215a6SBrian Somers } 4917ca215a6SBrian Somers 4927ca215a6SBrian Somers void 4937ca215a6SBrian Somers vary_destroy(struct vary *v) 4947ca215a6SBrian Somers { 4957ca215a6SBrian Somers struct vary *n; 4967ca215a6SBrian Somers 4977ca215a6SBrian Somers while (v) { 4987ca215a6SBrian Somers n = v->next; 4997ca215a6SBrian Somers free(v); 5007ca215a6SBrian Somers v = n; 5017ca215a6SBrian Somers } 5027ca215a6SBrian Somers } 503