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