|
Packit |
a69f91 |
/* interact (with only one process) - give user keyboard control
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Written by: Don Libes, NIST, 2/6/90
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Design and implementation of this program was paid for by U.S. tax
|
|
Packit |
a69f91 |
dollars. Therefore it is public domain. However, the author and NIST
|
|
Packit |
a69f91 |
would appreciate credit if this program or parts of it are used.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* This file exists for deficient versions of UNIX that lack select,
|
|
Packit |
a69f91 |
poll, or some other multiplexing hook. Instead, this code uses two
|
|
Packit |
a69f91 |
processes per spawned process. One sends characters from the spawnee
|
|
Packit |
a69f91 |
to the spawner; a second send chars the other way.
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
This will work on any UNIX system. The only sacrifice is that it
|
|
Packit |
a69f91 |
doesn't support multiple processes. Eventually, it should catch
|
|
Packit |
a69f91 |
SIGCHLD on dead processes and do the right thing. But it is pretty
|
|
Packit |
a69f91 |
gruesome to imagine so many processes to do all this. If you change
|
|
Packit |
a69f91 |
it successfully, please mail back the changes to me. - Don
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "expect_cf.h"
|
|
Packit |
a69f91 |
#include <stdio.h>
|
|
Packit |
a69f91 |
#include <sys/types.h>
|
|
Packit |
a69f91 |
#include <sys/time.h>
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef HAVE_SYS_WAIT_H
|
|
Packit |
a69f91 |
#include <sys/wait.h>
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "tcl.h"
|
|
Packit |
a69f91 |
#include "exp_prog.h"
|
|
Packit |
a69f91 |
#include "exp_command.h" /* for struct ExpState defs */
|
|
Packit |
a69f91 |
#include "exp_event.h"
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_arm_background_filehandler(esPtr)
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_disarm_background_filehandler(esPtr)
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_disarm_background_filehandler_force(esPtr)
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_unblock_background_filehandler(esPtr)
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_block_background_filehandler(esPtr)
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_event_disarm(fd)
|
|
Packit |
a69f91 |
int fd;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
ExpState (*esPtrs)[];
|
|
Packit |
a69f91 |
int n; /* # of esPtrs */
|
|
Packit |
a69f91 |
ExpState **esPtrOut; /* 1st event master, not set if none */
|
|
Packit |
a69f91 |
int timeout; /* seconds */
|
|
Packit |
a69f91 |
int key;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (n > 1) {
|
|
Packit |
a69f91 |
exp_error(interp,"expect not compiled with multiprocess support");
|
|
Packit |
a69f91 |
/* select a different INTERACT_TYPE in Makefile */
|
|
Packit |
a69f91 |
return(TCL_ERROR);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
esPtr = *esPtrOut = esPtrs[0];
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (esPtr->key != key) {
|
|
Packit |
a69f91 |
esPtr->key = key;
|
|
Packit |
a69f91 |
esPtr->force_read = FALSE;
|
|
Packit |
a69f91 |
return(EXP_DATA_OLD);
|
|
Packit |
a69f91 |
} else if ((!esPtr->force_read) && (esPtr->size != 0)) {
|
|
Packit |
a69f91 |
return(EXP_DATA_OLD);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
return(EXP_DATA_NEW);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_get_next_event_info(interp,esPtr,ready_mask)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
ExpState *esPtr;
|
|
Packit |
a69f91 |
int ready_mask;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* There is no portable way to do sub-second sleeps on such a system, so */
|
|
Packit |
a69f91 |
/* do the next best thing (without a busy loop) and fake it: sleep the right */
|
|
Packit |
a69f91 |
/* amount of time over the long run. Note that while "subtotal" isn't */
|
|
Packit |
a69f91 |
/* reinitialized, it really doesn't matter for such a gross hack as random */
|
|
Packit |
a69f91 |
/* scheduling pauses will easily introduce occasional one second delays. */
|
|
Packit |
a69f91 |
int /* returns TCL_XXX */
|
|
Packit |
a69f91 |
exp_dsleep(interp,sec)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
double sec;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static double subtotal = 0;
|
|
Packit |
a69f91 |
int seconds;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
subtotal += sec;
|
|
Packit |
a69f91 |
if (subtotal < 1) return TCL_OK;
|
|
Packit |
a69f91 |
seconds = subtotal;
|
|
Packit |
a69f91 |
subtotal -= seconds;
|
|
Packit |
a69f91 |
restart:
|
|
Packit |
a69f91 |
if (Tcl_AsyncReady()) {
|
|
Packit |
a69f91 |
int rc = Tcl_AsyncInvoke(interp,TCL_OK);
|
|
Packit |
a69f91 |
if (rc != TCL_OK) return(rc);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
sleep(seconds);
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#if 0
|
|
Packit |
a69f91 |
/* There is no portable way to do sub-second sleeps on such a system, so */
|
|
Packit |
a69f91 |
/* do the next best thing (without a busy loop) and fake it: sleep the right */
|
|
Packit |
a69f91 |
/* amount of time over the long run. Note that while "subtotal" isn't */
|
|
Packit |
a69f91 |
/* reinitialized, it really doesn't matter for such a gross hack as random */
|
|
Packit |
a69f91 |
/* scheduling pauses will easily introduce occasional one second delays. */
|
|
Packit |
a69f91 |
int /* returns TCL_XXX */
|
|
Packit |
a69f91 |
exp_usleep(interp,usec)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
long usec; /* microseconds */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static subtotal = 0;
|
|
Packit |
a69f91 |
int seconds;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
subtotal += usec;
|
|
Packit |
a69f91 |
if (subtotal < 1000000) return TCL_OK;
|
|
Packit |
a69f91 |
seconds = subtotal/1000000;
|
|
Packit |
a69f91 |
subtotal = subtotal%1000000;
|
|
Packit |
a69f91 |
restart:
|
|
Packit |
a69f91 |
if (Tcl_AsyncReady()) {
|
|
Packit |
a69f91 |
int rc = Tcl_AsyncInvoke(interp,TCL_OK);
|
|
Packit |
a69f91 |
if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
sleep(seconds);
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif /*0*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* set things up for later calls to event handler */
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_event()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
exp_event_exit = 0;
|
|
Packit |
a69f91 |
}
|