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