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