diff --git a/dvtm.c b/dvtm.c index 2b7ebdc..3fe2381 100644 --- a/dvtm.c +++ b/dvtm.c @@ -52,7 +52,7 @@ typedef struct { int history; int w; int h; - volatile sig_atomic_t need_resize; + bool need_resize; } Screen; typedef struct { @@ -248,6 +248,10 @@ static const char *shell; static Register copyreg; static volatile sig_atomic_t running = true; static bool runinall = false; +static int sigwinch_pipe[] = {-1, -1}; +static int sigchld_pipe[] = {-1, -1}; + +enum {PIPE_RD, PIPE_WR}; static void eprint(const char *errstr, ...) { @@ -698,6 +702,11 @@ get_client_by_coord(unsigned int x, unsigned int y) { static void sigchld_handler(int sig) { + write(sigchld_pipe[PIPE_WR], "\0", 1); +} + +static void +handle_sigchld() { int errsv = errno; int status; pid_t pid; @@ -731,6 +740,11 @@ sigchld_handler(int sig) { static void sigwinch_handler(int sig) { + write(sigwinch_pipe[PIPE_WR], "\0", 1); +} + +static void +handle_sigwinch() { screen.need_resize = true; } @@ -939,6 +953,14 @@ getshell(void) { return "/bin/sh"; } +static bool +set_blocking(int fd, bool blocking) { + int flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) return false; + flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + return !fcntl(fd, F_SETFL, flags); +} + static void setup(void) { shell = getshell(); @@ -962,6 +984,23 @@ setup(void) { colors[i].pair = vt_color_reserve(colors[i].fg, colors[i].bg); } resize_screen(); + + int *pipes[] = {&sigwinch_pipe[0], &sigchld_pipe[0]}; + for (int i = 0; i < 2; ++i) { + int r = pipe(pipes[i]); + if (r < 0) { + perror("pipe()"); + exit(EXIT_FAILURE); + } + + for (int j = 0; j < 2; ++j) { + if (!set_blocking(pipes[i][j], false)) { + perror("fcntl()"); + exit(EXIT_FAILURE); + } + } + } + struct sigaction sa; memset(&sa, 0, sizeof sa); sa.sa_flags = 0; @@ -1815,7 +1854,6 @@ main(int argc, char *argv[]) { KeyCombo keys; unsigned int key_index = 0; memset(keys, 0, sizeof(keys)); - sigset_t emptyset, blockset; setenv("DVTM", VERSION, 1); if (!parse_args(argc, argv)) { @@ -1823,12 +1861,6 @@ main(int argc, char *argv[]) { startup(NULL); } - sigemptyset(&emptyset); - sigemptyset(&blockset); - sigaddset(&blockset, SIGWINCH); - sigaddset(&blockset, SIGCHLD); - sigprocmask(SIG_BLOCK, &blockset, NULL); - while (running) { int r, nfds = 0; fd_set rd; @@ -1841,9 +1873,15 @@ main(int argc, char *argv[]) { FD_ZERO(&rd); FD_SET(STDIN_FILENO, &rd); + FD_SET(sigwinch_pipe[PIPE_RD], &rd); + nfds = MAX(nfds, sigwinch_pipe[PIPE_RD]); + + FD_SET(sigchld_pipe[PIPE_RD], &rd); + nfds = MAX(nfds, sigchld_pipe[PIPE_RD]); + if (cmdfifo.fd != -1) { FD_SET(cmdfifo.fd, &rd); - nfds = cmdfifo.fd; + nfds = MAX(nfds, cmdfifo.fd); } if (bar.fd != -1) { @@ -1867,7 +1905,7 @@ main(int argc, char *argv[]) { } doupdate(); - r = pselect(nfds + 1, &rd, NULL, NULL, NULL, &emptyset); + r = select(nfds + 1, &rd, NULL, NULL, NULL); if (r < 0) { if (errno == EINTR) @@ -1903,6 +1941,18 @@ main(int argc, char *argv[]) { continue; } + if (FD_ISSET(sigwinch_pipe[PIPE_RD], &rd)) { + char buf[512]; + while (read(sigwinch_pipe[PIPE_RD], &buf, sizeof(buf)) > 0); + handle_sigwinch(); + } + + if (FD_ISSET(sigchld_pipe[PIPE_RD], &rd)) { + char buf[512]; + while (read(sigchld_pipe[PIPE_RD], &buf, sizeof(buf)) > 0); + handle_sigchld(); + } + if (cmdfifo.fd != -1 && FD_ISSET(cmdfifo.fd, &rd)) handle_cmdfifo();