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