1 /*- 2 * Copyright (c) 1980, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 32 __FBSDID("$FreeBSD$"); 33 34 #ifdef lint 35 static const char sccsid[] = "@(#)keyboard.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 38 #include <sys/select.h> 39 #include <sys/time.h> 40 41 #include <errno.h> 42 #include <ctype.h> 43 #include <stdlib.h> 44 #include <termios.h> 45 #include <unistd.h> 46 47 #include "systat.h" 48 #include "extern.h" 49 50 static char line[80]; 51 static int keyboard_dispatch(int ch); 52 53 int 54 keyboard(void) 55 { 56 int ch, n; 57 struct timeval last, intvl, now, tm; 58 fd_set rfds; 59 60 /* Set initial timings */ 61 gettimeofday(&last, NULL); 62 intvl.tv_sec = delay / 1000000; 63 intvl.tv_usec = delay % 1000000; 64 for (;;) { 65 col = 0; 66 move(CMDLINE, 0); 67 for (;;) { 68 /* Determine interval to sleep */ 69 (void)gettimeofday(&now, NULL); 70 tm.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; 71 tm.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; 72 while (tm.tv_usec < 0) { 73 tm.tv_usec += 1000000; 74 tm.tv_sec--; 75 } 76 while (tm.tv_usec >= 1000000) { 77 tm.tv_usec -= 1000000; 78 tm.tv_sec++; 79 } 80 if (tm.tv_sec < 0) { 81 /* We have to update screen immediately */ 82 display(); 83 gettimeofday(&last, NULL); 84 continue; 85 } 86 87 /* Prepare select */ 88 FD_ZERO(&rfds); 89 FD_SET(STDIN_FILENO, &rfds); 90 n = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tm); 91 92 if (n > 0) { 93 /* Read event on stdin */ 94 ch = getch(); 95 96 if (keyboard_dispatch(ch) == 0) { 97 refresh(); 98 continue; 99 } 100 101 line[col] = '\0'; 102 command(line + 1); 103 /* Refresh delay */ 104 intvl.tv_sec = delay / 1000000; 105 intvl.tv_usec = delay % 1000000; 106 refresh(); 107 break; 108 } 109 110 if (n < 0 && errno != EINTR) 111 exit(1); 112 113 /* Timeout or signal. Call display another time */ 114 display(); 115 gettimeofday(&last, NULL); 116 } 117 } 118 } 119 120 static int 121 keyboard_dispatch(int ch) 122 { 123 124 if (ch == ERR) { 125 if (errno == EINTR) 126 return 0; 127 exit(1); 128 } 129 if (ch >= 'A' && ch <= 'Z') 130 ch += 'a' - 'A'; 131 if (col == 0) { 132 if (ch == CTRL('l')) { 133 wrefresh(curscr); 134 return 0; 135 } 136 if (ch == CTRL('g')) { 137 status(); 138 return 0; 139 } 140 if (ch != ':') 141 return 0; 142 move(CMDLINE, 0); 143 clrtoeol(); 144 } 145 if (ch == erasechar() && col > 0) { 146 if (col == 1 && line[0] == ':') 147 return 0; 148 col--; 149 goto doerase; 150 } 151 if (ch == CTRL('w') && col > 0) { 152 while (--col >= 0 && isspace(line[col])) 153 ; 154 col++; 155 while (--col >= 0 && !isspace(line[col])) 156 if (col == 0 && line[0] == ':') 157 return 1; 158 col++; 159 goto doerase; 160 } 161 if (ch == killchar() && col > 0) { 162 col = 0; 163 if (line[0] == ':') 164 col++; 165 doerase: 166 move(CMDLINE, col); 167 clrtoeol(); 168 return 0; 169 } 170 if (isprint(ch) || ch == ' ') { 171 line[col] = ch; 172 mvaddch(CMDLINE, col, ch); 173 col++; 174 } 175 176 if (col == 0 || (ch != '\r' && ch != '\n')) 177 return 0; 178 179 return 1; 180 } 181