35
35
#include "exp_prog.h"
36
36
#include "exp_command.h"
37
37
#include "exp_log.h"
38
#include "tcldbg.h" /* Dbg_StdinMode */
40
extern int expSetBlockModeProc _ANSI_ARGS_((int fd, int mode));
39
41
static int ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData,
41
43
static int ExpCloseProc _ANSI_ARGS_((ClientData instanceData,
57
59
Tcl_ChannelType expChannelType = {
58
60
"exp", /* Type name. */
60
/* Tcl_ChannelType was redefined in 8.3.2 but Tcl does not
61
advertise its patch level in a useful way so for simplicity,
62
assume 8.3 is a modern 8.3, i.e. 8.3.2
65
#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 3))
66
TCL_CHANNEL_VERSION_2,
67
ExpCloseProc, /* Close proc. */
68
ExpInputProc, /* Input proc. */
69
ExpOutputProc, /* Output proc. */
70
NULL, /* Seek proc. */
71
NULL, /* Set option proc. */
72
NULL, /* Get option proc. */
73
ExpWatchProc, /* Initialize notifier. */
74
ExpGetHandleProc, /* Get OS handles out of channel. */
75
NULL, /* Close2 proc */
76
ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
77
NULL, /* Flush proc. */
78
NULL, /* Handle channel event proc. */
80
/* Expect channels are always non-blocking */
81
ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
82
ExpCloseProc, /* Close proc. */
83
ExpInputProc, /* Input proc. */
84
ExpOutputProc, /* Output proc. */
85
NULL, /* Seek proc. */
86
NULL, /* Set option proc. */
87
NULL, /* Get option proc. */
88
ExpWatchProc, /* Initialize notifier. */
89
ExpGetHandleProc, /* Get OS handles out of channel. */
90
NULL, /* Close2 proc */
61
ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
62
ExpCloseProc, /* Close proc. */
63
ExpInputProc, /* Input proc. */
64
ExpOutputProc, /* Output proc. */
65
NULL, /* Seek proc. */
66
NULL, /* Set option proc. */
67
NULL, /* Get option proc. */
68
ExpWatchProc, /* Initialize notifier. */
69
ExpGetHandleProc, /* Get OS handles out of channel. */
70
NULL, /* Close2 proc */
94
73
typedef struct ThreadSpecificData {
131
110
* TCL_MODE_NONBLOCKING. */
133
112
ExpState *esPtr = (ExpState *) instanceData;
114
if (esPtr->fdin == 0) {
115
/* Forward status to debugger. Required for FIONBIO systems,
116
* which are unable to query the fd for its current state.
118
Dbg_StdinMode (mode);
121
/* [Expect SF Bug 1108551] (July 7 2005)
122
* Exclude manipulation of the blocking status for stdin/stderr.
124
* This is handled by the Tcl core itself and we must absolutely
125
* not pull the rug out from under it. The standard setting to
126
* non-blocking will mess with the core which had them set to
127
* blocking, and makes all its decisions based on that assumption.
128
* Setting to non-blocking can cause hangs and crashes.
130
* Stdin is ok however, apparently.
131
* (Sep 9 2005) No, it is not.
134
if ((esPtr->fdin == 0) ||
135
(esPtr->fdin == 1) ||
136
(esPtr->fdin == 2)) {
140
return expSetBlockModeProc (esPtr->fdin, mode);
144
expSetBlockModeProc(fd, mode)
146
int mode; /* The mode to set. Can be one of
147
* TCL_MODE_BLOCKING or
148
* TCL_MODE_NONBLOCKING. */
135
151
/*printf("ExpBlockModeProc(%d)\n",mode);
136
printf("fdin = %d\n",esPtr->fdin);*/
152
printf("fdin = %d\n",fd);*/
138
154
#ifndef USE_FIONBIO
139
curStatus = fcntl(esPtr->fdin, F_GETFL);
155
curStatus = fcntl(fd, F_GETFL);
140
156
/*printf("curStatus = %d\n",curStatus);*/
141
157
if (mode == TCL_MODE_BLOCKING) {
142
158
curStatus &= (~(O_NONBLOCK));
144
160
curStatus |= O_NONBLOCK;
146
162
/*printf("new curStatus %d\n",curStatus);*/
147
if (fcntl(esPtr->fdin, F_SETFL, curStatus) < 0) {
163
if (fcntl(fd, F_SETFL, curStatus) < 0) {
150
curStatus = fcntl(esPtr->fdin, F_GETFL);
166
curStatus = fcntl(fd, F_GETFL);
151
167
#else /* USE_FIONBIO */
152
168
if (mode == TCL_MODE_BLOCKING) {
157
if (ioctl(esPtr->fdin, (int) FIONBIO, &curStatus) < 0) {
173
if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) {
160
176
#endif /* !USE_FIONBIO */
165
180
*----------------------------------------------------------------------
428
447
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
429
448
return tsdPtr->channelCount;
450
#if 0 /* Converted to macros */
433
452
expSizeGet(esPtr)
437
Tcl_GetStringFromObj(esPtr->buffer,&len);
455
return esPtr->input.use;
442
459
expSizeZero(esPtr)
446
Tcl_GetStringFromObj(esPtr->buffer,&len);
462
return (esPtr->input.use == 0);
450
465
/* return 0 for success or negative for failure */
452
467
expWriteChars(esPtr,buffer,lenBytes)
459
474
rc = Tcl_WriteChars(esPtr->channel,buffer,lenBytes);
460
475
if ((rc == -1) && (errno == EAGAIN)) goto retry;
477
if (!exp_strict_write) {
479
* 5.41 compatbility behaviour. Ignore any and all write errors
480
* the OS may have thrown.
462
485
/* just return 0 rather than positive byte counts */
463
486
return ((rc > 0) ? 0 : rc);
490
expWriteCharsUni(esPtr,buffer,lenChars)
498
Tcl_DStringInit (&ds);
499
Tcl_UniCharToUtfDString (buffer,lenChars,&ds);
501
rc = expWriteChars(esPtr,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds));
503
Tcl_DStringFree (&ds);
467
509
expStateFree(esPtr)
616
661
Tcl_SetChannelOption(interp,esPtr->channel,"-translation","lf");
618
663
esPtr->pid = pid;
621
/* initialize a dummy buffer */
622
esPtr->buffer = Tcl_NewStringObj("",0);
623
Tcl_IncrRefCount(esPtr->buffer);
665
esPtr->input.max = 1;
666
esPtr->input.use = 0;
667
esPtr->input.buffer = (Tcl_UniChar*) Tcl_Alloc (sizeof (Tcl_UniChar));
668
esPtr->input.newchars = Tcl_NewObj();
669
Tcl_IncrRefCount (esPtr->input.newchars);
624
671
esPtr->umsize = exp_default_match_max;
625
672
/* this will reallocate object with an appropriate sized buffer */
626
673
expAdjust(esPtr);