diff options
author | Mattias Andrée <maandree@kth.se> | 2021-02-07 00:24:39 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2021-02-07 00:24:39 +0100 |
commit | 68dd947b82c6508cb72558130759c9eb2480f1eb (patch) | |
tree | 519b32f07c9f46d48849acb88c6687ecb28db12b | |
parent | Add posix time support (diff) | |
download | mongotimer-68dd947b82c6508cb72558130759c9eb2480f1eb.tar.gz mongotimer-68dd947b82c6508cb72558130759c9eb2480f1eb.tar.bz2 mongotimer-68dd947b82c6508cb72558130759c9eb2480f1eb.tar.xz |
Fork mongoclock and turn into a timer and stopwatch
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 33 | ||||
-rw-r--r-- | README | 39 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rwxr-xr-x | digit.sh | 22 | ||||
-rw-r--r-- | mongoclock.1 | 52 | ||||
-rw-r--r-- | mongoclock.c | 290 | ||||
-rw-r--r-- | mongotimer.1 | 46 | ||||
-rw-r--r-- | mongotimer.c | 342 |
9 files changed, 443 insertions, 385 deletions
@@ -4,4 +4,4 @@ *.out *.su mongo_*.h -/mongoclock +/mongotimer @@ -6,15 +6,15 @@ include $(CONFIGFILE) DIGITS =\ mongo_0.h mongo_1.h mongo_2.h mongo_3.h mongo_4.h \ mongo_5.h mongo_6.h mongo_7.h mongo_8.h mongo_9.h \ - mongo_c.h + mongo_c.h mongo_m.h -all: mongoclock +all: mongotimer -mongoclock: mongoclock.o - $(CC) -o $@ $^ $(LDFLAGS) +mongotimer: mongotimer.o + $(CC) -o $@ mongotimer.o $(LDFLAGS) -mongoclock.o: mongoclock.c arg.h $(DIGITS) - $(CC) -c -o $@ mongoclock.c $(CPPFLAGS) $(CFLAGS) +mongotimer.o: mongotimer.c arg.h $(DIGITS) + $(CC) -c -o $@ mongotimer.c $(CPPFLAGS) $(CFLAGS) mongo_0.h: digit.sh ./digit.sh 0 > $@ @@ -49,20 +49,23 @@ mongo_9.h: digit.sh mongo_c.h: digit.sh ./digit.sh c > $@ -install: mongoclock +mongo_m.h: digit.sh + ./digit.sh m > $@ + +install: mongotimer mkdir -p -- "$(DESTDIR)$(PREFIX)/bin" - mkdir -p -- "$(DESTDIR)$(PREFIX)/share/licenses/mongoclock" + mkdir -p -- "$(DESTDIR)$(PREFIX)/share/licenses/mongotimer" mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1" - cp -- mongoclock "$(DESTDIR)$(PREFIX)/bin/" - cp -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/mongoclock/" - cp -- mongoclock.1 "$(DESTDIR)$(MANPREFIX)/man1/" + cp -- mongotimer "$(DESTDIR)$(PREFIX)/bin/" + cp -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/mongotimer/" + cp -- mongotimer.1 "$(DESTDIR)$(MANPREFIX)/man1/" uninstall: - -rm -- "$(DESTDIR)$(PREFIX)/bin/mongoclock" - -rm -- "$(DESTDIR)$(MANPREFIX)/man1/mongoclock.1" - -rm -r -- "$(DESTDIR)$(PREFIX)/share/licenses/mongoclock" + -rm -- "$(DESTDIR)$(PREFIX)/bin/mongotimer" + -rm -- "$(DESTDIR)$(MANPREFIX)/man1/mongotimer.1" + -rm -r -- "$(DESTDIR)$(PREFIX)/share/licenses/mongotimer" clean: - -rm -f -- *.o mongoclock mongo_*.h + -rm -f -- *.o mongotimer mongo_*.h .PHONY: all install uninstall clean @@ -1,17 +1,20 @@ NAME - mongoclock - Just a humongous clock for the terminal + mongotimer - A humongous timer or stopwatch for the terminal SYNOPSIS - mongoclock + mongotimer [[-e] [[hh:]mm:]ss] DESCRIPTION - Type mongoclock in the terminal and it will either, - depending on the terminal size, show the time HH:MM - or HH:MM:SS with humongous digits. + mongotimer will, if no arguments are specified, + simply display time since it started. If a time + is specified, it will count down from that time. - If the terminal is too small, it will not run. + Pressing space will pause the timer/stopwatch, + and the time be displayed in yellow will + paused. Pressing space again will unpause the + timer/stopwatch. - mongoclock is designed to be fit on most screens + mongotimer is designed to be fit on most screens and be readable from all practical distances, so that it can be used in place of a standard wall- or alarm-clock. If the font is not big enough for @@ -22,26 +25,14 @@ DESCRIPTION OPTIONS The mongoclock utility shall conform to the Base - Definitions volume of POSIX.1‐2008, Section 12.2, + Definitions volume of POSIX.1-2008, Section 12.2, Utility Syntax Guidelines. The following options shall be supported: - -s Display the posix time (seconds since - 1970-01-01 00:00:00 UTC, ignoring inserted - and removed leap seconds). - -RATIONALE - It is really nice to have a large clock on your - computer, instead of a small clock somewhere in - your room, when your are sleeping. It is also - nice to have a glansable clock available on your - netbook for when you need to keep track of the - time but are not working on a computer. - Pocket-watches are just too much work to getting - up, opening, closing, and putting down, and you - would not like to forget it when you leave if - you are in a public place. + -e Exit with status 0 when the timer reaches 0. + If not specified, the timer will continue + into negative times but with a red font. SEE ALSO - watch(1) + mongoclock(1), watch(1) @@ -2,5 +2,5 @@ PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man CFLAGS = -std=c99 -Wall -Wextra -O2 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -DUSE_ADJTIMEX +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 LDFLAGS = -s @@ -176,6 +176,22 @@ mongo_c() { ' ' } +mongo_m() { + printf '%s\n' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' [XXXXXXXXXX] ' \ + ' [XXXXXXXXXX] ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' +} + digit() { if test "$1" = 0; then mongo_0 @@ -197,14 +213,16 @@ digit() { mongo_8 elif test "$1" = 9; then mongo_9 - else + elif test "$1" = c; then mongo_c + else + mongo_m fi } printf 'static const char *mongo_%s[] = {\n' "$1" digit "$1" | \ - sed -e 's/X/ /g' -e 's/\[/\\033\[7m /g' -e 's/\]/\\033\[m /g' | \ + sed -e 's/X/ /g' -e 's/\[/\\033\[7m /g' -e 's/\]/\\033\[27m /g' | \ sed -e 's/^/"/' -e 's/$/",/' | \ sed '$s/,$//' printf '};\n' diff --git a/mongoclock.1 b/mongoclock.1 deleted file mode 100644 index 46131ff..0000000 --- a/mongoclock.1 +++ /dev/null @@ -1,52 +0,0 @@ -.TH MONGOCLOCK 1 MONGOCLOCK -.SH NAME -mongoclock - Just a humongous clock for the terminal -.SH SYNOPSIS -.BR mongoclock -.SH DESCRIPTION -Type -.BR mongoclock -in the terminal and it will either, depending on -the terminal size, show the time \fIHH:MM\fP or -\fIHH:MM:SS\fP with humongous digits. -.PP -If the terminal is too small, it will not run. -.PP -.BR mongoclock -is designed to be fit on most screens and be -readable from all practical distances, so that -it can be used in place of a standard wall- or -alarm-clock. If the font is not big enough for -your (or if it is too large,) just change the -font size on your terminal. If it is not the -right colour for you, simply change the font -colour on your terminal -.SH OPTIONS -The -.B cp -utility shall conform to the Base Definitions -volume of POSIX.1-2008, -.IR "Section 12.2, Utility Syntax Guidelines" . -.PP -The following options shall be supported: -.TP -.B -s -Display the posix time (seconds since 1970-01-01 -00:00:00 UTC, ignoring inserted and removed leap -seconds). -.SH RATIONALE -It is really nice to have a large clock on your -computer, instead of a small clock somewhere in -your room, when your are sleeping. It is also -nice to have a glansable clock available on your -netbook for when you need to keep track of the -time but are not working on a computer. -Pocket-watches are just too much work to getting -up, opening, closing, and putting down, and you -would not like to forget it when you leave if -you are in a public place. -.SH "SEE ALSO" -.BR watch (1) -.SH AUTHORS -Mattias Andrée -.RI < maandree@kth.se > diff --git a/mongoclock.c b/mongoclock.c deleted file mode 100644 index b98cc67..0000000 --- a/mongoclock.c +++ /dev/null @@ -1,290 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <sys/ioctl.h> -#include <sys/timerfd.h> -#include <errno.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#ifdef USE_ADJTIMEX -# include <sys/timex.h> -#endif - -#include "arg.h" - -#define DX 16 -#define DY 12 -#define DC 16 - -#include "mongo_0.h" -#include "mongo_1.h" -#include "mongo_2.h" -#include "mongo_3.h" -#include "mongo_4.h" -#include "mongo_5.h" -#include "mongo_6.h" -#include "mongo_7.h" -#include "mongo_8.h" -#include "mongo_9.h" -#include "mongo_c.h" - -static const char **mongo_ds[] = { - mongo_0, mongo_1, mongo_2, mongo_3, mongo_4, - mongo_5, mongo_6, mongo_7, mongo_8, mongo_9 -}; - -static volatile sig_atomic_t caught_sigterm = 0; -static volatile sig_atomic_t caught_sigwinch = 1; - -char *argv0; - -static void -usage(void) -{ - fprintf(stderr, "usage: %s\n", argv0); - exit(1); -} - -static void -sigterm(int signo) -{ - caught_sigterm = 1; - (void) signo; -} - -static void -sigwinch(int signo) -{ - caught_sigwinch = 1; - (void) signo; -} - -static void -print_time(const char ***str, size_t y, size_t x) -{ - size_t r, c; - - fprintf(stdout, "\033[%zu;1H\033[1J", y + 1); - - for (r = 0; r < DY; r++) { - fprintf(stdout, "\033[%zu;%zuH\033[1K", y + r + 1, x + 1); - for (c = 0; str[c]; c++) - fprintf(stdout, "%s", str[c][r]); - fprintf(stdout, "\033[0K"); - } - - fprintf(stdout, "\033[0J"); - fflush(stdout); -} - -static int -display_time(int timerfd) -{ - const char **digits[9]; - int small = 0; - uint64_t _overrun; - struct winsize winsize; - size_t x = 0, y = 0; - struct tm *now; -#ifdef USE_ADJTIMEX - struct timex timex; - int r; -#else - time_t now_; -#endif - -#ifdef USE_ADJTIMEX - memset(&timex, 0, sizeof(timex)); -#endif - - digits[8] = NULL; - - while (!caught_sigterm) { - if (caught_sigwinch) { - if (ioctl(STDOUT_FILENO, (unsigned long)TIOCGWINSZ, &winsize) < 0) { - if (errno == EINTR) - continue; - goto fail; - } - caught_sigwinch = 0; - y = winsize.ws_row; - x = winsize.ws_col; - if (y < DY) small = 2; - else if (x < 4 * DX + DC) small = 2; - else if (x < 6 * DX + 2 * DC) small = 1; - else small = 0; - y -= DY; - x -= 4 * DX + DC; - if (!small) - x -= 2 * DX + DC; - y /= 2; - x /= 2; - } - - if (small == 2) { - fprintf(stdout, "\033[H\033[2J%s\n", "Screen is too small"); - fflush(stdout); - pause(); - continue; - } - -#ifdef USE_ADJTIMEX - r = adjtimex(&timex); - if (r == -1) - goto fail; - now = localtime(&timex.time.tv_sec); - if (now == NULL) - goto fail; - if (r == TIME_OOP) - now->tm_sec += 1; -#else - now_ = time(NULL); - if (now_ == -1) - goto fail; - now = localtime(&now_); - if (now == NULL) - goto fail; -#endif - - digits[0] = mongo_ds[now->tm_hour / 10]; - digits[1] = mongo_ds[now->tm_hour % 10]; - digits[2] = mongo_c; - digits[3] = mongo_ds[now->tm_min / 10]; - digits[4] = mongo_ds[now->tm_min % 10]; - digits[5] = small ? NULL : mongo_c; - digits[6] = mongo_ds[now->tm_sec / 10]; - digits[7] = mongo_ds[now->tm_sec % 10]; - - print_time(digits, y, x); - - if (read(timerfd, &_overrun, sizeof(_overrun)) < 0) - if (errno != EINTR) - goto fail; - } - - return 0; - -fail: - return -1; -} - -static int -display_posixtime(int timerfd) -{ - const char **digits[21]; - uint64_t _overrun; - struct winsize winsize; - size_t w = 0, h = 0, x, y; - time_t now; - size_t first_digit, ndigits; - - digits[20] = NULL; - - while (!caught_sigterm) { - if (caught_sigwinch) { - if (ioctl(STDOUT_FILENO, (unsigned long)TIOCGWINSZ, &winsize) < 0) { - if (errno == EINTR) - continue; - goto fail; - } - caught_sigwinch = 0; - h = winsize.ws_row; - w = winsize.ws_col; - } - - now = time(NULL); - if (now < 0) - goto fail; - - first_digit = 20; - do { - if (!first_digit) - abort(); - digits[--first_digit] = mongo_ds[now % 10]; - } while (now /= 10); - ndigits = 20 - first_digit; - - if (h < DY || w < ndigits * DX) { - fprintf(stdout, "\033[H\033[2J%s\n", "Screen is too small"); - fflush(stdout); - pause(); - continue; - } - - y = (h - DY) / 2; - x = (w - ndigits * DX) / 2; - print_time(&digits[first_digit], y, x); - - if (read(timerfd, &_overrun, sizeof(_overrun)) < 0) - if (errno != EINTR) - goto fail; - } - - return 0; - -fail: - return -1; -} - -int -main(int argc, char *argv[]) -{ - int timerfd = -1; - int posixtime = 0; - struct itimerspec itimerspec; - struct sigaction sigact; - - ARGBEGIN { - case 's': - posixtime = 1; - break; - default: - usage(); - } ARGEND; - - if (argc) - usage(); - - fprintf(stdout, "\033[?1049h\033[?25l"); - - if (clock_gettime(CLOCK_REALTIME, &itimerspec.it_value)) - goto fail; - itimerspec.it_interval.tv_sec = 1; - itimerspec.it_interval.tv_nsec = 0; - itimerspec.it_value.tv_sec += 1; - itimerspec.it_value.tv_nsec = 0; - timerfd = timerfd_create(CLOCK_REALTIME, 0); - if (timerfd < 0) - goto fail; - if (timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &itimerspec, NULL)) - goto fail; - - memset(&sigact, 0, sizeof(sigact)); - - sigact.sa_handler = sigterm; - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGQUIT, &sigact, NULL); - sigaction(SIGINT, &sigact, NULL); - - sigact.sa_handler = sigwinch; - sigaction(SIGWINCH, &sigact, NULL); - - if (posixtime ? display_posixtime(timerfd) : display_time(timerfd)) - goto fail; - - fprintf(stdout, "\033[?25h\n\033[?1049l"); - fflush(stdout); - close(timerfd); - return 0; - -fail: - perror(argv0 ? argv0 : "mongoclock"); - fprintf(stdout, "\033[?25h\n\033[?1049l"); - fflush(stdout); - if (timerfd >= 0) - close(timerfd); - return 1; -} diff --git a/mongotimer.1 b/mongotimer.1 new file mode 100644 index 0000000..7067e68 --- /dev/null +++ b/mongotimer.1 @@ -0,0 +1,46 @@ +.TH MONGOTIMER 1 MONGOTIMER +.SH NAME +mongotimer - A humongous timer or stopwatch for the terminal +.SH SYNOPSIS +.BR mongotimer +[[-e] +.RI [[ hh\fB: ] mm\fB: ] ss ] +.SH DESCRIPTION +.B mongotimer +will, if no arguments are specified, simply +display time since it started. If a time is +specified, it will count down from that time. +.PP +Pressing space will pause the timer/stopwatch, +and the time be displayed in yellow will paused. +Pressing space again will unpause the +timer/stopwatch. +.PP +.B mongotimer +is designed to be fit on most screens and be +readable from all practical distances, so that +it can be used in place of a standard wall- or +alarm-clock. If the font is not big enough for +your (or if it is too large,) just change the +font size on your terminal. If it is not the +right colour for you, simply change the font +colour on your terminal +.SH OPTIONS +The +.B cp +utility shall conform to the Base Definitions +volume of POSIX.1-2008, +.IR "Section 12.2, Utility Syntax Guidelines" . +.PP +The following options shall be supported: +.TP +.B -e +Exit with status 0 when the timer reaches 0. +If not specified, the timer will continue +into negative times but with a red font. +.SH "SEE ALSO" +.BR mongoclock (1) +.BR watch (1) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/mongotimer.c b/mongotimer.c new file mode 100644 index 0000000..692d7a2 --- /dev/null +++ b/mongotimer.c @@ -0,0 +1,342 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/ioctl.h> +#include <sys/timerfd.h> +#include <errno.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "arg.h" + +#define DX 16 +#define DY 12 +#define DC 16 +#define DM 16 + +#include "mongo_0.h" +#include "mongo_1.h" +#include "mongo_2.h" +#include "mongo_3.h" +#include "mongo_4.h" +#include "mongo_5.h" +#include "mongo_6.h" +#include "mongo_7.h" +#include "mongo_8.h" +#include "mongo_9.h" +#include "mongo_c.h" +#include "mongo_m.h" + +static const char **mongo_ds[] = { + mongo_0, mongo_1, mongo_2, mongo_3, mongo_4, + mongo_5, mongo_6, mongo_7, mongo_8, mongo_9 +}; + +static volatile sig_atomic_t caught_sigterm = 0; +static volatile sig_atomic_t caught_sigwinch = 1; + +char *argv0; + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [[-e] [[hh]:mm:]ss]\n", argv0); + exit(1); +} + +static void +sigterm(int signo) +{ + caught_sigterm = 1; + (void) signo; +} + +static void +sigwinch(int signo) +{ + caught_sigwinch = 1; + (void) signo; +} + +static void +print_time(const char ***str, size_t y, size_t x) +{ + size_t r, c; + + fprintf(stdout, "\033[%zu;1H\033[1J", y + 1); + + for (r = 0; r < DY; r++) { + fprintf(stdout, "\033[%zu;%zuH\033[1K", y + r + 1, x + 1); + for (c = 0; str[c]; c++) + fprintf(stdout, "%s", str[c][r]); + fprintf(stdout, "\033[0K"); + } + + fprintf(stdout, "\033[0J"); + fflush(stdout); +} + +static int +display_stopwatch(int timerfd) +{ + uint64_t overrun, total_overrun = 0; + struct winsize winsize; + size_t x = 0, y = 0, width, i; + const char **digits[23]; + uint64_t h, m, s, h_div = 1, th; + size_t h_digits = 0; + int small = 0; + + /* TODO pause (yellow text) on <space> */ + + while (!caught_sigterm) { + if (caught_sigwinch) { + if (ioctl(STDOUT_FILENO, (unsigned long)TIOCGWINSZ, &winsize) < 0) { + if (errno == EINTR) + continue; + goto fail; + } + caught_sigwinch = 0; + recenter: + y = winsize.ws_row; + x = winsize.ws_col; + width = 4 * DX + DC; + if (h_digits) { + width += DC; + width += h_digits * DX; + } + if (y < DY) small = 1; + else if (x < width) small = 1; + else small = 0; + y -= DY; + x -= width; + y /= 2; + x /= 2; + } + + if (small) { + fprintf(stdout, "\033[H\033[2J%s\n", "Screen is too small"); + fflush(stdout); + pause(); + continue; + } + + s = total_overrun % 60; + m = total_overrun / 60 % 60; + h = total_overrun / 60 / 60; + if (h / h_div) { + h_div *= 10; + h_digits++; + goto recenter; + } + + i = 0; + if (h_digits) { + for (th = h; th; th /= 10) + digits[h_digits - ++i] = mongo_ds[th % 10]; + digits[i++] = mongo_c; + } + digits[i++] = mongo_ds[m / 10]; + digits[i++] = mongo_ds[m % 10]; + digits[i++] = mongo_c; + digits[i++] = mongo_ds[s / 10]; + digits[i++] = mongo_ds[s % 10]; + digits[i++] = NULL; + + print_time(digits, y, x); + + if (read(timerfd, &overrun, sizeof(overrun)) < 0) { + if (errno != EINTR) + goto fail; + } else { + total_overrun += overrun; + } + } + + return 0; + +fail: + return -1; +} + +static int +display_timer(int timerfd, int64_t time, int exit_on_zero) +{ + uint64_t overrun, abstime; + struct winsize winsize; + size_t x = 0, y = 0, width; + const char **digits[24]; + uint64_t h, m, s, th, h_div; + size_t h_digits, i; + int small = 0; + + /* TODO pause (yellow text) on <space> */ + + while (!caught_sigterm) { + if (caught_sigwinch) { + if (ioctl(STDOUT_FILENO, (unsigned long)TIOCGWINSZ, &winsize) < 0) { + if (errno == EINTR) + continue; + goto fail; + } + caught_sigwinch = 0; + } + + abstime = time < 0 ? (uint64_t)-time : (uint64_t)time; + s = abstime % 60; + m = abstime / 60 % 60; + h = abstime / 60 / 60; + + y = winsize.ws_row; + x = winsize.ws_col; + for (h_div = 1, h_digits = 0; h / h_div; h_div *= 10, h_digits += 1); + width = 4 * DX + DC; + if (time < 0) + width += DM; + if (h_digits) + width += h_digits * DX + DC; + if (y < DY) small = 1; + else if (x < width) small = 1; + else small = 0; + y -= DY; + x -= width; + y /= 2; + x /= 2; + + if (small) { + fprintf(stdout, "\033[H\033[2J%s\n", "Screen is too small"); + fflush(stdout); + pause(); + continue; + } + + i = 0; + if (time < 0) + digits[i++] = mongo_m; + if (h_digits) { + for (th = h; th; th /= 10) + digits[h_digits - ++i] = mongo_ds[th % 10]; + digits[i++] = mongo_c; + } + digits[i++] = mongo_ds[m / 10]; + digits[i++] = mongo_ds[m % 10]; + digits[i++] = mongo_c; + digits[i++] = mongo_ds[s / 10]; + digits[i++] = mongo_ds[s % 10]; + digits[i++] = NULL; + + if (time >= 0) { + print_time(digits, y, x); + } else { + fprintf(stdout, "\033[31m\n"); + print_time(digits, y, x); + fprintf(stdout, "\033[39m\n"); + } + + if (read(timerfd, &overrun, sizeof(overrun)) < 0) { + if (errno != EINTR) + goto fail; + } else { + time -= (int64_t)overrun; + if (time <= 0 && exit_on_zero) + break; + } + } + + if (caught_sigterm && exit_on_zero) + return -1; + + return 0; + +fail: + return -1; +} + +int +main(int argc, char *argv[]) +{ + int timerfd = -1; + int exit_on_zero = 0; + struct itimerspec itimerspec; + struct sigaction sigact; + int64_t time = 0, t = 0; + size_t colons = 0; + char *s; + + ARGBEGIN { + case 'e': + exit_on_zero = 1; + break; + default: + usage(); + } ARGEND; + + if (argc > 1 || (exit_on_zero && !argc)) + usage(); + + fprintf(stdout, "\033[?1049h\033[?25l"); + + itimerspec.it_interval.tv_sec = 1; + itimerspec.it_interval.tv_nsec = 0; + itimerspec.it_value.tv_sec = 1; + itimerspec.it_value.tv_nsec = 0; + timerfd = timerfd_create(CLOCK_BOOTTIME, 0); + if (timerfd < 0) + goto fail; + if (timerfd_settime(timerfd, 0, &itimerspec, NULL)) + goto fail; + + memset(&sigact, 0, sizeof(sigact)); + + sigact.sa_handler = sigterm; + sigaction(SIGTERM, &sigact, NULL); + sigaction(SIGQUIT, &sigact, NULL); + sigaction(SIGINT, &sigact, NULL); + + sigact.sa_handler = sigwinch; + sigaction(SIGWINCH, &sigact, NULL); + + if (argc) { + for (s = argv[0]; *s; s++) { + if ('0' <= *s && *s <= '9') { + t = t * 10 + (*s & 15); + } else if (*s == ':' && colons++ < 2) { + if (s == argv[0] || s[-1] == ':') + goto fail_usage; + time = (time + t) * 60; + t = 0; + } else { + goto fail_usage; + } + } + if (s == argv[0] || s[-1] == ':') + goto fail_usage; + time += t; + if (display_timer(timerfd, time, exit_on_zero)) + goto fail; + } else { + if (display_stopwatch(timerfd)) + goto fail; + } + + fprintf(stdout, "\033[?25h\n\033[?1049l"); + fflush(stdout); + close(timerfd); + return 0; + +fail: + perror(argv0 ? argv0 : "mongotimer"); + fprintf(stdout, "\033[?25h\n\033[?1049l"); + fflush(stdout); + if (timerfd >= 0) + close(timerfd); + return 1; + +fail_usage: + fprintf(stdout, "\033[?25h\n\033[?1049l"); + fflush(stdout); + usage(); +} |