Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / lwp / waitkey.c
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 }