[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / lib / std / cbits / inputReady.lc
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1994
3 %
4 \subsection[inputReady.lc]{hReady Runtime Support}
5
6 \begin{code}
7
8 /* select and supporting types is not */
9 #ifndef _AIX
10 #define NON_POSIX_SOURCE  
11 #endif
12
13 #include "rtsdefs.h"
14 #include "stgio.h"
15
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19
20 #ifdef _AIX 
21 /* this is included from sys/types.h only if _BSD is defined. */
22 /* Since it is not, I include it here. - andre */
23 #include <sys/select.h>
24 #endif
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
33
34 #ifdef HAVE_SYS_TIME_H
35 #include <sys/time.h>
36 #endif
37
38 /*
39  * inputReady(ptr, msecs) checks to see whether input is available
40  * on the file object 'ptr', timing out after (approx.) 'msec' milliseconds.
41  * Input meaning 'can I safely read at least a *character* from this file
42  * object without blocking?'
43  * 
44  * If the file object has a non-empty buffer, the test is trivial. If not,
45  * we select() on the (readable) file descriptor.
46  *
47  * Notice that for file descriptors connected to ttys in non-canonical mode
48  * (i.e., it's buffered), inputReady will not return true until a *complete
49  * line* can be read.
50  */
51
52 StgInt
53 inputReady(ptr, msecs)
54 StgForeignObj ptr;
55 StgInt msecs;
56 {
57     IOFileObject* fo = (IOFileObject*)ptr;
58     int c, fd, maxfd, ready;
59     fd_set rfd;
60     struct timeval tv;
61
62     if ( FILEOBJ_IS_EOF(fo) )
63         return 0;
64
65     if ( !FILEOBJ_BUFFER_EMPTY(fo) ) {
66            /* Don't look any further, there's stuff in the buffer */
67            return 1;
68     }
69
70     fd = fo->fd;
71
72     /* Now try to get a character */
73     FD_ZERO(&rfd);
74     FD_SET(fd, &rfd);
75     /* select() will consider the descriptor set in the range of 0 to (maxfd-1) */
76     maxfd = fd + 1;
77     tv.tv_sec  = msecs / 1000;
78     tv.tv_usec = msecs % 1000;
79     while ((ready = select(maxfd, &rfd, NULL, NULL, &tv)) < 0 ) {
80       if (errno != EINTR ) {
81                 cvtErrno();
82                 stdErrno();
83                 ready = -1;
84                 break;
85       }
86    }
87
88     /* 1 => Input ready, 0 => time expired  (-1 error) */
89     return (ready);
90
91 }
92
93 \end{code}