diff options
Diffstat (limited to 'mongoclock.c')
-rw-r--r-- | mongoclock.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/mongoclock.c b/mongoclock.c new file mode 100644 index 0000000..e2d7e20 --- /dev/null +++ b/mongoclock.c @@ -0,0 +1,169 @@ +/* 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 <time.h> +#include <unistd.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; + +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); +} + +int +main(int argc, char *argv[]) +{ + time_t now_; + struct tm *now; + const char **digits[9]; + size_t x = 0, y = 0; + struct winsize winsize; + int small = 0; + int fd = -1; + struct itimerspec itimerspec; + uint64_t _overrun; + + 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; + fd = timerfd_create(CLOCK_REALTIME, 0); + if (fd < 0) + goto fail; + if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &itimerspec, NULL)) + goto fail; + + signal(SIGTERM, sigterm); + signal(SIGQUIT, sigterm); + signal(SIGINT, sigterm); + signal(SIGWINCH, sigwinch); + siginterrupt(SIGTERM, 1); + siginterrupt(SIGQUIT, 1); + siginterrupt(SIGINT, 1); + siginterrupt(SIGWINCH, 1); + + 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; + } + + now_ = time(NULL); + if (now_ == -1) + goto fail; + now = localtime(&now_); + if (now == NULL) + goto fail; + + 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]; + digits[8] = NULL; + + print_time(digits, y, x); + + if (read(fd, &_overrun, sizeof(_overrun)) < 0) + if (errno != EINTR) + goto fail; + } + + fprintf(stdout, "\033[?25h\n\033[?1049l"); + fflush(stdout); + close(fd); + return 0; + +fail: + perror(argc ? *argv : "mongoclock"); + fprintf(stdout, "\033[?25h\n\033[?1049l"); + fflush(stdout); + if (fd >= 0) + close(fd); + return 1; +} + |