X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=snooze.c;h=9a3381a06144667379d2ab2c208fa478ff16dcfb;hb=1b13bb82c9a732cd9d7216e74dab45e782c4f207;hp=a5df96767c541106a85deec9494c062ca0dd691a;hpb=a99b4704518369ebf6606b6a1a271c5cfd21bd5e;p=user%2Fhenk%2Fcode%2Fsnooze.git diff --git a/snooze.c b/snooze.c index a5df967..9a3381a 100644 --- a/snooze.c +++ b/snooze.c @@ -1,16 +1,11 @@ /* * snooze - run a command at a particular time * - * To the extent possible under law, - * Christian Neukirchen + * To the extent possible under law, Leah Neukirchen * has waived all copyright and related or neighboring rights to this work. * http://creativecommons.org/publicdomain/zero/1.0/ */ -/* -##% gcc -Os -Wall -g -o $STEM $FILE -Wextra -Wwrite-strings -*/ - #include #include @@ -64,6 +59,34 @@ parse_int(char **s, size_t minn, size_t maxn) return n; } +static long +parse_dur(char *s) +{ + long n; + char *end; + + errno = 0; + n = strtol(s, &end, 10); + if (errno) { + perror("strtol"); + exit(1); + } + if (n < 0) { + fprintf(stderr, "negative duration\n"); + exit(1); + } + switch (*end) { + case 'm': n *= 60; break; + case 'h': n *= 60*60; break; + case 'd': n *= 24*60*60; break; + case 0: break; + default: + fprintf(stderr, "junk after duration: %s\n", end); + exit(1); + } + return n; +} + static int parse(char *expr, char *buf, long bufsiz, int offset) { @@ -90,7 +113,8 @@ parse(char *expr, char *buf, long bufsiz, int offset) case '/': s++; n0 = n; - n = parse_int(&s, -offset, bufsiz); + if (*s) + n = parse_int(&s, -offset, bufsiz); if (n == 0) // / = * n = 1; for (i = n0; i < bufsiz; i += n) @@ -119,7 +143,7 @@ char weekday[8] = {0}; char dayofmonth[31] = {0}; char month[12] = {0}; char dayofyear[366] = {0}; -char weekofyear[53] = {0}; +char weekofyear[54] = {0}; char hour[24] = {0}; char minute[60] = {0}; char second[61] = {0}; @@ -162,7 +186,7 @@ next_day: tm->tm_hour = 0; t = mktime(tm); - if (t > from+(365*24*60*60)) // no result within a year + if (t > from+(366*24*60*60)) // no result within a year return -1; } @@ -202,6 +226,7 @@ int main(int argc, char *argv[]) int c; time_t t; time_t now = time(0); + time_t last = 0; /* default: every day at 00:00:00 */ memset(weekday, '*', sizeof weekday); @@ -213,7 +238,7 @@ int main(int argc, char *argv[]) minute[0] = '*'; second[0] = '*'; - while ((c = getopt(argc, argv, "D:W:H:M:S:T:R:d:m:ns:t:vw:")) != -1) + while ((c = getopt(argc, argv, "+D:W:H:M:S:T:R:d:m:ns:t:vw:")) != -1) switch(c) { case 'D': parse(optarg, dayofyear, sizeof dayofyear, -1); break; case 'W': parse(optarg, weekofyear, sizeof weekofyear, -1); break; @@ -229,10 +254,10 @@ int main(int argc, char *argv[]) break; case 'n': nflag++; break; case 'v': vflag++; break; - case 's': slack = atoi(optarg); break; - case 'T': timewait = atoi(optarg); break; + case 's': slack = parse_dur(optarg); break; + case 'T': timewait = parse_dur(optarg); break; case 't': timefile = optarg; break; - case 'R': randdelay = atoi(optarg); break; + case 'R': randdelay = parse_dur(optarg); break; default: fprintf(stderr, "Usage: %s [-nv] [-t timefile] [-T timewait] [-R randdelay] [-s slack]\n" " [-d mday] [-m mon] [-w wday] [-D yday] [-W yweek] [-H hour] [-M min] [-S sec] COMMAND...\n" @@ -251,7 +276,7 @@ int main(int argc, char *argv[]) perror("stat"); t = start - slack - 1 - timewait; } else { - t = st.st_mtime; + t = st.st_mtime + 1; } if (timewait == -1) { while (t < start - slack) @@ -290,9 +315,22 @@ int main(int argc, char *argv[]) /* dry-run, just output the next 5 dates. */ int i; for (i = 0; i < 5; i++) { - if (t > 0) - printf("%s\n", isotime(localtime(&t))); + char weekstr[4]; + struct tm *tm = localtime(&t); + strftime(weekstr, sizeof weekstr, "%a", tm); + printf("%s %s %2ldd%3ldh%3ldm%3lds\n", + isotime(tm), + weekstr, + ((t - now) / (60*60*24)), + ((t - now) / (60*60)) % 24, + ((t - now) / 60) % 60, + (t - now) % 60); t = find_next(t + 1); + if (t < 0) { + fprintf(stderr, + "no satisfying date found within a year.\n"); + exit(2); + } } exit(0); } @@ -310,6 +348,11 @@ int main(int argc, char *argv[]) while (!alarm_rang) { now = time(0); + if (now < last) { + t = find_next(now); + if (vflag) + printf("Time moved backwards, rescheduled for %s\n", isotime(tm)); + } t = mktime(tm); if (t <= now) { if (now - t <= slack) // still about time @@ -327,6 +370,7 @@ int main(int argc, char *argv[]) struct timespec ts; ts.tv_nsec = 0; ts.tv_sec = t - now > SLEEP_PHASE ? SLEEP_PHASE : t - now; + last = now; nanosleep(&ts, 0); // we just iterate again when this exits early }