1 /* 2 * Copyright (c) 2011 Tim van der Molen <tim@kariliq.nl> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <errno.h> 18 #include <poll.h> 19 #include <pthread.h> 20 #include <signal.h> 21 #include <termios.h> 22 #include <unistd.h> 23 24 #include "siren.h" 25 26 static void input_handle_signal(int); 27 28 static enum input_mode input_mode = INPUT_MODE_VIEW; 29 static pthread_mutex_t input_mode_mtx = PTHREAD_MUTEX_INITIALIZER; 30 static volatile sig_atomic_t input_quit; 31 #ifdef SIGWINCH 32 static volatile sig_atomic_t input_sigwinch; 33 #endif 34 35 void 36 input_end(void) 37 { 38 input_quit = 1; 39 } 40 41 void 42 input_init(void) 43 { 44 struct sigaction sa; 45 #ifdef VDSUSP 46 struct termios tio; 47 #endif 48 49 sa.sa_handler = input_handle_signal; 50 sa.sa_flags = 0; 51 sigemptyset(&sa.sa_mask); 52 53 if (sigaction(SIGINT, &sa, NULL) == -1) 54 LOG_ERR("sigaction"); 55 if (sigaction(SIGQUIT, &sa, NULL) == -1) 56 LOG_ERR("sigaction"); 57 if (sigaction(SIGTERM, &sa, NULL) == -1) 58 LOG_ERR("sigaction"); 59 #ifdef SIGWINCH 60 if (sigaction(SIGWINCH, &sa, NULL) == -1) 61 LOG_ERR("sigaction"); 62 #endif 63 64 #ifdef VDSUSP 65 /* 66 * Check if the DSUSP special character is set to ^Y. If it is, disable 67 * it so that ^Y becomes an ordinary character that can be bound to a 68 * command. 69 */ 70 if (tcgetattr(STDIN_FILENO, &tio) == -1) 71 LOG_ERR("tcgetattr"); 72 else 73 if (tio.c_cc[VDSUSP] == K_CTRL('Y')) { 74 tio.c_cc[VDSUSP] = _POSIX_VDISABLE; 75 if (tcsetattr(STDIN_FILENO, TCSANOW, &tio) == -1) 76 LOG_ERR("tcsetattr"); 77 } 78 #endif 79 } 80 81 enum input_mode 82 input_get_mode(void) 83 { 84 enum input_mode mode; 85 86 XPTHREAD_MUTEX_LOCK(&input_mode_mtx); 87 mode = input_mode; 88 XPTHREAD_MUTEX_UNLOCK(&input_mode_mtx); 89 return mode; 90 } 91 92 void 93 input_handle_key(void) 94 { 95 struct pollfd pfd[1]; 96 int key; 97 98 pfd[0].fd = STDIN_FILENO; 99 pfd[0].events = POLLIN; 100 101 while (!input_quit) { 102 #ifdef SIGWINCH 103 if (input_sigwinch) { 104 input_sigwinch = 0; 105 screen_refresh(); 106 } 107 #endif 108 109 if (poll(pfd, NELEMENTS(pfd), -1) == -1) { 110 if (errno != EINTR) 111 LOG_FATAL("poll"); 112 } else { 113 if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) 114 LOG_FATALX("poll() failed"); 115 116 key = screen_get_key(); 117 if (input_mode == INPUT_MODE_VIEW) 118 view_handle_key(key); 119 else 120 prompt_handle_key(key); 121 } 122 } 123 } 124 125 static void 126 input_handle_signal(int sig) 127 { 128 switch (sig) { 129 case SIGINT: 130 case SIGQUIT: 131 case SIGTERM: 132 input_quit = 1; 133 break; 134 #ifdef SIGWINCH 135 case SIGWINCH: 136 input_sigwinch = 1; 137 break; 138 #endif 139 } 140 } 141 142 void 143 input_set_mode(enum input_mode mode) 144 { 145 XPTHREAD_MUTEX_LOCK(&input_mode_mtx); 146 input_mode = mode; 147 XPTHREAD_MUTEX_UNLOCK(&input_mode_mtx); 148 } 149