1/* interact (with only one process) - give user keyboard control 2 3Written by: Don Libes, NIST, 2/6/90 4 5Design and implementation of this program was paid for by U.S. tax 6dollars. Therefore it is public domain. However, the author and NIST 7would appreciate credit if this program or parts of it are used. 8*/ 9 10/* This file exists for deficient versions of UNIX that lack select, 11poll, or some other multiplexing hook. Instead, this code uses two 12processes per spawned process. One sends characters from the spawnee 13to the spawner; a second send chars the other way. 14 15This will work on any UNIX system. The only sacrifice is that it 16doesn't support multiple processes. Eventually, it should catch 17SIGCHLD on dead processes and do the right thing. But it is pretty 18gruesome to imagine so many processes to do all this. If you change 19it successfully, please mail back the changes to me. - Don 20*/ 21 22#include "expect_cf.h" 23#include <stdio.h> 24#include <sys/types.h> 25#include <sys/time.h> 26 27#ifdef HAVE_SYS_WAIT_H 28#include <sys/wait.h> 29#endif 30 31#include "tcl.h" 32#include "exp_prog.h" 33#include "exp_command.h" /* for struct ExpState defs */ 34#include "exp_event.h" 35 36/*ARGSUSED*/ 37void 38exp_arm_background_filehandler(esPtr) 39ExpState *esPtr; 40{ 41} 42 43/*ARGSUSED*/ 44void 45exp_disarm_background_filehandler(esPtr) 46ExpState *esPtr; 47{ 48} 49 50/*ARGSUSED*/ 51void 52exp_disarm_background_filehandler_force(esPtr) 53ExpState *esPtr; 54{ 55} 56 57/*ARGSUSED*/ 58void 59exp_unblock_background_filehandler(esPtr) 60ExpState *esPtr; 61{ 62} 63 64/*ARGSUSED*/ 65void 66exp_block_background_filehandler(esPtr) 67ExpState *esPtr; 68{ 69} 70 71/*ARGSUSED*/ 72void 73exp_event_disarm(fd) 74int fd; 75{ 76} 77 78/* returns status, one of EOF, TIMEOUT, ERROR or DATA */ 79/*ARGSUSED*/ 80int 81exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key) 82Tcl_Interp *interp; 83ExpState (*esPtrs)[]; 84int n; /* # of esPtrs */ 85ExpState **esPtrOut; /* 1st event master, not set if none */ 86int timeout; /* seconds */ 87int key; 88{ 89 if (n > 1) { 90 exp_error(interp,"expect not compiled with multiprocess support"); 91 /* select a different INTERACT_TYPE in Makefile */ 92 return(TCL_ERROR); 93 } 94 95 esPtr = *esPtrOut = esPtrs[0]; 96 97 if (esPtr->key != key) { 98 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); 103 } 104 105 return(EXP_DATA_NEW); 106} 107 108/*ARGSUSED*/ 109int 110exp_get_next_event_info(interp,esPtr,ready_mask) 111Tcl_Interp *interp; 112ExpState *esPtr; 113int ready_mask; 114{ 115} 116 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. */ 122int /* returns TCL_XXX */ 123exp_dsleep(interp,sec) 124Tcl_Interp *interp; 125double sec; 126{ 127 static double subtotal = 0; 128 int seconds; 129 130 subtotal += sec; 131 if (subtotal < 1) return TCL_OK; 132 seconds = subtotal; 133 subtotal -= seconds; 134 restart: 135 if (Tcl_AsyncReady()) { 136 int rc = Tcl_AsyncInvoke(interp,TCL_OK); 137 if (rc != TCL_OK) return(rc); 138 } 139 sleep(seconds); 140 return TCL_OK; 141} 142 143#if 0 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. */ 149int /* returns TCL_XXX */ 150exp_usleep(interp,usec) 151Tcl_Interp *interp; 152long usec; /* microseconds */ 153{ 154 static subtotal = 0; 155 int seconds; 156 157 subtotal += usec; 158 if (subtotal < 1000000) return TCL_OK; 159 seconds = subtotal/1000000; 160 subtotal = subtotal%1000000; 161 restart: 162 if (Tcl_AsyncReady()) { 163 int rc = Tcl_AsyncInvoke(interp,TCL_OK); 164 if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc)); 165 } 166 sleep(seconds); 167 return TCL_OK; 168} 169#endif /*0*/ 170 171/* set things up for later calls to event handler */ 172void 173exp_init_event() 174{ 175 exp_event_exit = 0; 176} 177