Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /* | |
11 | * LWP_WaitForKeystroke - wait indefinitely or for a specified number of | |
12 | * seconds for keyboard input. | |
13 | * | |
14 | * If seconds < 0, LWP_WaitForKeystroke will wait indefinitely. | |
15 | * If seconds == 0, LWP_WaitForKeystroke will just determine if data is now | |
16 | * present. | |
17 | * Otherwise, wait "seconds" for data. | |
18 | * | |
19 | * Return 1 if data available. | |
20 | */ | |
21 | ||
22 | #include <afsconfig.h> | |
23 | #include <afs/param.h> | |
24 | ||
25 | #include <roken.h> | |
26 | ||
27 | #ifdef HAVE_STDIO_EXT_H | |
28 | #include <stdio_ext.h> | |
29 | #endif | |
30 | ||
31 | #ifdef AFS_NT40_ENV | |
32 | #include <conio.h> | |
33 | #endif | |
34 | ||
35 | #include "lwp.h" | |
36 | ||
37 | #define LWP_KEYSTROKE_DELAY 250 /* 250ms. Must be < 1000 */ | |
38 | #define LWP_MAXLINELEN 256 | |
39 | ||
40 | #ifdef AFS_NT40_ENV | |
41 | /* LWP_WaitForKeystroke : Wait until a key has been struck or time (secconds) | |
42 | * runs out and return to caller. The NT version of this function will return | |
43 | * immediately after a key has been pressed (doesn't wait for cr). | |
44 | * Input: | |
45 | * seconds: wait for <seconds> seconds before returning. If seconds < 0, | |
46 | * wait infinitely. | |
47 | * Return Value: | |
48 | * 1: Keyboard input available | |
49 | * 0: seconds elapsed. Timeout. | |
50 | */ | |
51 | int | |
52 | LWP_WaitForKeystroke(int seconds) | |
53 | { | |
54 | time_t startTime, nowTime; | |
55 | double timeleft = 1; | |
56 | #ifndef AFS_PTHREAD_ENV | |
57 | struct timeval twait; | |
58 | ||
59 | twait.tv_sec = 0; | |
60 | twait.tv_usec = LWP_KEYSTROKE_DELAY; | |
61 | #endif | |
62 | ||
63 | time(&startTime); | |
64 | ||
65 | if (seconds >= 0) | |
66 | timeleft = seconds; | |
67 | ||
68 | do { | |
69 | /* check if we have a keystroke */ | |
70 | if (_kbhit()) | |
71 | return 1; | |
72 | ||
73 | if (timeleft == 0) | |
74 | break; | |
75 | ||
76 | /* sleep for LWP_KEYSTROKE_DELAY ms and let other | |
77 | * process run some*/ | |
78 | #ifdef AFS_PTHREAD_ENV | |
79 | Sleep(LWP_KEYSTROKE_DELAY); | |
80 | #else | |
81 | IOMGR_Select(0, 0, 0, 0, &twait); | |
82 | #endif | |
83 | if (seconds > 0) { /* we only worry about elapsed time if | |
84 | * not looping forever (seconds < 0) */ | |
85 | /* now check elapsed time */ | |
86 | time(&nowTime); | |
87 | timeleft = seconds - difftime(nowTime, startTime); | |
88 | } | |
89 | } | |
90 | while (timeleft > 0); | |
91 | ||
92 | return 0; | |
93 | } | |
94 | ||
95 | /* LWP_GetLine() - Waits indefinitely until a newline has been typed | |
96 | * and then returns the line typed. | |
97 | * | |
98 | * This is trivial in unix, but requires some processing on NT. | |
99 | * we basically read all chars into a buffer until we hit a newline and | |
100 | * then return it to the user. | |
101 | * Return Value: | |
102 | * n - a whole line has been read.(has n chars) | |
103 | * 0 - buf not big enough. | |
104 | * -1 - line with only EOF | |
105 | */ | |
106 | ||
107 | int | |
108 | LWP_GetLine(char *linebuf, int len) | |
109 | { | |
110 | int cnt = 0; | |
111 | int ch = 0; | |
112 | ||
113 | fflush(stdin); | |
114 | /* loop until a new line has been entered */ | |
115 | while (ch != '\r' && cnt < len - 1) { | |
116 | LWP_WaitForKeystroke(-1); | |
117 | ch = getch(); | |
118 | ||
119 | if ((ch == EOF) && (cnt == 0)) | |
120 | return -1; | |
121 | ||
122 | if (ch == '\b') { /* print and throw away a backspace */ | |
123 | if (!cnt) /* if we are at the start of the line don't bspace */ | |
124 | continue; | |
125 | /* print a space to delete char and move cursor back */ | |
126 | printf("\b \b"); | |
127 | cnt--; | |
128 | } else { | |
129 | putchar(ch); | |
130 | linebuf[cnt++] = ch; | |
131 | } | |
132 | } | |
133 | ||
134 | if (ch == '\r') { /* got a cr. translate to nl */ | |
135 | linebuf[cnt - 1] = '\n'; | |
136 | linebuf[cnt] = '\0'; | |
137 | putchar('\n'); | |
138 | return cnt; | |
139 | } else { /* buffer too small */ | |
140 | linebuf[cnt] = '\0'; | |
141 | return 0; | |
142 | } | |
143 | ||
144 | } | |
145 | #else | |
146 | /* LWP_WaitForKeystroke(Unix) :Wait until a key has been struck or time (secconds) | |
147 | * runs out and return to caller. The Unix version will actually wait until | |
148 | * a <cr> has been entered before returning. | |
149 | * Input: | |
150 | * seconds: wait for <seconds> seconds before returning. If seconds < 0, | |
151 | * wait infinitely. | |
152 | * Return Value: | |
153 | * 1: Keyboard input available | |
154 | * 0: seconds elapsed. Timeout. | |
155 | */ | |
156 | int | |
157 | LWP_WaitForKeystroke(int seconds) | |
158 | { | |
159 | fd_set rdfds; | |
160 | int code; | |
161 | struct timeval twait; | |
162 | struct timeval *tp = NULL; | |
163 | ||
164 | #if defined(HAVE_STDIO_EXT_H) | |
165 | if (__fbufsize(stdin) > 0) | |
166 | return 1; | |
167 | #elif defined(AFS_LINUX20_ENV) | |
168 | if (stdin->_IO_read_ptr < stdin->_IO_read_end) | |
169 | return 1; | |
170 | #elif (defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)) && defined(AFS_DFBSD_ENV) | |
171 | struct appx_sbuf { | |
172 | unsigned char *_base; | |
173 | int _size; | |
174 | }; | |
175 | struct APPX_FILE | |
176 | { | |
177 | struct __FILE_public pub; | |
178 | struct appx_sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ | |
179 | }; | |
180 | struct APPX_FILE *appx_stdin = (struct APPX_FILE *) stdin; | |
181 | if (appx_stdin->_bf._size > 0) | |
182 | return 1; | |
183 | #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) | |
184 | if (stdin->_bf._size > 0) | |
185 | return 1; | |
186 | #else | |
187 | if (stdin->_cnt > 0) | |
188 | return 1; | |
189 | #endif | |
190 | ||
191 | FD_ZERO(&rdfds); | |
192 | FD_SET(fileno(stdin), &rdfds); | |
193 | ||
194 | if (seconds >= 0) { | |
195 | twait.tv_sec = seconds; | |
196 | twait.tv_usec = 0; | |
197 | tp = &twait; | |
198 | } | |
199 | ||
200 | #ifdef AFS_PTHREAD_ENV | |
201 | code = select(1 + fileno(stdin), &rdfds, NULL, NULL, tp); | |
202 | #else | |
203 | code = IOMGR_Select(1 + fileno(stdin), &rdfds, NULL, NULL, tp); | |
204 | #endif | |
205 | ||
206 | return (code == 1) ? 1 : 0; | |
207 | } | |
208 | ||
209 | /* LWP_GetLine() - Waits indefinitely until a newline has been typed | |
210 | * and then returns the line typed. | |
211 | * | |
212 | * This is trivial in unix, but requires some processing on NT. | |
213 | * we basically read all chars into a buffer until we hit a newline and | |
214 | * then return it to the user. | |
215 | * Return Value: | |
216 | * n - a whole line has been read.(has n chars) | |
217 | * 0 - buf not big enough. | |
218 | * -1 - line with only EOF | |
219 | */ | |
220 | ||
221 | int | |
222 | LWP_GetLine(char *linebuf, int len) | |
223 | { | |
224 | int linelen; | |
225 | char *s; | |
226 | ||
227 | LWP_WaitForKeystroke(-1); | |
228 | ||
229 | s = fgets(linebuf, len, stdin); | |
230 | if (s == NULL) | |
231 | return -1; | |
232 | ||
233 | linelen = strlen(linebuf); | |
234 | if (linebuf[linelen - 1] != '\n') /* buffer too small */ | |
235 | return 0; | |
236 | else | |
237 | return linelen; | |
238 | } | |
239 | ||
240 | #endif /* else NT40 */ | |
241 | ||
242 | /* LWP_GetResponseKey() - Waits for a specified period of time and | |
243 | * returns a char when one has been typed by the user. | |
244 | * Input: | |
245 | * seconds - how long to wait for a key press. | |
246 | * *key - char entered by user | |
247 | * Return Values: | |
248 | * 0 - Time ran out before the user typed a key. | |
249 | * 1 - Valid char is being returned. | |
250 | */ | |
251 | ||
252 | int | |
253 | LWP_GetResponseKey(int seconds, char *key) | |
254 | { | |
255 | int rc; | |
256 | ||
257 | if (key == NULL) | |
258 | return 0; /* need space to store char */ | |
259 | ||
260 | ||
261 | fflush(stdin); /* flush all existing data and start anew */ | |
262 | ||
263 | ||
264 | rc = LWP_WaitForKeystroke(seconds); | |
265 | if (rc == 0) { /* time ran out */ | |
266 | *key = 0; | |
267 | return rc; | |
268 | } | |
269 | ||
270 | /* now read the char. */ | |
271 | #ifdef AFS_NT40_ENV | |
272 | *key = getche(); /* get char and echo it to screen */ | |
273 | #else | |
274 | *key = (char)getchar(); | |
275 | #endif | |
276 | ||
277 | return rc; | |
278 | } |