diff options
Diffstat (limited to 'mongoclock.c')
-rw-r--r-- | mongoclock.c | 64 |
1 files changed, 61 insertions, 3 deletions
diff --git a/mongoclock.c b/mongoclock.c index dfc5578..6e8b6a0 100644 --- a/mongoclock.c +++ b/mongoclock.c @@ -2,11 +2,13 @@ #include <sys/ioctl.h> #include <sys/timerfd.h> #include <errno.h> +#include <fcntl.h> #include <signal.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <termios.h> #include <time.h> #include <unistd.h> #ifdef USE_ADJTIMEX @@ -40,6 +42,7 @@ static volatile sig_atomic_t caught_sigterm = 0; static volatile sig_atomic_t caught_sigwinch = 1; char *argv0; +static int exit_value = 0; static void usage(void) @@ -63,6 +66,22 @@ sigwinch(int signo) } static void +sigio(int signo) +{ + char c; + ssize_t r; + r = read(STDIN_FILENO, &c, 1); + if (r <= 0) { + if (r < 0) + exit_value = 1; + caught_sigterm = 1; + } else if (c == 'q') { + caught_sigterm = 1; + } + (void) signo; +} + +static void print_time(const char ***str, size_t y, size_t x) { size_t r, c; @@ -250,10 +269,12 @@ fail: int main(int argc, char *argv[]) { - int timerfd = -1; - int posixtime = 0; + int timerfd = -1, old_flags = -1, tcset = 0; + int posixtime = 0, old_sig = 0, owner_set = 0; struct itimerspec itimerspec; struct sigaction sigact; + struct f_owner_ex old_owner, new_owner; + struct termios stty, saved_stty; ARGBEGIN { case 's': @@ -290,18 +311,55 @@ main(int argc, char *argv[]) sigact.sa_handler = sigwinch; sigaction(SIGWINCH, &sigact, NULL); + sigact.sa_handler = sigio; + sigaction(SIGIO, &sigact, NULL); + sigaction(SIGURG, &sigact, NULL); + + if (fcntl(STDIN_FILENO, F_GETOWN_EX, &old_owner)) + goto fail; + memset(&new_owner, 0, sizeof(new_owner)); + new_owner.type = F_OWNER_PID; + new_owner.pid = getpid(); + if (fcntl(STDIN_FILENO, F_SETOWN_EX, &new_owner)) + goto fail; + owner_set = 1; + old_flags = fcntl(STDIN_FILENO, F_GETFL); + fcntl(STDIN_FILENO, F_SETFL, old_flags | FASYNC | O_NONBLOCK); + fcntl(STDIN_FILENO, F_GETSIG, &old_sig); + if (old_sig) + fcntl(STDIN_FILENO, F_SETSIG, 0); + + if (!tcgetattr(STDIN_FILENO, &stty)) { + saved_stty = stty; + stty.c_lflag &= (tcflag_t)~(ECHO | ICANON); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty); + tcset = 1; + } + if (posixtime ? display_posixtime(timerfd) : display_time(timerfd)) goto fail; fprintf(stdout, "\033[?25h\n\033[?1049l"); fflush(stdout); + fcntl(STDIN_FILENO, F_SETOWN_EX, &old_owner); + fcntl(STDIN_FILENO, F_SETFL, old_flags); + fcntl(STDIN_FILENO, F_SETSIG, old_sig); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_stty); close(timerfd); - return 0; + return exit_value; fail: perror(argv0 ? argv0 : "mongoclock"); fprintf(stdout, "\033[?25h\n\033[?1049l"); fflush(stdout); + if (owner_set) + fcntl(STDIN_FILENO, F_SETOWN_EX, &old_owner); + if (old_flags != -1) + fcntl(STDIN_FILENO, F_SETFL, old_flags); + if (old_sig) + fcntl(STDIN_FILENO, F_SETSIG, old_sig); + if (tcset) + tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_stty); if (timerfd >= 0) close(timerfd); return 1; |