aboutsummaryrefslogtreecommitdiffstats
path: root/mongoclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'mongoclock.c')
-rw-r--r--mongoclock.c169
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;
+}
+