summaryrefslogtreecommitdiff
path: root/pico/osdep/read.c
blob: 52fe92e58a34cbb7cf0a18d82e228691d20d378e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#if !defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: read.c 763 2007-10-23 23:37:34Z hubert@u.washington.edu $";
#endif

/*
 * ========================================================================
 * Copyright 2006 University of Washington
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * ========================================================================
 */

/*
 * Keyboard input test and read functions
 */

#include <system.h>		/* os-dep defs/includes */
#include <general.h>		/* generally useful definitions */

#include "../keydefs.h"

#ifndef _WINDOWS
#include "raw.h"
#endif /* !_WINDOWS */

#include "read.h"


static time_t _time_of_last_input;

time_t
time_of_last_input(void)
{
    if(_time_of_last_input == 0)
      _time_of_last_input = time((time_t *) 0);

    return(_time_of_last_input);
}

#ifndef _WINDOWS
#if	HAVE_SELECT

#ifdef	HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif


/*
 *  Check whether or not a character is ready to be read, or time out.
 *  This version uses a select call.
 *
 *   Args: time_out -- number of seconds before it will time out.
 *
 * Result: NO_OP_IDLE:	  timed out before any chars ready, time_out > 25
 *         NO_OP_COMMAND: timed out before any chars ready, time_out <= 25
 *         READ_INTR:	  read was interrupted
 *         READY_TO_READ: input is available
 *         BAIL_OUT:	  reading input failed, time to bail gracefully
 *         PANIC_NOW:	  system call error, die now
 */
UCS
input_ready(int time_out)
{
     struct timeval tmo;
     fd_set         readfds, errfds;
     int	    res;

     fflush(stdout);

     if(time_out > 0){
         /* Check to see if there are bytes to read with a timeout */
	 FD_ZERO(&readfds);
	 FD_ZERO(&errfds);
	 FD_SET(STDIN_FD, &readfds);
	 FD_SET(STDIN_FD, &errfds);
	 tmo.tv_sec  = time_out;
         tmo.tv_usec = 0; 
         res = select(STDIN_FD+1, &readfds, 0, &errfds, &tmo);
         if(res < 0){
             if(errno == EINTR || errno == EAGAIN)
               return(READ_INTR);

	     return(BAIL_OUT);
         }

         if(res == 0){ /* the select timed out */
#ifndef __CYGWIN__
	     if(getppid() == 1){
		 /* Parent is init! */
	         return(BAIL_OUT);
	     }
#endif
	       
	     /*
	      * "15" is the minimum allowed mail check interval.
	      * Anything less, and we're being told to cycle thru
	      * the command loop because some task is pending...
	      */
             return(time_out < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE);
         }
     }

     _time_of_last_input = time((time_t *) 0);
     return(READY_TO_READ);
}


#elif	HAVE_POLL


#ifdef	HAVE_STROPTS_H
# include <stropts.h>
#endif

#ifdef	HAVE_SYS_POLL_H
# include <poll.h>
#endif

/*
 *  Check whether or not a character is ready to be read, or time out.
 *  This version uses a poll call.
 *
 *   Args: time_out -- number of seconds before it will time out.
 *
 * Result: NO_OP_IDLE:	  timed out before any chars ready, time_out > 25
 *         NO_OP_COMMAND: timed out before any chars ready, time_out <= 25
 *         READ_INTR:	  read was interrupted
 *         READY_TO_READ: input is available
 *         BAIL_OUT:	  reading input failed, time to bail gracefully
 *         PANIC_NOW:	  system call error, die now
 */
UCS
input_ready(int time_out)
{
     struct pollfd pollfd;
     int	   res;

     fflush(stdout);

     if(time_out > 0){
         /* Check to see if there are bytes to read with a timeout */
	 pollfd.fd = STDIN_FD;
	 pollfd.events = POLLIN;
	 res = poll (&pollfd, 1, time_out * 1000);
	 if(res >= 0){				/* status bits OK? */
	     if(pollfd.revents & (POLLERR | POLLNVAL))
	       res = -1;			/* bad news, exit below! */
	     else if(pollfd.revents & POLLHUP)
	       return(BAIL_OUT);
	 }

         if(res < 0){
             if(errno == EINTR || errno == EAGAIN)
               return(READ_INTR);

	     return(PANIC_NOW);
         }

         if(res == 0){ /* the select timed out */
	     if(getppid() == 1){
		 /* Parent is init! */
	         return(BAIL_OUT);
	     }

	     /*
	      * "15" is the minimum allowed mail check interval.
	      * Anything less, and we're being told to cycle thru
	      * the command loop because some task is pending...
	      */
             return(time_out < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE);
         }
     }

     _time_of_last_input = time((time_t *) 0);
     return(READY_TO_READ);
}

#endif /* HAVE_POLL */


/*
 * Read one character from STDIN.
 *
 * Result:           -- the single character read
 *         READ_INTR -- read was interrupted
 *         BAIL_OUT  -- read error of some sort
 */
int
read_one_char(void)
{
     int	    res;
     unsigned char  c;

     res = read(STDIN_FD, &c, 1);

     if(res <= 0){
	 /*
	  * Error reading from terminal!
	  * The only acceptable failure is being interrupted.  If so,
	  * return a value indicating such...
	  */
	 if(res < 0 && errno == EINTR)
	   return(READ_INTR);
	 else
	   return(BAIL_OUT);
     }

     return((int)c);
}

#else /* _WINDOWS */
int
set_time_of_last_input(void)
{
    _time_of_last_input = time(0L);
    return(0);
}
#endif /* _WINDOWS */