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: stable/9/usr.bin/systat/keyboard.c 241213 2012-10-04 22:56:15Z melifaro $");
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
keyboard(void)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
keyboard_dispatch(int ch)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