Fix LTO build
[platform/upstream/expect.git] / exp_select.c
1 /* exp_select.c - select() interface for Expect
2
3 Written by: Don Libes, NIST, 2/6/90
4
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.
8
9 */
10
11 /* suppress file-empty warnings produced by some compilers */
12 void exp_unused() {}
13
14 #if 0 /* WHOLE FILE!!!! */
15 #include "expect_cf.h"
16 #include <stdio.h>
17 #include <errno.h>
18 #include <sys/types.h>
19
20 #ifdef HAVE_SYS_WAIT_H
21 #include <sys/wait.h>
22 #endif
23
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27
28 #ifdef HAVE_SYSSELECT_H
29 #  include <sys/select.h>       /* Intel needs this for timeval */
30 #endif
31
32 #ifdef HAVE_PTYTRAP
33 #  include <sys/ptyio.h>
34 #endif
35
36 #ifdef HAVE_UNISTD_H
37 #  include <unistd.h>
38 #endif
39
40 #ifdef _AIX
41 /* AIX has some unusual definition of FD_SET */
42 #include <sys/select.h>
43 #endif
44
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 */
49
50 #include "tcl.h"
51 #include "exp_prog.h"
52 #include "exp_command.h"        /* for struct exp_f defs */
53 #include "exp_event.h"
54
55 #ifdef HAVE_SYSCONF_H
56 #include <sys/sysconfig.h>
57 #endif
58
59 #ifndef FD_SET
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)))
64 #ifndef AUX2
65 typedef struct fd_set {
66         long fds_bits[1];
67         /* any implementation so pathetic as to not define FD_SET will just */
68         /* have to suffer with only 32 bits worth of fds */
69 } fd_set;
70 #endif /* AUX2 */
71 #endif
72
73 static struct timeval zerotime = {0, 0};
74 static struct timeval anytime = {0, 0}; /* can be changed by user */
75
76 /* returns status, one of EOF, TIMEOUT, ERROR or DATA */
77 int
78 exp_get_next_event(interp,masters, n,master_out,timeout,key)
79 Tcl_Interp *interp;
80 int *masters;
81 int n;                  /* # of masters */
82 int *master_out;        /* 1st event master, not set if none */
83 int timeout;            /* seconds */
84 int key;
85 {
86         static rr = 0;  /* round robin ptr */
87
88         int i;  /* index into in-array */
89         struct timeval *t;
90
91         fd_set rdrs;
92         fd_set excep;
93 /* FIXME: This is really gross, but the folks at Lynx said their select is
94  *        way hosed and to ignore all exceptions.
95  */
96 #ifdef __Lynx__
97 #define EXCEP 0
98 #else
99 #define EXCEP &excep
100 #endif
101
102         for (i=0;i<n;i++) {
103                 struct exp_f *f;
104                 int m;
105
106                 rr++;
107                 if (rr >= n) rr = 0;
108
109                 m = masters[rr];
110                 f = exp_fs + m;
111
112                 if (f->key != key) {
113                         f->key = key;
114                         f->force_read = FALSE;
115                         *master_out = m;
116                         return(EXP_DATA_OLD);
117                 } else if ((!f->force_read) && (f->size != 0)) {
118                         *master_out = m;
119                         return(EXP_DATA_OLD);
120                 }
121         }
122
123         if (timeout >= 0) {
124                 t = &anytime;
125                 t->tv_sec = timeout;
126         } else {
127                 t = NULL;
128         }
129
130  restart:
131         if (Tcl_AsyncReady()) {
132                 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
133                 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
134
135                 /* anything in the environment could have changed */
136                 return EXP_RECONFIGURE;
137         }
138
139         FD_ZERO(&rdrs);
140         FD_ZERO(&excep);
141         for (i = 0;i < n;i++) {
142                 FD_SET(masters[i],&rdrs);
143                 FD_SET(masters[i],&excep);
144         }
145
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. */
149
150         if (-1 == select(exp_fd_max+1,
151                         (SELECT_MASK_TYPE *)&rdrs,
152                         (SELECT_MASK_TYPE *)0,
153                         (SELECT_MASK_TYPE *)EXCEP,
154                         t)) {
155                 /* window refreshes trigger EINTR, ignore */
156                 if (errno == EINTR) goto restart;
157                 else if (errno == EBADF) {
158                     /* someone is rotten */
159                     for (i=0;i<n;i++) {
160                         fd_set suspect;
161                         FD_ZERO(&suspect);
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,
167                                         &zerotime)) {
168                                 exp_error(interp,"invalid spawn_id (%d)\r",masters[i]);
169                                 return(EXP_TCLERROR);
170                         }
171                    }
172                 } else {
173                         /* not prepared to handle anything else */
174                         exp_error(interp,"select: %s\r",Tcl_PosixError(interp));
175                         return(EXP_TCLERROR);
176                 }
177         }
178
179         for (i=0;i<n;i++) {
180                 rr++;
181                 if (rr >= n) rr = 0;    /* ">" catches previous readys that */
182                                 /* used more fds then we're using now */
183
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)) {
189 #ifndef HAVE_PTYTRAP
190                         *master_out = masters[rr];
191                         return(EXP_EOF);
192 #else
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));
196                                 break;
197                         }
198                         if (ioctl_info.request == TIOCCLOSE) {
199                                 /* eof */
200                                 *master_out = masters[rr];
201                                 return(EXP_EOF);
202                         }
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 */
206                         goto restart;
207 #endif /* HAVE_PTYTRAP */
208                 }
209         }
210         return(EXP_TIMEOUT);
211 }
212
213 /*ARGSUSED*/
214 int
215 exp_get_next_event_info(interp,fd,ready_mask)
216 Tcl_Interp *interp;
217 int fd;
218 int ready_mask;
219 {
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 */
223         return 0;
224 }
225
226 int     /* returns TCL_XXX */
227 exp_dsleep(interp,sec)
228 Tcl_Interp *interp;
229 double sec;
230 {
231         struct timeval t;
232
233         t.tv_sec = sec;
234         t.tv_usec = (sec - t.tv_sec) * 1000000L;
235  restart:
236         if (Tcl_AsyncReady()) {
237                 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
238                 if (rc != TCL_OK) return rc;
239         }
240         if (-1 == select(1,
241                         (SELECT_MASK_TYPE *)0,
242                         (SELECT_MASK_TYPE *)0,
243                         (SELECT_MASK_TYPE *)0,
244                         &t)
245                                 && errno == EINTR)
246                 goto restart;
247         return TCL_OK;
248 }
249
250 #if 0
251 int     /* returns TCL_XXX */
252 exp_usleep(interp,usec)
253 Tcl_Interp *interp;
254 long usec;              /* microseconds */
255 {
256         struct timeval t;
257
258         t.tv_sec = usec/1000000L;
259         t.tv_usec = usec%1000000L;
260  restart:
261         if (Tcl_AsyncReady()) {
262                 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
263                 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
264         }
265         if (-1 == select(1,
266                         (SELECT_MASK_TYPE *)0,
267                         (SELECT_MASK_TYPE *)0,
268                         (SELECT_MASK_TYPE *)0,
269                         &t)
270                                 && errno == EINTR)
271                 goto restart;
272         return TCL_OK;
273 }
274 #endif /*0*/
275
276 /* set things up for later calls to event handler */
277 void
278 exp_init_event()
279 {
280 #if 0
281 #ifdef _SC_OPEN_MAX
282         maxfds = sysconf(_SC_OPEN_MAX);
283 #else
284         maxfds = getdtablesize();
285 #endif
286 #endif
287
288         exp_event_exit = 0;
289 }
290 #endif /* WHOLE FILE !!!! */