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