1 /* exp_select.c - select() interface for Expect
3 Written by: Don Libes, NIST, 2/6/90
5 Design and implementation of this program was paid for by U.S. tax
6 dollars. Therefore it is public domain. However, the author and NIST
7 would appreciate credit if this program or parts of it are used.
11 /* suppress file-empty warnings produced by some compilers */
14 #if 0 /* WHOLE FILE!!!! */
15 #include "expect_cf.h"
18 #include <sys/types.h>
20 #ifdef HAVE_SYS_WAIT_H
24 #ifdef HAVE_SYS_TIME_H
28 #ifdef HAVE_SYSSELECT_H
29 # include <sys/select.h> /* Intel needs this for timeval */
33 # include <sys/ptyio.h>
41 /* AIX has some unusual definition of FD_SET */
42 #include <sys/select.h>
45 #if !defined( FD_SET ) && defined( HAVE_SYS_BSDTYPES_H )
46 /* like AIX, ISC has it's own definition of FD_SET */
47 # include <sys/bsdtypes.h>
48 #endif /* ! FD_SET && HAVE_SYS_BSDTYPES_H */
52 #include "exp_command.h" /* for struct exp_f defs */
53 #include "exp_event.h"
56 #include <sys/sysconfig.h>
60 #define FD_SET(fd,fdset) (fdset)->fds_bits[0] |= (1<<(fd))
61 #define FD_CLR(fd,fdset) (fdset)->fds_bits[0] &= ~(1<<(fd))
62 #define FD_ZERO(fdset) (fdset)->fds_bits[0] = 0
63 #define FD_ISSET(fd,fdset) (((fdset)->fds_bits[0]) & (1<<(fd)))
65 typedef struct fd_set {
67 /* any implementation so pathetic as to not define FD_SET will just */
68 /* have to suffer with only 32 bits worth of fds */
73 static struct timeval zerotime = {0, 0};
74 static struct timeval anytime = {0, 0}; /* can be changed by user */
76 /* returns status, one of EOF, TIMEOUT, ERROR or DATA */
78 exp_get_next_event(interp,masters, n,master_out,timeout,key)
81 int n; /* # of masters */
82 int *master_out; /* 1st event master, not set if none */
83 int timeout; /* seconds */
86 static rr = 0; /* round robin ptr */
88 int i; /* index into in-array */
93 /* FIXME: This is really gross, but the folks at Lynx said their select is
94 * way hosed and to ignore all exceptions.
114 f->force_read = FALSE;
116 return(EXP_DATA_OLD);
117 } else if ((!f->force_read) && (f->size != 0)) {
119 return(EXP_DATA_OLD);
131 if (Tcl_AsyncReady()) {
132 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
133 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
135 /* anything in the environment could have changed */
136 return EXP_RECONFIGURE;
141 for (i = 0;i < n;i++) {
142 FD_SET(masters[i],&rdrs);
143 FD_SET(masters[i],&excep);
146 /* The reason all fd masks are (seemingly) redundantly cast to */
147 /* SELECT_MASK_TYPE is that the HP defines its mask in terms of */
148 /* of int * and yet defines FD_SET in terms of fd_set. */
150 if (-1 == select(exp_fd_max+1,
151 (SELECT_MASK_TYPE *)&rdrs,
152 (SELECT_MASK_TYPE *)0,
153 (SELECT_MASK_TYPE *)EXCEP,
155 /* window refreshes trigger EINTR, ignore */
156 if (errno == EINTR) goto restart;
157 else if (errno == EBADF) {
158 /* someone is rotten */
162 FD_SET(masters[i],&suspect);
163 if (-1 == select(exp_fd_max+1,
164 (SELECT_MASK_TYPE *)&suspect,
165 (SELECT_MASK_TYPE *)0,
166 (SELECT_MASK_TYPE *)0,
168 exp_error(interp,"invalid spawn_id (%d)\r",masters[i]);
169 return(EXP_TCLERROR);
173 /* not prepared to handle anything else */
174 exp_error(interp,"select: %s\r",Tcl_PosixError(interp));
175 return(EXP_TCLERROR);
181 if (rr >= n) rr = 0; /* ">" catches previous readys that */
182 /* used more fds then we're using now */
184 if (FD_ISSET(masters[rr],&rdrs)) {
185 *master_out = masters[rr];
186 return(EXP_DATA_NEW);
187 /*#ifdef HAVE_PTYTRAP*/
188 } else if (FD_ISSET(masters[rr], &excep)) {
190 *master_out = masters[rr];
193 struct request_info ioctl_info;
194 if (ioctl(masters[rr],TIOCREQCHECK,&ioctl_info) < 0) {
195 exp_DiagLog("ioctl error on TIOCREQCHECK: %s",Tcl_ErrnoMsg(errno));
198 if (ioctl_info.request == TIOCCLOSE) {
200 *master_out = masters[rr];
203 if (ioctl(masters[rr], TIOCREQSET, &ioctl_info) < 0)
204 expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
205 /* presumably, we trapped an open here */
207 #endif /* HAVE_PTYTRAP */
215 exp_get_next_event_info(interp,fd,ready_mask)
220 /* this function is only used when running with Tk */
221 /* hence, it is merely a stub in this file but to */
222 /* pacify lint, return something */
226 int /* returns TCL_XXX */
227 exp_dsleep(interp,sec)
234 t.tv_usec = (sec - t.tv_sec) * 1000000L;
236 if (Tcl_AsyncReady()) {
237 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
238 if (rc != TCL_OK) return rc;
241 (SELECT_MASK_TYPE *)0,
242 (SELECT_MASK_TYPE *)0,
243 (SELECT_MASK_TYPE *)0,
251 int /* returns TCL_XXX */
252 exp_usleep(interp,usec)
254 long usec; /* microseconds */
258 t.tv_sec = usec/1000000L;
259 t.tv_usec = usec%1000000L;
261 if (Tcl_AsyncReady()) {
262 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
263 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
266 (SELECT_MASK_TYPE *)0,
267 (SELECT_MASK_TYPE *)0,
268 (SELECT_MASK_TYPE *)0,
276 /* set things up for later calls to event handler */
282 maxfds = sysconf(_SC_OPEN_MAX);
284 maxfds = getdtablesize();
290 #endif /* WHOLE FILE !!!! */