1 /* interact (with only one process) - give user keyboard control
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.
10 /* This file exists for deficient versions of UNIX that lack select,
11 poll, or some other multiplexing hook. Instead, this code uses two
12 processes per spawned process. One sends characters from the spawnee
13 to the spawner; a second send chars the other way.
15 This will work on any UNIX system. The only sacrifice is that it
16 doesn't support multiple processes. Eventually, it should catch
17 SIGCHLD on dead processes and do the right thing. But it is pretty
18 gruesome to imagine so many processes to do all this. If you change
19 it successfully, please mail back the changes to me. - Don
22 #include "expect_cf.h"
24 #include <sys/types.h>
27 #ifdef HAVE_SYS_WAIT_H
33 #include "exp_command.h" /* for struct ExpState defs */
34 #include "exp_event.h"
38 exp_arm_background_filehandler(esPtr)
45 exp_disarm_background_filehandler(esPtr)
52 exp_disarm_background_filehandler_force(esPtr)
59 exp_unblock_background_filehandler(esPtr)
66 exp_block_background_filehandler(esPtr)
78 /* returns status, one of EOF, TIMEOUT, ERROR or DATA */
81 exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key)
84 int n; /* # of esPtrs */
85 ExpState **esPtrOut; /* 1st event master, not set if none */
86 int timeout; /* seconds */
90 exp_error(interp,"expect not compiled with multiprocess support");
91 /* select a different INTERACT_TYPE in Makefile */
95 esPtr = *esPtrOut = esPtrs[0];
97 if (esPtr->key != key) {
99 esPtr->force_read = FALSE;
100 return(EXP_DATA_OLD);
101 } else if ((!esPtr->force_read) && (esPtr->size != 0)) {
102 return(EXP_DATA_OLD);
105 return(EXP_DATA_NEW);
110 exp_get_next_event_info(interp,esPtr,ready_mask)
117 /* There is no portable way to do sub-second sleeps on such a system, so */
118 /* do the next best thing (without a busy loop) and fake it: sleep the right */
119 /* amount of time over the long run. Note that while "subtotal" isn't */
120 /* reinitialized, it really doesn't matter for such a gross hack as random */
121 /* scheduling pauses will easily introduce occasional one second delays. */
122 int /* returns TCL_XXX */
123 exp_dsleep(interp,sec)
127 static double subtotal = 0;
131 if (subtotal < 1) return TCL_OK;
135 if (Tcl_AsyncReady()) {
136 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
137 if (rc != TCL_OK) return(rc);
144 /* There is no portable way to do sub-second sleeps on such a system, so */
145 /* do the next best thing (without a busy loop) and fake it: sleep the right */
146 /* amount of time over the long run. Note that while "subtotal" isn't */
147 /* reinitialized, it really doesn't matter for such a gross hack as random */
148 /* scheduling pauses will easily introduce occasional one second delays. */
149 int /* returns TCL_XXX */
150 exp_usleep(interp,usec)
152 long usec; /* microseconds */
158 if (subtotal < 1000000) return TCL_OK;
159 seconds = subtotal/1000000;
160 subtotal = subtotal%1000000;
162 if (Tcl_AsyncReady()) {
163 int rc = Tcl_AsyncInvoke(interp,TCL_OK);
164 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
171 /* set things up for later calls to event handler */