Expect

Changes On Branch expect-sf418892-sf439042-branch
Login

Changes On Branch expect-sf418892-sf439042-branch

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch expect-sf418892-sf439042-branch Excluding Merge-Ins

This is equivalent to a diff from 4a5c83adb9 to e13848e868

2002-02-25
23:21
* expect.c: Applied patch by Don Libes fixing improper internationalization. Leaf check-in: e13848e868 user: andreas_kupries tags: trunk, expect-sf418892-sf439042-branch
2002-02-21
19:18
* expect.man: Changed the paragraph about [exp_continue] to contain information about the flag "-continue_timer". This fixes the bug SF #520630. check-in: 4fca3840d3 user: andreas_kupries tags: trunk, expect-sf418892-sf439042-branch
2001-09-13
01:06
moved from root check-in: 73c5ce26d6 user: davygrvy tags: trunk, win32-jump-point-1
2001-07-06
19:36
2001-06-05 Andreas Kupries <[email protected]> * exp_main_sub.c: Fixed bug [#418892]. check-in: 99ef534017 user: andreas_kupries tags: trunk, expect-sf418892-sf439042-branch
1999-06-07
17:49
Initial 8.1 changes. check-in: ccd6fc80e5 user: libes tags: trunk, master-UNNAMED-BRANCH
1998-10-14
22:53
Import of Expect v. 5.28.1 check-in: 4a5c83adb9 user: cvsadmin tags: trunk, master-UNNAMED-BRANCH
22:53
*** empty log message *** check-in: c9cbab5472 user: cvsadmin tags: trunk

Changes to ChangeLog.



















































































































1
2
3
4
5
6
7


















































































































Thu Mar 20 14:27:45 1997  Geoffrey Noer  <[email protected]>

	* configure.in: don't check if stty reads stdout for
	i[[3456]]86-*-sysv4.2MP during config; hard code instead
	
Tue Nov 19 09:22:08 1996  Tom Tromey  <[email protected]>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
2002-02-25  Andreas Kupries  <[email protected]>

	* expect.c: Applied patch by Don Libes fixing improper
	  internationalization.

2002-02-21  Andreas Kupries  <[email protected]>

	* expect.man: Changed the paragraph about [exp_continue] to
	  contain information about the flag "-continue_timer". This fixes
	  the bug SF #520630.

	* exp_main_sub.c (Expect_Init): Applied Don Porter's patch which
	  excludes the initialization of Tcl/Expect packages and the
	  creation of the ExitHandler from the 'firsttime' guard. This
	  allows the full use of Expect in slave-iterpreters. This fixes
	  the bug SF #459646.

2002-02-08  Andreas Kupries  <[email protected]>

	* expect.man: Changed abbreviation of "-notransfer" from "-n" to
	  "-not". "-n" is no longer unique due to the addition of
	  "-nocase". This fixes the bug SF #514994.

2002-02-07  Andreas Kupries  <[email protected]>

	* Applied patch for SF #514590 to correct behaviour of expect when
	  expecting and send from and to bogus spawn id's.

	* exp_log.c (expStdoutLogU): Use Tcl_WriteChars/Tcl_Flush instead
	  of 'fwrite' for tcl 8.1 and beyond to enforce correct conversion
	  of the internal UTF/8 into the external representation.

2002-01-16  Andreas Kupries  <[email protected]>

	* Resynchronization of SourceForge with Don's sources to Expect
	  version 5.34. The changes are

	  Don Porter <[email protected]> provided package-related fixes
	  for test suite.

	  Brian Theado <[email protected]> noted that interact's -re
	  support broke when offsets kicked in.  Turned out that the
	  regexp engine supports them during execution but the results are
	  delivered RELATIVE to the offset.  (I suspect this was done
	  due to expediency.)

2001-12-05  Andreas Kupries  <[email protected]>

	* exp_inter.c: Applied patch posted by Don libes to c.l.t. on his
	  behalf to keep the SF repository in sync with his changes. Don's
	  notes: I obviously missed the fact that although
	  "Tcl_RegExpExecObj" supports offsets, they aren't delivered to
	  "Tcl_RegExpGetInfo".

2001-08-01  Jeff Hobbs  <[email protected]>

	* Dbg.c (Dbg_On): fixed handling of stepping. [Bug: #446412]

2001-07-06  Andreas Kupries <[email protected]>

	* exp_main_exp.c:
	* exp_main_sub.c:
	* exp_main_tk.c:
	* exp_tty.c: Changed calls to 'Tcl_Exit' into calls to the command
	  [exit], to allow scripts and users to overide the functionality. 

2001-06-05  Andreas Kupries <[email protected]>

	* exp_main_sub.c: Fixed bug [#418892].
	
2000-04-26  Rob Savoye  <[email protected]>

	* pty_termios.h: Only include stropts.h if it exists, rather than
	deciding it exists based on HAVE_PTMX.
	* configure.in: Make sure libpt exists, rather than blindly using
	it for all our configure tests, which then all fail. Also assume
	our svr4 style ptys are broken, if /dev/ptmx exists, but stropts.h
	doesn't exist.
	
1999-08-31  Jennifer Hom  <[email protected]>

	* Makefile.in: Changed test target to source tests/all.tcl instead
	of tests/all

	* tests/README: Modified documentation to reflect the change from
	usage of a defs file to the use of package tcltest to run the tests

	* tests/all:
	* tests/defs:
	* tests/all.tcl:
	* tests/cat.test:
	* tests/expect.test:
	* tests/logfile.test:
	* tests/pid.test:
	* tests/send.test:
	* tests/spawn.test
	* tests/stty.test: Modified test files to use package tcltest, 
	removed tests/all and tests/defs, and added tests/all.tcl 

1999-06-22    <[email protected]>

	* expect.c: Fixed bug in token parsing where index was not being
	incremented properly.

	* configure.in: Changed version number to 5.31.

	* aclocal.m4: Fixed CY_AC_LOAD_TKCONFIG so it tests for Tk_Init
	instead of Tk_Main (which is only a macro in 8.1 and later).  Also
	added TCL_BUILD_LIB_SPEC to the set of flags used in this test to
	avoid linker errors.	

	* Dbgconfig.in: move CY_*_TCLCONFIG tests below AC_PROG_CC so it
	will work with gcc

Thu Mar 20 14:27:45 1997  Geoffrey Noer  <[email protected]>

	* configure.in: don't check if stty reads stdout for
	i[[3456]]86-*-sysv4.2MP during config; hard code instead
	
Tue Nov 19 09:22:08 1996  Tom Tromey  <[email protected]>

Changes to Dbg.c.

1
2
3
4
5
6
7
8


9
10
11
12
13
14
15
/* Dbg.c - Tcl Debugger - See cmdHelp() for commands

Written by: Don Libes, NIST, 3/23/93

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.



*/

#include <stdio.h>

#include "tcldbgcf.h"
#if 0
/* tclInt.h drags in stdlib.  By claiming no-stdlib, force it to drag in */








>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* Dbg.c - Tcl Debugger - See cmdHelp() for commands

Written by: Don Libes, NIST, 3/23/93

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.

 RCS: @(#) $Id: Dbg.c,v 5.31 2001/08/02 00:30:14 hobbs Exp $

*/

#include <stdio.h>

#include "tcldbgcf.h"
#if 0
/* tclInt.h drags in stdlib.  By claiming no-stdlib, force it to drag in */
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
/* every time a new debugger command is issued that is an action */
static debug_new_action;

#define NO_LINE -1	/* if break point is not set by line number */

struct breakpoint {
	int id;
	char *file;	/* file where breakpoint is */
	int line;	/* line where breakpoint is */

	char *pat;	/* pattern defining where breakpoint can be */
	regexp *re;	/* regular expression to trigger breakpoint */
	char *expr;	/* expr to trigger breakpoint */
	char *cmd;	/* cmd to eval at breakpoint */
	struct breakpoint *next, *previous;
};

static struct breakpoint *break_base = 0;
static int breakpoint_max_id = 0;

static struct breakpoint *







|

>
|
<
|
|







86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
/* every time a new debugger command is issued that is an action */
static debug_new_action;

#define NO_LINE -1	/* if break point is not set by line number */

struct breakpoint {
	int id;
	Tcl_Obj *file;	/* file where breakpoint is */
	int line;	/* line where breakpoint is */
	int re;		/* 1 if this is regexp pattern */
	Tcl_Obj *pat;	/* pattern defining where breakpoint can be */

	Tcl_Obj *expr;	/* expr to trigger breakpoint */
	Tcl_Obj *cmd;	/* cmd to eval at breakpoint */
	struct breakpoint *next, *previous;
};

static struct breakpoint *break_base = 0;
static int breakpoint_max_id = 0;

static struct breakpoint *
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153

154
155
156
157
158

159


160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180




181



182




183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

static
void
breakpoint_print(interp,b)
Tcl_Interp *interp;
struct breakpoint *b;
{
	print(interp,"breakpoint %d: ",b->id);

	if (b->re) {
		print(interp,"-re \"%s\" ",b->pat);
	} else if (b->pat) {
		print(interp,"-glob \"%s\" ",b->pat);
	} else if (b->line != NO_LINE) {
		if (b->file) {
			print(interp,"%s:",b->file);
		}
		print(interp,"%d ",b->line);
	}

	if (b->expr)
		print(interp,"if {%s} ",b->expr);

	if (b->cmd)
		print(interp,"then {%s}",b->cmd);

	print(interp,"\n");
}

static void
save_re_matches(interp,re)
Tcl_Interp *interp;
regexp *re;

{

	int i;
	char name[20];
	char match_char;/* place to hold char temporarily */
			/* uprooted by a NULL */


	for (i=0;i<NSUBEXP;i++) {


		if (re->startp[i] == 0) break;


		sprintf(name,"%d",i);
		/* temporarily null-terminate in middle */
		match_char = *re->endp[i];
		*re->endp[i] = 0;
		Tcl_SetVar2(interp,Dbg_VarName,name,re->startp[i],0);

		/* undo temporary null-terminator */
		*re->endp[i] = match_char;
	}
}

/* return 1 to break, 0 to continue */
static int
breakpoint_test(interp,cmd,bp)
Tcl_Interp *interp;
char *cmd;		/* command about to be executed */
struct breakpoint *bp;	/* breakpoint to test */
{
	if (bp->re) {




		if (0 == TclRegExec(bp->re,cmd,cmd)) return 0;



		save_re_matches(interp,bp->re);




	} else if (bp->pat) {
		if (0 == Tcl_StringMatch(cmd,bp->pat)) return 0;

	} else if (bp->line != NO_LINE) {
		/* not yet implemented - awaiting support from Tcl */
		return 0;
	}

	if (bp->expr) {
		int value;

		/* ignore errors, since they are likely due to */
		/* simply being out of scope a lot */
		if (TCL_OK != Tcl_ExprBoolean(interp,bp->expr,&value)
		    || (value == 0)) return 0;
	}

	if (bp->cmd) {
		Tcl_Eval(interp,bp->cmd);
	} else {
		breakpoint_print(interp,bp);
	}

	return 1;
}

static char *already_at_top_level = "already at top level";

/* similar to TclGetFrame but takes two frame ptrs and a direction.
If direction is up,   search up stack from curFrame
If direction is down, simulate searching down stack by







|

|
|
|
|
|
|
|
|
|
|

|
|

|
|

|



|

|
>

>
|
|
<
<

>
|
>
>
|
>

|
<
<
<
|
|
<
<
|









|
>
>
>
>
|
>
>
>
|
>
>
>
>
|
|
>
|
|
|
|

|
|

|
|
|
|
|

|
|
|
|
|

|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159


160
161
162
163
164
165
166
167
168



169
170


171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

static
void
breakpoint_print(interp,b)
Tcl_Interp *interp;
struct breakpoint *b;
{
    print(interp,"breakpoint %d: ",b->id);

    if (b->re) {
	print(interp,"-re \"%s\" ",Tcl_GetString(b->pat));
    } else if (b->pat) {
	print(interp,"-glob \"%s\" ",Tcl_GetString(b->pat));
    } else if (b->line != NO_LINE) {
	if (b->file) {
	    print(interp,"%s:",Tcl_GetString(b->file));
	}
	print(interp,"%d ",b->line);
    }

    if (b->expr)
	print(interp,"if {%s} ",Tcl_GetString(b->expr));

    if (b->cmd)
	print(interp,"then {%s}",Tcl_GetString(b->cmd));

    print(interp,"\n");
}

static void
save_re_matches(interp, re, objPtr)
Tcl_Interp *interp;
Tcl_RegExp re;
Tcl_Obj *objPtr;
{
    Tcl_RegExpInfo info;
    int i, start;
    char name[20];



    Tcl_RegExpGetInfo(re, &info); 
    for (i=0;i<=info.nsubs;i++) {
	start = info.matches[i].start;
	/* end = info.matches[i].end-1;*/

	if (start == -1) continue;

	sprintf(name,"%d",i);



	Tcl_SetVar2Ex(interp, Dbg_VarName, name, Tcl_GetRange(objPtr,
		info.matches[i].start, info.matches[i].end-1), 0);


    }
}

/* return 1 to break, 0 to continue */
static int
breakpoint_test(interp,cmd,bp)
Tcl_Interp *interp;
char *cmd;		/* command about to be executed */
struct breakpoint *bp;	/* breakpoint to test */
{
    if (bp->re) {
        int found = 0;
	Tcl_Obj *cmdObj;
	Tcl_RegExp re = Tcl_GetRegExpFromObj(NULL, bp->pat,
		TCL_REG_ADVANCED);
	cmdObj = Tcl_NewStringObj(cmd,-1);
	Tcl_IncrRefCount(cmdObj);
	if (Tcl_RegExpExecObj(NULL, re, cmdObj, 0 /* offset */,
		-1 /* nmatches */, 0 /* eflags */) > 0) {
	    save_re_matches(interp, re, cmdObj);
	    found = 1;
	}
	Tcl_DecrRefCount(cmdObj);
	if (!found) return 0;
    } else if (bp->pat) {
	if (0 == Tcl_StringMatch(cmd,
		Tcl_GetString(bp->pat))) return 0;
    } else if (bp->line != NO_LINE) {
	/* not yet implemented - awaiting support from Tcl */
	return 0;
    }

    if (bp->expr) {
	int value;

	/* ignore errors, since they are likely due to */
	/* simply being out of scope a lot */
	if (TCL_OK != Tcl_ExprBooleanObj(interp,bp->expr,&value)
		|| (value == 0)) return 0;
    }

    if (bp->cmd) {
	Tcl_EvalObjEx(interp, bp->cmd, 0);
    } else {
	breakpoint_print(interp,bp);
    }

    return 1;
}

static char *already_at_top_level = "already at top level";

/* similar to TclGetFrame but takes two frame ptrs and a direction.
If direction is up,   search up stack from curFrame
If direction is down, simulate searching down stack by
287
288
289
290
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330


331
332
333
334
335
336
337
338
339
340
341
342
343
    return result;
}


static char *printify(s)
char *s;
{
	static int destlen = 0;
	char *d;		/* ptr into dest */
	unsigned int need;
	static char buf_basic[DEFAULT_WIDTH+1];
	static char *dest = buf_basic;


	if (s == 0) return("<null>");

	/* worst case is every character takes 4 to printify */
	need = strlen(s)*4;
	if (need > destlen) {
		if (dest && (dest != buf_basic)) ckfree(dest);
		dest = (char *)ckalloc(need+1);
		destlen = need;
	}

	for (d = dest;*s;s++) {
		/* since we check at worst by every 4 bytes, play */
		/* conservative and subtract 4 from the limit */
		if (d-dest > destlen-4) break;

		if (*s == '\b') {
			strcpy(d,"\\b");		d += 2;
		} else if (*s == '\f') {
			strcpy(d,"\\f");		d += 2;
		} else if (*s == '\v') {
			strcpy(d,"\\v");		d += 2;
		} else if (*s == '\r') {
			strcpy(d,"\\r");		d += 2;
		} else if (*s == '\n') {
			strcpy(d,"\\n");		d += 2;
		} else if (*s == '\t') {
			strcpy(d,"\\t");		d += 2;
		} else if ((unsigned)*s < 0x20) { /* unsigned strips parity */
			sprintf(d,"\\%03o",*s);		d += 4;
		} else if (*s == 0177) {
			strcpy(d,"\\177");		d += 4;


		} else {
			*d = *s;			d += 1;
		}
	}
	*d = '\0';
	return(dest);
}

static
char *
print_argv(interp,argc,argv)
Tcl_Interp *interp;
int argc;







|
|
|
|
|
>

|

|
|
|
|
|
|
|

|
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324



325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    return result;
}


static char *printify(s)
char *s;
{
    static int destlen = 0;
    char *d;		/* ptr into dest */
    unsigned int need;
    static char buf_basic[DEFAULT_WIDTH+1];
    static char *dest = buf_basic;
    Tcl_UniChar ch;

    if (s == 0) return("<null>");

    /* worst case is every character takes 4 to printify */
    need = strlen(s)*6;
    if (need > destlen) {
	if (dest && (dest != buf_basic)) ckfree(dest);
	dest = (char *)ckalloc(need+1);
	destlen = need;
    }

    for (d = dest;*s;) {



	s += Tcl_UtfToUniChar(s, &ch);
	if (ch == '\b') {
	    strcpy(d,"\\b");		d += 2;
	} else if (ch == '\f') {
	    strcpy(d,"\\f");		d += 2;
	} else if (ch == '\v') {
	    strcpy(d,"\\v");		d += 2;
	} else if (ch == '\r') {
	    strcpy(d,"\\r");		d += 2;
	} else if (ch == '\n') {
	    strcpy(d,"\\n");		d += 2;
	} else if (ch == '\t') {
	    strcpy(d,"\\t");		d += 2;
	} else if ((unsigned)ch < 0x20) { /* unsigned strips parity */
	    sprintf(d,"\\%03o",ch);		d += 4;
	} else if (ch == 0177) {
	    strcpy(d,"\\177");		d += 4;
	} else if ((ch < 0x80) && isprint(UCHAR(ch))) {
	    *d = (char)ch;		d += 1;
	} else {
	    sprintf(d,"\\u%04x",ch);	d += 6;
	}
    }
    *d = '\0';
    return(dest);
}

static
char *
print_argv(interp,argc,argv)
Tcl_Interp *interp;
int argc;
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
	len = strlen(buf);
	space = buf_width - len;
	bufp = buf + len;
	argc--; argv++;
	arg_index = 1;
	
	while (argc && (space > 0)) {
		char *elementPtr;
		char *nextPtr;
		int wrap;

		/* braces/quotes have been stripped off arguments */
		/* so put them back.  We wrap everything except lists */
		/* with one argument.  One exception is to always wrap */
		/* proc's 2nd arg (the arg list), since people are */
		/* used to always seeing it this way. */







|
|







376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	len = strlen(buf);
	space = buf_width - len;
	bufp = buf + len;
	argc--; argv++;
	arg_index = 1;
	
	while (argc && (space > 0)) {
		CONST char *elementPtr;
		CONST char *nextPtr;
		int wrap;

		/* braces/quotes have been stripped off arguments */
		/* so put them back.  We wrap everything except lists */
		/* with one argument.  One exception is to always wrap */
		/* proc's 2nd arg (the arg list), since people are */
		/* used to always seeing it this way. */
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
Tcl_Interp *interp;
int objc;
Tcl_Obj *objv[];
{
    char **argv;
    int argc;
    int len;
    argv = ckalloc(objc+1 * sizeof(char *));
    for (argc=0 ; argc<objc ; argc++) {
	argv[argc] = Tcl_GetStringFromObj(objv[argc],&len);
    }
    argv[argc] = NULL;
    return(print_argv(interp,argc,argv));
}
#endif







|







438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
Tcl_Interp *interp;
int objc;
Tcl_Obj *objv[];
{
    char **argv;
    int argc;
    int len;
    argv = (char **)ckalloc(objc+1 * sizeof(char *));
    for (argc=0 ; argc<objc ; argc++) {
	argv[argc] = Tcl_GetStringFromObj(objv[argc],&len);
    }
    argv[argc] = NULL;
    return(print_argv(interp,argc,argv));
}
#endif
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
}

static
void
breakpoint_destroy(b)
struct breakpoint *b;
{
	if (b->file) ckfree(b->file);
	if (b->pat) ckfree(b->pat);
	if (b->re) ckfree((char *)b->re);			
	if (b->cmd) ckfree(b->cmd);

	/* unlink from chain */
	if ((b->previous == 0) && (b->next == 0)) {
		break_base = 0;
	} else if (b->previous == 0) {
		break_base = b->next;
		b->next->previous = 0;
	} else if (b->next == 0) {
		b->previous->next = 0;
	} else {
		b->previous->next = b->next;
		b->next->previous = b->previous;
	}

	ckfree((char *)b);
}

static void
savestr(straddr,str)
char **straddr;
char *str;
{
	*straddr = ckalloc(strlen(str)+1);
	strcpy(*straddr,str);
}

/* return 1 if a string is substring of a flag */
static int
flageq(flag,string,minlen)
char *flag;
char *string;







|
|
|
|


















|
|


|
|







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
}

static
void
breakpoint_destroy(b)
struct breakpoint *b;
{
	if (b->file) Tcl_DecrRefCount(b->file);
	if (b->pat) Tcl_DecrRefCount(b->pat);
	if (b->cmd) Tcl_DecrRefCount(b->cmd);
	if (b->expr) Tcl_DecrRefCount(b->expr);

	/* unlink from chain */
	if ((b->previous == 0) && (b->next == 0)) {
		break_base = 0;
	} else if (b->previous == 0) {
		break_base = b->next;
		b->next->previous = 0;
	} else if (b->next == 0) {
		b->previous->next = 0;
	} else {
		b->previous->next = b->next;
		b->next->previous = b->previous;
	}

	ckfree((char *)b);
}

static void
savestr(objPtr,str)
Tcl_Obj **objPtr;
char *str;
{
    *objPtr = Tcl_NewStringObj(str, -1);
    Tcl_IncrRefCount(*objPtr);
}

/* return 1 if a string is substring of a flag */
static int
flageq(flag,string,minlen)
char *flag;
char *string;
876
877
878
879
880
881
882
883

884





885
886
887
888
889
890
891
892
		}
	}

	b = breakpoint_new();

	if (flageq("-regexp",argv[0],2)) {
		argc--; argv++;
		if ((argc > 0) && (b->re = TclRegComp(argv[0]))) {

			savestr(&b->pat,argv[0]);





			argc--; argv++;
		} else {
			breakpoint_fail("bad regular expression")
		}
	} else if (flageq("-glob",argv[0],2)) {
		argc--; argv++;
		if (argc > 0) {
			savestr(&b->pat,argv[0]);







|
>
|
>
>
>
>
>
|







889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
		}
	}

	b = breakpoint_new();

	if (flageq("-regexp",argv[0],2)) {
		argc--; argv++;
		if (argc > 0) {
		    b->re = 1;
		    savestr(&b->pat,argv[0]);
		    if (Tcl_GetRegExpFromObj(interp, b->pat, TCL_REG_ADVANCED)
			    == NULL) {
			breakpoint_destroy(b);
			return TCL_ERROR;
		    }
		    argc--; argv++;
		} else {
			breakpoint_fail("bad regular expression")
		}
	} else if (flageq("-glob",argv[0],2)) {
		argc--; argv++;
		if (argc > 0) {
			savestr(&b->pat,argv[0]);
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

		if (TCL_OK == Tcl_GetInt(interp,linep,&b->line)) {
			argc--; argv++;
			print(interp,"setting breakpoints by line number is currently unimplemented - use patterns or expressions\n");
		} else {
			/* not an int? - unwind & assume it is an expression */

			if (b->file) ckfree(b->file);
		}
	}

	if (argc > 0) {
		int do_if = FALSE;

		if (flageq("if",argv[0],1)) {







|







932
933
934
935
936
937
938
939
940
941
942
943
944
945
946

		if (TCL_OK == Tcl_GetInt(interp,linep,&b->line)) {
			argc--; argv++;
			print(interp,"setting breakpoints by line number is currently unimplemented - use patterns or expressions\n");
		} else {
			/* not an int? - unwind & assume it is an expression */

			if (b->file) Tcl_DecrRefCount(b->file);
		}
	}

	if (argc > 0) {
		int do_if = FALSE;

		if (flageq("if",argv[0],1)) {
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286

1287
1288
1289
1290
1291
1292
1293
1294
1295
Tcl_Interp *interp;
int immediate;		/* if true, stop immediately */
			/* should only be used in safe places */
			/* i.e., when Tcl_Eval can be called */
{
	if (!debugger_active) init_debugger(interp);

	/* intuitively, it would seem natural to initialize the
	debugger with the step command.  However, it's too late at

	this point.  It must be done before the command reader

	(whatever it is) has gotten control. */
	/* debug_cmd = step;*/
	step_count = 1;

	if (immediate) {
		static char *fake_cmd = "--interrupted-- (command_unknown)";

		debugger_trap((ClientData)0,interp,-1,fake_cmd,(int (*)())0,
					(ClientData)0,1,&fake_cmd);







|
<
>
|
>
|
|







1296
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
Tcl_Interp *interp;
int immediate;		/* if true, stop immediately */
			/* should only be used in safe places */
			/* i.e., when Tcl_Eval can be called */
{
	if (!debugger_active) init_debugger(interp);

	/* Initialize debugger in single-step mode.

	 *
	 * Note: if the command reader is already active, it's too late
	 * which is why we also statically initialize debug_cmd to step.
	 */
	debug_cmd = step; 
	step_count = 1;

	if (immediate) {
		static char *fake_cmd = "--interrupted-- (command_unknown)";

		debugger_trap((ClientData)0,interp,-1,fake_cmd,(int (*)())0,
					(ClientData)0,1,&fake_cmd);

Changes to DbgMkfl.in.

208
209
210
211
212
213
214




215
216
217
218
219
220
221

######################################
# Targets for pushing out releases
######################################

FTPDIR = /proj/itl/www/div826/subject/expect/tcl-debug





ftp:	tcl-debug-$(VERSION).tar.Z tcl-debug-$(VERSION).tar.gz
	cp tcl-debug-$(VERSION).tar.Z $(FTPDIR)/tcl-debug.tar.Z
	cp tcl-debug-$(VERSION).tar.gz $(FTPDIR)/tcl-debug.tar.gz
	cp HISTORY $(FTPDIR)
	cp README $(FTPDIR)/README.distribution
	rm tcl-debug-$(VERSION).tar*
	ls -l $(FTPDIR)/tcl-debug.tar*







>
>
>
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

######################################
# Targets for pushing out releases
######################################

FTPDIR = /proj/itl/www/div826/subject/expect/tcl-debug

# make a private tar file for myself
tar:	tcl-debug-$(VERSION).tar
	mv tcl-debug-$(VERSION).tar tcl-debug.tar

ftp:	tcl-debug-$(VERSION).tar.Z tcl-debug-$(VERSION).tar.gz
	cp tcl-debug-$(VERSION).tar.Z $(FTPDIR)/tcl-debug.tar.Z
	cp tcl-debug-$(VERSION).tar.gz $(FTPDIR)/tcl-debug.tar.gz
	cp HISTORY $(FTPDIR)
	cp README $(FTPDIR)/README.distribution
	rm tcl-debug-$(VERSION).tar*
	ls -l $(FTPDIR)/tcl-debug.tar*

Changes to Dbgconfig.in.

1
2
3
4
5
6
7
8
9
10
11
12
13




14
15
16
17
18
19
20
21
22
23
24
25
dnl Process this file with autoconf to produce a configure script.

AC_INIT(tcldbg.h)

DBG_MAJOR_VERSION=1
DBG_MINOR_VERSION=9
DBG_MICRO_VERSION=1
DBG_VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION
DBG_VERSION_FULL=$DBG_VERSION.$DBG_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION

AC_CONFIG_HEADER(tcldbgcf.h)





CY_AC_PATH_TCLCONFIG
CY_AC_LOAD_TCLCONFIG
CC=$TCL_CC
AC_PROG_CC
CY_AC_C_WORKS

# this'll use a BSD compatible install or our included install-sh
AC_PROG_INSTALL

# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
AC_PROG_RANLIB













>
>
>
>




<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
dnl Process this file with autoconf to produce a configure script.

AC_INIT(tcldbg.h)

DBG_MAJOR_VERSION=1
DBG_MINOR_VERSION=9
DBG_MICRO_VERSION=1
DBG_VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION
DBG_VERSION_FULL=$DBG_VERSION.$DBG_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION

AC_CONFIG_HEADER(tcldbgcf.h)

OLD_CFLAGS=$CFLAGS
AC_PROG_CC
CFLAGS=$OLD_CFLAGS

CY_AC_PATH_TCLCONFIG
CY_AC_LOAD_TCLCONFIG
CC=$TCL_CC

CY_AC_C_WORKS

# this'll use a BSD compatible install or our included install-sh
AC_PROG_INSTALL

# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
AC_PROG_RANLIB

Changes to Dbgconfigure.

1
2
3
4
5
6
7
8
9
10
11
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.11 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=



|







1
2
3
4
5
6
7
8
9
10
11
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.9 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12

ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then







<
<







55
56
57
58
59
60
61


62
63
64
65
66
67
68
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=



ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.11"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }







|







336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.9"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
531
532
533
534
535
536
537






























































































































538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
DBG_VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION
DBG_VERSION_FULL=$DBG_VERSION.$DBG_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION


































































































































#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tclconfig
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  # Check whether --with-tclconfig or --without-tclconfig was given.
if test "${with_tclconfig+set}" = set; then
  withval="$with_tclconfig"
  with_tclconfig=${withval}
fi

  echo $ac_n "checking for Tcl configuration""... $ac_c" 1>&6
echo "configure:556: checking for Tcl configuration" >&5
  if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tclconfig was specified.
  if test x"${with_tclconfig}" != x ; then







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















<







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678

679
680
681
682
683
684
685
DBG_VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION
DBG_VERSION_FULL=$DBG_VERSION.$DBG_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$DBG_MAJOR_VERSION.$DBG_MINOR_VERSION



OLD_CFLAGS=$CFLAGS
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  ac_prog_rejected=no
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"
      break
    fi
  done
  IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# -gt 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    set dummy "$ac_dir/$ac_word" "$@"
    shift
    ac_cv_prog_CC="$@"
  fi
fi
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:624: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6
if test $ac_cv_prog_gcc = yes; then
  GCC=yes
  if test "${CFLAGS+set}" != set; then
    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_gcc_g=yes
else
  ac_cv_prog_gcc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
    if test $ac_cv_prog_gcc_g = yes; then
      CFLAGS="-g -O"
    else
      CFLAGS="-O"
    fi
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"
fi

CFLAGS=$OLD_CFLAGS


#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tclconfig
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  # Check whether --with-tclconfig or --without-tclconfig was given.
if test "${with_tclconfig+set}" = set; then
  withval="$with_tclconfig"
  with_tclconfig=${withval}
fi

  echo $ac_n "checking for Tcl configuration""... $ac_c" 1>&6

  if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tclconfig was specified.
  if test x"${with_tclconfig}" != x ; then
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642



643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920

    
    
    





    

# Tcl defines TCL_SHLIB_SUFFIX but TCL_SHARED_LIB_SUFFIX then looks for it
# as just SHLIB_SUFFIX.  How bizarre.
    SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
    

    

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""



echo $ac_n "checking for Tcl_CreateCommand""... $ac_c" 1>&6
echo "configure:645: checking for Tcl_CreateCommand" >&5
if eval "test \"`echo '$''{'ac_cv_func_Tcl_CreateCommand'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 650 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char Tcl_CreateCommand(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char Tcl_CreateCommand();

int main() {


/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_Tcl_CreateCommand) || defined (__stub___Tcl_CreateCommand)
choke me
#else
Tcl_CreateCommand();
#endif

; return 0; }
EOF
if { (eval echo configure:673: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'Tcl_CreateCommand`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:689: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""yes" 1>&6

else
  echo "$ac_t""no" 1>&6

	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:699: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""no" 1>&6

fi

LIBS=$SAVELIBS

    
    

    


CC=$TCL_CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:716: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:745: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  ac_prog_rejected=no
  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"
      break
    fi
  done
  IFS="$ac_save_ifs"
if test $ac_prog_rejected = yes; then
  # We found a bogon in the path, so make sure we never use it.
  set dummy $ac_cv_prog_CC
  shift
  if test $# -gt 0; then
    # We chose a different compiler from the bogus one.
    # However, it has the same basename, so the bogon will be chosen
    # first if we set CC to just the basename; use the full file name.
    shift
    set dummy "$ac_dir/$ac_word" "$@"
    shift
    ac_cv_prog_CC="$@"
  fi
fi
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:793: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'

cat > conftest.$ac_ext <<EOF
#line 802 "configure"
#include "confdefs.h"

int main() {

; return 0; }
EOF
if { (eval echo configure:809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  ac_cv_prog_cc_works=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_prog_cc_works=no
fi
rm -f conftest*


echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: Installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi

echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:827: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:836: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes
  ac_test_CFLAGS="${CFLAGS+set}"
  ac_save_CFLAGS="$CFLAGS"
  CFLAGS=
  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:851: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_gcc_g=yes
else
  ac_cv_prog_gcc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
  if test "$ac_test_CFLAGS" = set; then
    CFLAGS="$ac_save_CFLAGS"
  elif test $ac_cv_prog_gcc_g = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-O2"
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"
fi

# If we cannot compile and link a trivial program, we can't expect anything to work
echo $ac_n "checking whether the compiler ($CC) actually works""... $ac_c" 1>&6
echo "configure:880: checking whether the compiler ($CC) actually works" >&5
cat > conftest.$ac_ext <<EOF
#line 882 "configure"
#include "confdefs.h"

int main() {

/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:889: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  c_compiles=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_compiles=no
fi
rm -f conftest*


cat > conftest.$ac_ext <<EOF
#line 902 "configure"
#include "confdefs.h"

int main() {

/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  c_links=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_links=no
fi
rm -f conftest*


if test x"${c_compiles}" = x"no" ; then







|















>
>
>

<




|





<
<


|
>












|



<
<










<









<













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<

|


|
>



|



<
<







|


|
>



|



<
<







743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779


780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799


800
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826
827
828
829
830
831





































































































































































832
833

834
835
836
837
838
839
840
841
842
843
844
845
846


847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865


866
867
868
869
870
871
872

    
    
    



    

    

# Tcl defines TCL_SHLIB_SUFFIX but TCL_SHARED_LIB_SUFFIX then looks for it
# as just SHLIB_SUFFIX.  How bizarre.
    SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
    

    

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""
echo $ac_n "checking Tcl build library""... $ac_c" 1>&6
echo "$ac_t""$LIBS" 1>&6

echo $ac_n "checking for Tcl_CreateCommand""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_func_Tcl_CreateCommand'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 775 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char Tcl_CreateCommand(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */


char Tcl_CreateCommand();

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_Tcl_CreateCommand) || defined (__stub___Tcl_CreateCommand)
choke me
#else
Tcl_CreateCommand();
#endif

; return 0; }
EOF
if { (eval echo configure:797: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=yes"
else


  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'Tcl_CreateCommand`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6

	echo "$ac_t""yes" 1>&6

else
  echo "$ac_t""no" 1>&6

	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6

	echo "$ac_t""no" 1>&6

fi

LIBS=$SAVELIBS

    
    

    


CC=$TCL_CC





































































































































































# If we cannot compile and link a trivial program, we can't expect anything to work
echo $ac_n "checking whether the compiler ($CC) actually works""... $ac_c" 1>&6

cat > conftest.$ac_ext <<EOF
#line 836 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  c_compiles=yes
else


  rm -rf conftest*
  c_compiles=no
fi
rm -f conftest*


cat > conftest.$ac_ext <<EOF
#line 855 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
  rm -rf conftest*
  c_links=yes
else


  rm -rf conftest*
  c_links=no
fi
rm -f conftest*


if test x"${c_compiles}" = x"no" ; then
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:962: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    # Account for people who put trailing slashes in PATH elements.







<







906
907
908
909
910
911
912

913
914
915
916
917
918
919
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6

if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    # Account for people who put trailing slashes in PATH elements.
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'


# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1016: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"







<







959
960
961
962
963
964
965

966
967
968
969
970
971
972
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'


# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
# building. It's weirder than that, cause the flag varies depending
# how old the compiler is. So...
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1052: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 1067 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1073: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 1084 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1090: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if running LynxOS""... $ac_c" 1>&6
echo "configure:1114: checking if running LynxOS" >&5
if eval "test \"`echo '$''{'ac_cv_os_lynx'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1119 "configure"
#include "confdefs.h"
/*
 * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
 */
#if defined(__Lynx__) || defined(Lynx)
yes
#endif







<














|





|





<
<



|





|





<
<
















<




|







994
995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026


1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041


1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
# building. It's weirder than that, cause the flag varies depending
# how old the compiler is. So...
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6

# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 1016 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5


  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 1031 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1037: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5


  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if running LynxOS""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_os_lynx'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1063 "configure"
#include "confdefs.h"
/*
 * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
 */
#if defined(__Lynx__) || defined(Lynx)
yes
#endif
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
if test "$ac_cv_os_lynx" = "yes" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define LYNX 1
EOF

  echo $ac_n "checking whether -mposix or -X is available""... $ac_c" 1>&6
echo "configure:1149: checking whether -mposix or -X is available" >&5
  if eval "test \"`echo '$''{'ac_cv_c_posix_flag'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1154 "configure"
#include "confdefs.h"

int main() {


  /*
   * This flag varies depending on how old the compiler is.
   * -X is for the old "cc" and "gcc" (based on 1.42).
   * -mposix is for the new gcc (at least 2.5.8).
   */
  #if defined(__GNUC__) && __GNUC__ >= 2
  choke me
  #endif
  
; return 0; }
EOF
if { (eval echo configure:1170: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_c_posix_flag=" -mposix"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_c_posix_flag=" -X"
fi
rm -f conftest*

fi








<




|


|
>












|



<
<







1085
1086
1087
1088
1089
1090
1091

1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116


1117
1118
1119
1120
1121
1122
1123
if test "$ac_cv_os_lynx" = "yes" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define LYNX 1
EOF

  echo $ac_n "checking whether -mposix or -X is available""... $ac_c" 1>&6

  if eval "test \"`echo '$''{'ac_cv_c_posix_flag'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1097 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {

  /*
   * This flag varies depending on how old the compiler is.
   * -X is for the old "cc" and "gcc" (based on 1.42).
   * -mposix is for the new gcc (at least 2.5.8).
   */
  #if defined(__GNUC__) && __GNUC__ >= 2
  choke me
  #endif
  
; return 0; }
EOF
if { (eval echo configure:1114: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_c_posix_flag=" -mposix"
else


  rm -rf conftest*
  ac_cv_c_posix_flag=" -X"
fi
rm -f conftest*

fi

1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
echo $ac_n "checking for Tcl private headers""... $ac_c" 1>&6
echo "configure:1201: checking for Tcl private headers" >&5
# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
  withval="$with_tclinclude"
  with_tclinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tclh'+set}'`\" = set"; then







<







1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
echo $ac_n "checking for Tcl private headers""... $ac_c" 1>&6

# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
  withval="$with_tclinclude"
  with_tclinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tclh'+set}'`\" = set"; then
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
   ac_safe=`echo "tclInt.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tclInt.h""... $ac_c" 1>&6
echo "configure:1267: checking for tclInt.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1272 "configure"
#include "confdefs.h"
#include <tclInt.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1277: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6







|

<




|




|






<
<







1198
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222


1223
1224
1225
1226
1227
1228
1229
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
   ac_safe=`echo "tclInt.h" | tr './\055' '___'`
echo $ac_n "checking for tclInt.h""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1212 "configure"
#include "confdefs.h"
#include <tclInt.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5


  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
    echo "      If Tcl is installed, see INSTALL on how to tell"
    echo "      configure where Tcl is installed."
    exit 1
fi

# Use -g on all systems but Linux where it upsets the dynamic X libraries.
echo $ac_n "checking if we are running Linux""... $ac_c" 1>&6
echo "configure:1338: checking if we are running Linux" >&5
if test "x`(uname) 2>/dev/null`" = xLinux; then
  echo "$ac_t""yes" 1>&6
  linux=1
  DBG_CFLAGS=
else
  echo "$ac_t""no" 1>&6
  linux=0
  DBG_CFLAGS=-g
fi

#
# Look for functions that may be missing
#
echo $ac_n "checking for strchr""... $ac_c" 1>&6
echo "configure:1353: checking for strchr" >&5
if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1358 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strchr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char strchr();

int main() {


/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_strchr) || defined (__stub___strchr)
choke me
#else
strchr();
#endif

; return 0; }
EOF
if { (eval echo configure:1381: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_strchr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strchr=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRCHR 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


#
# Look for various header files
#
ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6
echo "configure:1409: checking for stdlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1414 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1419: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6







<














<




|





<
<


|
>












|



<
<




















|

<




|




|






<
<







1268
1269
1270
1271
1272
1273
1274

1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1296
1297
1298


1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318


1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340

1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356


1357
1358
1359
1360
1361
1362
1363
    echo "      If Tcl is installed, see INSTALL on how to tell"
    echo "      configure where Tcl is installed."
    exit 1
fi

# Use -g on all systems but Linux where it upsets the dynamic X libraries.
echo $ac_n "checking if we are running Linux""... $ac_c" 1>&6

if test "x`(uname) 2>/dev/null`" = xLinux; then
  echo "$ac_t""yes" 1>&6
  linux=1
  DBG_CFLAGS=
else
  echo "$ac_t""no" 1>&6
  linux=0
  DBG_CFLAGS=-g
fi

#
# Look for functions that may be missing
#
echo $ac_n "checking for strchr""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1294 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strchr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */


char strchr();

int main() { return 0; }
int t() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_strchr) || defined (__stub___strchr)
choke me
#else
strchr();
#endif

; return 0; }
EOF
if { (eval echo configure:1316: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
  rm -rf conftest*
  eval "ac_cv_func_strchr=yes"
else


  rm -rf conftest*
  eval "ac_cv_func_strchr=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRCHR 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


#
# Look for various header files
#
ac_safe=`echo "stdlib.h" | tr './\055' '___'`
echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1346 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5


  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
  enable_gcc=no
fi


DBG_UNSHARED_LIB_FILE=libtcldbg.a

echo $ac_n "checking type of library to build""... $ac_c" 1>&6
echo "configure:1468: checking type of library to build" >&5
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  enable_shared=yes
else
  enable_shared=no
fi







<







1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
  enable_gcc=no
fi


DBG_UNSHARED_LIB_FILE=libtcldbg.a

echo $ac_n "checking type of library to build""... $ac_c" 1>&6

# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  enable_shared=yes
else
  enable_shared=no
fi
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
# HP-UX 10.01 sh prints single quotes around any value that contains spaces.
(set) 2>&1 |
sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)='*\([^']*\)'*/\1=\${\1='\2'}/p"\
  >> confcache
if cmp -s $cache_file confcache; then
  :
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file







<

|







1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1462
1463
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.

(set) 2>&1 |
  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
  >> confcache
if cmp -s $cache_file confcache; then
  :
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.11"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done








|







1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.9"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

1618
1619
1620
1621
1622
1623
1624

1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g

s%@TCL_DEFS@%$TCL_DEFS%g
s%@TCL_DELETEME@%$TCL_DELETEME%g
s%@TCL_DBGX@%$TCL_DBGX%g

s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g
s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
s%@TCL_LD_FLAGS@%$TCL_LD_FLAGS%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
s%@TCL_SHARED_LIB_SUFFIX@%$TCL_SHARED_LIB_SUFFIX%g
s%@CC@%$CC%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@RANLIB@%$RANLIB%g
s%@CPP@%$CPP%g
s%@TCLHDIR@%$TCLHDIR%g
s%@TCLHDIRDASHI@%$TCLHDIRDASHI%g
s%@TCL_LIBRARY@%$TCL_LIBRARY%g







>



>






<







1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@CC@%$CC%g
s%@TCL_DEFS@%$TCL_DEFS%g
s%@TCL_DELETEME@%$TCL_DELETEME%g
s%@TCL_DBGX@%$TCL_DBGX%g
s%@TCL_EXEC_PREFIX@%$TCL_EXEC_PREFIX%g
s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g
s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
s%@TCL_LD_FLAGS@%$TCL_LD_FLAGS%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
s%@TCL_SHARED_LIB_SUFFIX@%$TCL_SHARED_LIB_SUFFIX%g

s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@RANLIB@%$RANLIB%g
s%@CPP@%$CPP%g
s%@TCLHDIR@%$TCLHDIR%g
s%@TCLHDIRDASHI@%$TCLHDIRDASHI%g
s%@TCL_LIBRARY@%$TCL_LIBRARY%g
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
s%@DBG_LIB_FILE@%$DBG_LIB_FILE%g
s%@DBG_LIB_FILES@%$DBG_LIB_FILES%g
s%@DBG_CFLAGS@%$DBG_CFLAGS%g
s%@UNSHARED_RANLIB@%$UNSHARED_RANLIB%g

CEOF
EOF

cat >> $CONFIG_STATUS <<\EOF

# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
  if test $ac_beg -gt 1; then
    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
  else
    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
  fi
  if test ! -s conftest.s$ac_file; then
    ac_more_lines=false
    rm -f conftest.s$ac_file
  else
    if test -z "$ac_sed_cmds"; then
      ac_sed_cmds="sed -f conftest.s$ac_file"
    else
      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
    fi
    ac_file=`expr $ac_file + 1`
    ac_beg=$ac_end
    ac_end=`expr $ac_end + $ac_max_sed_cmds`
  fi
done
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
fi
EOF

cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile pkgIndex"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













|







1579
1580
1581
1582
1583
1584
1585




































1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
s%@DBG_LIB_FILE@%$DBG_LIB_FILE%g
s%@DBG_LIB_FILES@%$DBG_LIB_FILES%g
s%@DBG_CFLAGS@%$DBG_CFLAGS%g
s%@UNSHARED_RANLIB@%$UNSHARED_RANLIB%g

CEOF
EOF




































cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile pkgIndex"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust relative srcdir, etc. for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac

  case "$ac_given_INSTALL" in
  [/$]*) INSTALL="$ac_given_INSTALL" ;;
  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
  esac

  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" $ac_given_srcdir/$ac_file_in | eval "$ac_sed_cmds" > $ac_file
fi; done
rm -f conftest.s*

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
ac_dC='\3'
ac_dD='%g'
# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_uB='\([ 	]\)%\1#\2define\3'
ac_uC=' '
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'

if test -z "$CONFIG_HEADERS"; then
EOF
cat >> $CONFIG_STATUS <<EOF
  CONFIG_HEADERS="tcldbgcf.h"
EOF
cat >> $CONFIG_STATUS <<\EOF
fi
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac







<













|

|




















<
<
<
|
<
<
<







1620
1621
1622
1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662



1663



1664
1665
1666
1667
1668
1669
1670
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac

  case "$ac_given_INSTALL" in
  [/$]*) INSTALL="$ac_given_INSTALL" ;;
  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
  esac

  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
fi; done
rm -f conftest.subs

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
ac_dC='\3'
ac_dD='%g'
# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_uB='\([ 	]\)%\1#\2define\3'
ac_uC=' '
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'




CONFIG_HEADERS=${CONFIG_HEADERS-"tcldbgcf.h"}



for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac
1810
1811
1812
1813
1814
1815
1816


1817
1818
1819
1820
1821
1822
1823
# on some systems where configure will not decide to define it.
cat >> conftest.vals <<\EOF
s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
EOF

# Break up conftest.vals because some shells have a limit on
# the size of here documents, and old seds have small limits too.



rm -f conftest.tail
while :
do
  ac_lines=`grep -c . conftest.vals`
  # grep -c gives empty output for an empty file on some AIX systems.
  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi







>
>







1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
# on some systems where configure will not decide to define it.
cat >> conftest.vals <<\EOF
s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
EOF

# Break up conftest.vals because some shells have a limit on
# the size of here documents, and old seds have small limits too.
# Maximum number of lines to put in a single here document.
ac_max_here_lines=12

rm -f conftest.tail
while :
do
  ac_lines=`grep -c . conftest.vals`
  # grep -c gives empty output for an empty file on some AIX systems.
  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
  cat conftest.in >> conftest.h
  rm -f conftest.in
  if cmp -s $ac_file conftest.h 2>/dev/null; then
    echo "$ac_file is unchanged"
    rm -f conftest.h
  else
    # Remove last slash and all that follows it.  Not all systems have dirname.
      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
      # The file is in a subdirectory.
      test ! -d "$ac_dir" && mkdir "$ac_dir"
    fi
    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done










<
<
<
<
<
<







1728
1729
1730
1731
1732
1733
1734






1735
1736
1737
1738
1739
1740
1741
  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
  cat conftest.in >> conftest.h
  rm -f conftest.in
  if cmp -s $ac_file conftest.h 2>/dev/null; then
    echo "$ac_file is unchanged"
    rm -f conftest.h
  else






    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done



Changes to HISTORY.

1
2
3
4
5



























































































































































































































































6
7
8
9
10
11
12
This is the HISTORY file for Expect.  Modifications made by Cygnus
support are in ChangeLog. - Don

Date	Version	Description
-------	-------	------------------------------------------------------



























































































































































































































































9/30/98	5.28.1	Brian France <[email protected]> noted that his compiler
		rejected label with no statement.

9/28/98	5.28.0	Fixed two bugs in tcl-debugger (see that HISTORY file).

		Submitted Expect documentation for official NIST review.  At
		their request, modified a couple things.





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
This is the HISTORY file for Expect.  Modifications made by Cygnus
support are in ChangeLog. - Don

Date	Version	Description
-------	-------	------------------------------------------------------
12/20/01 5.34.0	Don Porter <[email protected]> provided package-related
		fixes for test suite.

		Brian Theado <[email protected]> noted that interact's -re
		support broke when offsets kicked in.  Turned out that the
		regexp engine supports them during execution but the results
		are delivered RELATIVE to the offset.  (I suspect this was done
		due to expediency.)

10/1/01 5.33.0	<[email protected]> found that expect's diagnostics
		didn't include the "no" after testing for a full buffer.

		Hemang Lavana <[email protected]> noted that "debug" (Dbg_On)
		calls didn't always force the debugger into step mode.

		Martin Kammerhofer <[email protected]> noted that the man
		page neglected to document interpreter -eof.

		Chris Clare <[email protected]> provided fix for
		multiple decl in C lib.

		Sheng Wang <[email protected]> found interact's
		can-match code had broken.  It was missing the special hook
		that Henry had added just for this purpose.  How strange.

		Dieter Fiebelkorn <[email protected]> requested addition
		to config.guess for Power*Macintosh:Darwin for MacOSX.
		Aside - to download latest config.guess:
		 cvs -d :pserver:[email protected]:/cvs checkout \
		 config

		Added pipeline example to unbuffer man page.

8/4/00 5.32.2	Allen J. Newton <[email protected]> provided code for
		generating passwords with special characters in mkpasswd.

		Brent Welch <[email protected]> changed the fix1line
		install script so that "autoexpect" and other scripts that
		get installed into the platform-independent bin directory
		generically invoke "expect" from the users PATH instead
		of hardwiring the platform-specific expect pathname.

		TclPro 1.4 released with 5.32.2 bundled.

7/13/00	5.32.1	Uwe Klein <[email protected]> reported segfaults from reading
		nulls.  Due to code rewrite in 5.30->5.31 transition.

5/14/00 5.32.0	New version for timing with Ajuba TclPro 1.4.  This version
		of Expect has no new features or behaviors but a lot has been
		fixed since 5.31.0.

		Martin Buchholz <[email protected]> noted that his
		alphaev56-dec-osf4.0e has ptmx and ptmx_bsd (and ptm, pts,
		pty, ptym).  He suggested that BSD things are now usually
		deprecated so to skip ptmx_bsd if ptmx avail.

		Chang Li <[email protected]> noted that debugger's bp cmd
		broke on every command.  Was a bug in breakpoint_trace from
		when we installed the new regexp engine.

		Jonathan Kamens fixed printf formats in several pty diags.

		rm_nulls -d was set to wrong value.

5/12/00 5.31.8	After receiving yet another request for fully versioned
		archives, gave in.

		Signal handler sometimes sent error to stderr inappropriately.

4/27/00 5.31.7	Rob Savoye fixed Debian ptys and properly checking of libpt.

3/8/00  5.31.6	Petrus Vloet <[email protected]> noted that Expect
		installed tclRegexp.h which included regex.h which of course
		misbehaves when it reads the system's version.  This is new
		since 8.0.  Since I need to revise the Clib anyway (which
		is what this install was for), I'll back this out for now.

3/6/00	5.31.5	Larry Virden noted that configure checked for threads twice.

2/19/00 5.31.4	Omer Azmon <[email protected]> note errors in
		pty_termios.c in exp_pty_test that caused problems during
		pty testing.

		Jeffrey Hobbs recommended having configure accept and warn
		about --enable-threads.

		John Ellson <[email protected]> noted configure's autoconf
		testing had leftover debugging code.  Also provided a fix for
		building w/shared libs on HP - appeared to be leftover from
		earlier Tcl-required configuration that has now disappeared.

		Susan Muston <[email protected]> noted that exp_wait with
		no spawned processes exited immediately which is different
		than 5.29 behavior which reported "no children".  This new
		behavior was evidentally a gratuitous change during the
		channel driver addition.  Backed out.  At the same time,
		neither behavior matches documentation - doc should be fixed
		and improved except I'm not sure if the behavior should yet
		be something else (depending if stdin closed or not).

		[email protected] reported "spawn cat;exp_open" failed.
		Uninited variable.

		Scriptics reported memory leak.  Was bug in parse_expect_args.

		"Michael P. Reilly" <[email protected]> noted clib was hanging
		in spawn code.  status_pipe wasn't being closed.

		Egil Kvaleberg <[email protected]> provided fix due to new gcc
		which defines strchr as a macro.

		Dave Morrison <[email protected]> noted some printfs
		in exp_log.c that misinterpreted embedded %'s with resulting
		core dumps.

		Dick Goodwin <[email protected]> noted that "system echo
		foo" returned with no apparent effect.  Due to closeonexec
		in expect's channel driver.  Added skip if std channel.
		Fixed similar bug in stty command.  Minor bug left in stty
		which isn't passing output back from underlying exec.

		Stacy W. Smith <[email protected]> provided patch that uses
		sigsetjmp instead of setjmp that he says fixes a problem he
		encountered with C lib where it stopped timing out in expect()
		as if the signals were corrupted.  The man page doesn't
		explain the difference between these calls in a way that makes
		sense as to why they should make a difference, but I'll the
		names are certainly suggestive so I'll try it.  He says "it
		  appears that the linux setjmp behaves a little differently
		  compared to setjmp on some other OSs.  Specifically, setjmp
		  on linux does not save the signal context.  It seems most
		  BSDish OSs do save the signal context with setjmp.  On those
		  machines, it appears setjmp(env) is equivalent to
		  sigsetjmp(env,1) whereas on linux, setjmp(env) is equivalent
		  to sigsetjmp(env,0).  My patch made a (probably bad)
		  assumption that if siglongjmp() exists that we should use
		  the sigXXX versions.  I specifically tested for siglongjmp 
		  rather than sigsetjmp because on linux, sigsetjmp is just a
		  #define for  __sigsetjmp.  It appears that linux will give
		  the BSD behaviour if  __FAVOR_BSD is defined, but I didn't
		  know what other implications that might have.

		Michael Schumacher provided fix so that test for whether
		configure was out-of-date worked when not using the default
		build dir.

11/1/99 5.31.3	Shlomi Mahlab <[email protected]> noted all.tcl in CVS
		but not distribution.

		More notes from Keith Brown on HP cc complaints in exp_pty.c.

10/28/99 5.31.2	"Keith Brown" <[email protected]> noted that HP cc
		objected to auto aggregate initialization in
		expLogChannelOpen.

10/22/99 5.31.1 Official release!

		P Darcy Barnett <[email protected]> noted Makefile could
		produce "autoconf not found" for non-developers using CVS.
		Made configure detect and provide advice on workaround.

		Fixed bug in interact -echo exhibited in rftp example.

		Ryan Murray <[email protected]> noted Expect wasn't
		handling handling 8-bit bytes correctly.  I had accidentally
		used Tcl_Write instead of Tcl_WriteChar.

		Ashley Pittman <[email protected]> noted that digital unix
		V5.0 prefers openpty (4000 ptys) over ptmx (60 ptys), so I'm
		reversing the login in pty_termios.c.  This also controls
		linux, but no linux hackers have weighed in on this subject
		yet.

		Andrew Tannenbaum <[email protected]> noted exp_internal
		command and "expect -exact" were broken.

6/29/99 5.31.0	See the NEWS file for this date for an overview.  (I'm
		too tired to add all the details.  Maybe later.)

		Fixed exp_clib so that it immediately reported failure of
		exec (in spawn) rather than passing it back through pipe.

		Removed error checking from ioctl(TIOCSCTTY) to pacify the
		variety of (but not all) Linux systems and a few others which
		define TIOCSCTTY but return an error although seem to work
		anyway.

		Added configure test for 0 vs 2-arg setpgrp.

		Kenji Kamizono <[email protected]> noted it was possible
		to compile Linux (2.2.5) so that it recognized both openpty
		and ptmx leading to conflicts.  I arbitrarily chose ptmx.

10/15/99 5.30.2	Herve Tireford <[email protected]> noted extraneous
		sleep(20) in clib.  Apparently left over from debugging, oops.

8/18/99 5.30.1	Added test for newer versions of Tcl that are incompatible.

		Kenji Kamizono <[email protected]> noted it was possible
		to compile Linux (2.2.5) so that it recognized both openpty
		and ptmx leading to conflicts.  I arbitrarily chose ptmx.

4/1/99	5.30.0  Martin Forssen <[email protected]> provided fix to allow configure
		to start with LDFLAGS from environment.

		Paul Tazzyman <[email protected]> noted that log_file didn't
		check for logging twice without turning off logging first.

		Ben <[email protected]> provided updated host for
		weather example.

		Jonathon Kamens noted that Expect didn't build properly if
		Tcl and/or Tk used build/install directories out of the usual
		hierarchy.  At the same time, I fixed a number of other related
		problems in Makefile/configure.

		Pierre Pomes <[email protected]> provided fix
		to ftp-inband.  It blew up from an unprotected send that
		was handed a uuencoded line that started with a -.

		Autoexpect was thrown off by simple-minded [file executable]
		test picking up expect directory while searching for
		executable.

1/21/99 5.29.0	Martin Forssen provides mods to support INSTALL_ROOT.

		Bryan Surles <[email protected]> modified configure.in to
		map DBGX to the same value as TCL_DBGX so the .so is named
		correctly.

		Suresh Sastry <[email protected]> forced $LIBS to be
		added to EXP_SHLIB_LD_LIBS.  It's not clear to me why this is
		necessary (since Tk doesn't) but he was having a problem
		with openpty not being found during runtime on Linux.

		Martin Forssen noted expectk was crashing if a Tcl error was
		encountered.  He found that exp_exit_handlers() was trying
		to write into interp->result after interp had been deleted.

		Added another copy to distribution site - with version number.

		Stanislav Shalunov <[email protected]> closed race in pty code.

		Fixed man page: -brace should be -nobrace.

		Dan O'Brien <[email protected]> noted that Expect needed to
		call Tcl_FindExecutable at startup for info nameofexecutable.

		Robbie Gilbert <[email protected]> noted indirect spawn
		ids occasionally failed.  Fixed.

9/30/98	5.28.1	Brian France <[email protected]> noted that his compiler
		rejected label with no statement.

9/28/98	5.28.0	Fixed two bugs in tcl-debugger (see that HISTORY file).

		Submitted Expect documentation for official NIST review.  At
		their request, modified a couple things.
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
		Kristina  <[email protected]> noted that tip failed when
		spawned from a cgi script (BSDI BSD/OS 3.1 i386) because tip
		didn't see a definition for SHELL and HOME.  They need to be
		set.  (Doesn't have to be anything useful; the empty string is
		fine!)  Solution: documented this in Expect man page.

		Zachariah Baum <[email protected]> noted that config.sub
		didn't grok Intel 686.  Found a newer version that did in
		autoconf-2.11.

		POTENTIAL INCOMPATIBILITY: Changed interact so that it observes
		parity while matching.  It used to ignore parity.  This impacts
		people who use interact to connect through to a real serial
		device that generates parity.  If matches don't work, use the
		exp_parity command.  (This fix should have been made years ago,







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
		Kristina  <[email protected]> noted that tip failed when
		spawned from a cgi script (BSDI BSD/OS 3.1 i386) because tip
		didn't see a definition for SHELL and HOME.  They need to be
		set.  (Doesn't have to be anything useful; the empty string is
		fine!)  Solution: documented this in Expect man page.

		Zachariah Baum <[email protected]> noted that config.sub
		didn't recognize Intel 686.  Found a newer version that did in
		autoconf-2.11.

		POTENTIAL INCOMPATIBILITY: Changed interact so that it observes
		parity while matching.  It used to ignore parity.  This impacts
		people who use interact to connect through to a real serial
		device that generates parity.  If matches don't work, use the
		exp_parity command.  (This fix should have been made years ago,
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
		LIBS to find strftime.  This test should really be done by Tcl.

8/12/96 5.20b17 Glen Biagioni <[email protected]> noted interact -re "A(xx)"
		failed to match.  Problem turned out to be that Tcl 7.5 changed
		a constant which in the regexp code, which Expect didn't see
		because it provides its own defn for interact.  Alas, the one
		thing Expect reuses from Tcl was where the change was.  This
		should really be fixed so Expect doesn't rely on Expect in this
		way, but there's no point in putting in a lot of work on regexp
		when we're anticipating a new one soon anyway.

		Bjorn S. Nilsson <[email protected]> noted fixcat hangs.
		Turned out that new Tcl (7.5p1) now waits for all children to
		disappear.  But Expect still had a handle to a child.  I added
		an exit handler to close the connections before Tcl's exit







|







494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
		LIBS to find strftime.  This test should really be done by Tcl.

8/12/96 5.20b17 Glen Biagioni <[email protected]> noted interact -re "A(xx)"
		failed to match.  Problem turned out to be that Tcl 7.5 changed
		a constant which in the regexp code, which Expect didn't see
		because it provides its own defn for interact.  Alas, the one
		thing Expect reuses from Tcl was where the change was.  This
		should really be fixed so Expect doesn't rely on Tcl in this
		way, but there's no point in putting in a lot of work on regexp
		when we're anticipating a new one soon anyway.

		Bjorn S. Nilsson <[email protected]> noted fixcat hangs.
		Turned out that new Tcl (7.5p1) now waits for all children to
		disappear.  But Expect still had a handle to a child.  I added
		an exit handler to close the connections before Tcl's exit
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
		Gary Shea noted that a recent change to expectk made it not
		default to interactive.		

4/12/93	4.5.1	At request of Rusty Wilson <[email protected]>, added
		"-console" to spawn.

		Pang Wai Man Raymond <[email protected]> reported that
		passmass didn't grok DEC's passwd prompts for root.

4/7/93	4.5.0	Fixed bug in interact regexp preventing match of multichar
		literals.

4/6/93	4.4.3	Bennett Todd <[email protected]> noted missing example scripts
		timed-read and time-run.








|







1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
		Gary Shea noted that a recent change to expectk made it not
		default to interactive.		

4/12/93	4.5.1	At request of Rusty Wilson <[email protected]>, added
		"-console" to spawn.

		Pang Wai Man Raymond <[email protected]> reported that
		passmass didn't recognize DEC's passwd prompts for root.

4/7/93	4.5.0	Fixed bug in interact regexp preventing match of multichar
		literals.

4/6/93	4.4.3	Bennett Todd <[email protected]> noted missing example scripts
		timed-read and time-run.

1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662

3/15/93 4.3.0	Cleaned up /tmp files used during pty locking.

		Added command "parity" to enable parity stripping.  Fixed
		match_max to do -i correctly.

3/15/93	4.2.4	Fixed to work on new SGI which returns slave-close via excep
		(select) or POLLERR (poll) rather than thru read().  Why do you
		people do things like this?

3/12/93	4.2.3	Fixed to work on AIX (using /dev/ptc) and UTS (using getpty).

3/11/93 4.2.1-2	Fixed numerous bugs relating to HP ptys.  It's amazing that for
		their bewildering complexity, they couldn't support generation
		of EOF to the master (or at least enable trapping of just
		close), rather than forcing the code to know about opens, too.







|
<







1898
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912

3/15/93 4.3.0	Cleaned up /tmp files used during pty locking.

		Added command "parity" to enable parity stripping.  Fixed
		match_max to do -i correctly.

3/15/93	4.2.4	Fixed to work on new SGI which returns slave-close via excep
		(select) or POLLERR (poll) rather than thru read().


3/12/93	4.2.3	Fixed to work on AIX (using /dev/ptc) and UTS (using getpty).

3/11/93 4.2.1-2	Fixed numerous bugs relating to HP ptys.  It's amazing that for
		their bewildering complexity, they couldn't support generation
		of EOF to the master (or at least enable trapping of just
		close), rather than forcing the code to know about opens, too.
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
		it.

2/21/92	3.18.0	Worked on the HP port some more.  The HP causes a real problem
		by insisting SIGCLD be delivered in order for wait to return
		a status.  This royally complicated the code, partly because
		of the special casing all over the place in the trap command,
		the asynchronous delivery of SIGCLD and also because Tcl itself
		is not prepared to have system calls be interrupted.  Cleverly,
		the HP also defines both CLD and CHLD which threw my macros
		off at first.  Thanks, but I don't this kind of help!

		Anyway, the end result is that on the HP, SIGCLD is ignored.
		The manual claims wait status will not be delivered but it
		seems to be anyway.  Good grief!  (Even if it were ignored,
		it would not be such a calamity, since wait is used mainly
		to discard zombies on other systems.)

		A remaining problem is that there appears to be some odd
		interaction, perhaps with fork, such that the script is rolled
		back at eof if a spawned process happens to exit at the same
		time.  The solution for now is to exit all scripts via exit
		rather than letting exit be called implicitly.  There must be
		some real bug, but I'm unable to find anything after lots of
		testing, line and Saber.  At the moment, I'm highly suspicious
		of the HP itself rather than expect.

		Bob Proulx and Jeff Okamoto supplied me with patches for
		inter_select.c.  HP transmits some pty interactions via the
		exception field in select.

		Michael Grant gave me a mod to grok ~ in the logfile and
		debug commands.

2/17/92	3.17.1	Brian Keves <[email protected]> pointed out that the man page
		still referred to "expect_match" instead of "expect_out".

2/12/92	3.17.0	Eric Arnold <[email protected]> ran into a problem
		when running in the background.  interact did ioctl(0...)s to







|
|
<




















|







2188
2189
2190
2191
2192
2193
2194
2195
2196

2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
		it.

2/21/92	3.18.0	Worked on the HP port some more.  The HP causes a real problem
		by insisting SIGCLD be delivered in order for wait to return
		a status.  This royally complicated the code, partly because
		of the special casing all over the place in the trap command,
		the asynchronous delivery of SIGCLD and also because Tcl itself
		is not prepared to have system calls be interrupted.  The HP
		also defines both CLD and CHLD which threw my macros off.


		Anyway, the end result is that on the HP, SIGCLD is ignored.
		The manual claims wait status will not be delivered but it
		seems to be anyway.  Good grief!  (Even if it were ignored,
		it would not be such a calamity, since wait is used mainly
		to discard zombies on other systems.)

		A remaining problem is that there appears to be some odd
		interaction, perhaps with fork, such that the script is rolled
		back at eof if a spawned process happens to exit at the same
		time.  The solution for now is to exit all scripts via exit
		rather than letting exit be called implicitly.  There must be
		some real bug, but I'm unable to find anything after lots of
		testing, line and Saber.  At the moment, I'm highly suspicious
		of the HP itself rather than expect.

		Bob Proulx and Jeff Okamoto supplied me with patches for
		inter_select.c.  HP transmits some pty interactions via the
		exception field in select.

		Michael Grant gave me a mod to recognize ~ in the logfile and
		debug commands.

2/17/92	3.17.1	Brian Keves <[email protected]> pointed out that the man page
		still referred to "expect_match" instead of "expect_out".

2/12/92	3.17.0	Eric Arnold <[email protected]> ran into a problem
		when running in the background.  interact did ioctl(0...)s to
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
		#ifdef va_dcl and put my inclusion after tclInt.h.

10/31/91 3.3.0	Converted most of the examples.  Three more to go.
		Worked on man page some more.

		Modified expect so that if timeout > 0, and nothing in the
		buffer matched, it will force a read, no matter how long the
		preceeding code took.  This may be hard to understand, but is
		the intuitive behavior that I always desired.

10/30/91 3.2.0	Fixed bug in eof handling.  Converted some more of the
		examples, and added to Makefile.

10/29/91 3.1.0	Fixed slight bugs in tty mode switching, pty initialization
		(via stty).







|







2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
		#ifdef va_dcl and put my inclusion after tclInt.h.

10/31/91 3.3.0	Converted most of the examples.  Three more to go.
		Worked on man page some more.

		Modified expect so that if timeout > 0, and nothing in the
		buffer matched, it will force a read, no matter how long the
		preceding code took.  This may be hard to understand, but is
		the intuitive behavior that I always desired.

10/30/91 3.2.0	Fixed bug in eof handling.  Converted some more of the
		examples, and added to Makefile.

10/29/91 3.1.0	Fixed slight bugs in tty mode switching, pty initialization
		(via stty).
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
3/17/90		Sent copies of man page to Doug Gwyn and Larry Wall for
		comments.  Note that gwyn downloaded it.

3/16/90		Am really irritated by USENIX.  My paper has been put in a
		session against another session, the BSD people.  Furthermore,
		they called my paper an application, when it is no more so than
		any other shell or language.  Better I should be in "lessons
		learned".  Mashey said take a hike, i.e., it was too late to
		change the schedule.  On top of that, our session has four
		people in it, so I'll have very little time to speak.  Grrrr.

3/13/90	1.6	Added "stty", because without it you can't do things like
		turning off echo to accept a password.

3/8/90	1.5	Abstract was accepted into USENIX!!!!  Time to start writing
		it!  Sent man page to Ousterhout.  He didn't seem too
		impressed.







|
|
|







3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3/17/90		Sent copies of man page to Doug Gwyn and Larry Wall for
		comments.  Note that gwyn downloaded it.

3/16/90		Am really irritated by USENIX.  My paper has been put in a
		session against another session, the BSD people.  Furthermore,
		they called my paper an application, when it is no more so than
		any other shell or language.  Better I should be in "lessons
		learned".  But it was too late to change the schedule.  On top
		of that, our session has four people in it, so I'll have very
		little time to speak.  Grrrr.

3/13/90	1.6	Added "stty", because without it you can't do things like
		turning off echo to accept a password.

3/8/90	1.5	Abstract was accepted into USENIX!!!!  Time to start writing
		it!  Sent man page to Ousterhout.  He didn't seem too
		impressed.

Changes to INSTALL.

78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
these from uunet or any good archive site.

--------------------
Trying Expect Without Installing Tcl
--------------------

Once expect is built, you can try it out.  If Tcl has not been
installed, you will need to define the environment variable
TCL_LIBRARY.  It should name the directory contain the Tcl libraries.
For example, if you are using csh with Tcl 8.0.3:


	$ setenv TCL_LIBRARY ../tcl8.0.3/library

Now you can run expect.

The same advice applies to Tk.  If it is available but has not been
installed, you can try out expectk but only after defining TK_LIBRARY.







|
|
|
>







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
these from uunet or any good archive site.

--------------------
Trying Expect Without Installing Tcl
--------------------

Once expect is built, you can try it out.  If Tcl has not been
installed (but it has been compiled), you will need to define the
environment variable TCL_LIBRARY.  It should name the directory
contain the Tcl libraries.  For example, if you are using csh with Tcl
8.0.3:

	$ setenv TCL_LIBRARY ../tcl8.0.3/library

Now you can run expect.

The same advice applies to Tk.  If it is available but has not been
installed, you can try out expectk but only after defining TK_LIBRARY.
135
136
137
138
139
140
141




142
143
144
145
146
147
148
149
150
151
152
153
154
155
				configure Tcl with it and then reconfigure
				Expect.  Expect will inherit the definition
				that way.  It is not safe to modify the
				Makefile to use gcc by hand.  If you do
				this, then information related to dynamic
				linking will be incorrect.





	--with-tclconfig=...	Specifies the directory containing Tcl's
				configure file (tclConfig.sh).

	--with-tclinclude=...	Specifies the directory containing Tcl's
				private include files (such as tclInt.h)

	--with-tkconfig=...	Specifies the directory containing Tk's
				configure file (tkConfig.sh).

	--with-tkinclude=...	Specifies the directory containing Tk's
				private include files (such as tkInt.h)

Some of the defaults in "configure" can be overridden by environment
variables.  This is a convenience intended for environments that are







>
>
>
>
|





|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
				configure Tcl with it and then reconfigure
				Expect.  Expect will inherit the definition
				that way.  It is not safe to modify the
				Makefile to use gcc by hand.  If you do
				this, then information related to dynamic
				linking will be incorrect.

	--enable-threads	This switch is ignored so that you can
				configure Expect with the same configure
				command as Tcl.

	--with-tcl=...		Specifies the directory containing Tcl's
				configure file (tclConfig.sh).

	--with-tclinclude=...	Specifies the directory containing Tcl's
				private include files (such as tclInt.h)

	--with-tk=...		Specifies the directory containing Tk's
				configure file (tkConfig.sh).

	--with-tkinclude=...	Specifies the directory containing Tk's
				private include files (such as tkInt.h)

Some of the defaults in "configure" can be overridden by environment
variables.  This is a convenience intended for environments that are
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
By default, configure uses the latest Tcl it can find.  You can
override this by creating a symbolic link of "tcl" which points to the
release you want.

If you can't or don't want to create symbolic links, you can instead
indicate where Tcl and Tk are by using the following environment variables:
 
with_tclconfig		Directory containing Tcl configure file (tclConfig.h)
with_tclinclude		Directory containing Tcl include files
with_tkinclude		Directory containing Tk include files
with_tkconfig		Directory containing Tk binary library (tkConfig.h)

--------------------
Multiple-Architecture Installation
--------------------

You might want to compile a software package in a different directory
from the one that contains the source code.  Doing this allows you to







|


|







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
By default, configure uses the latest Tcl it can find.  You can
override this by creating a symbolic link of "tcl" which points to the
release you want.

If you can't or don't want to create symbolic links, you can instead
indicate where Tcl and Tk are by using the following environment variables:
 
with_tcl		Directory containing Tcl configure file (tclConfig.h)
with_tclinclude		Directory containing Tcl include files
with_tkinclude		Directory containing Tk include files
with_tk			Directory containing Tk binary library (tkConfig.h)

--------------------
Multiple-Architecture Installation
--------------------

You might want to compile a software package in a different directory
from the one that contains the source code.  Doing this allows you to

Changes to Makefile.in.

57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
# your Expect scripts.
# Note: On Linux systems which only have dynamic X libraries, the -g prevents
# the linker from using them.  So do not use -g on such systems.
CFLAGS = @CFLAGS@
#XCFLAGS = @CFLAGS@ @EXP_CFLAGS@ @EXP_SHLIB_CFLAGS@ 
XCFLAGS = @CFLAGS@ @EXP_CFLAGS@

# Tcl libraries built with optimization switches have this additional extension
TCL_DBGX =              @TCL_DBGX@


# From now on, CFLAGS is never used.  Instead, use XCFLAGS.  This is done so
# that we can provide a public interface for CFLAGS thereby allowing users
# to add to it on the Make command-line and still get the rest of the flags
# computed by configure.  Do this at your own risk - it obvious goes against
# the idea of configure's interface, however this is established tradition
# at some sites (e.g., Cygnus)!







|

>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# your Expect scripts.
# Note: On Linux systems which only have dynamic X libraries, the -g prevents
# the linker from using them.  So do not use -g on such systems.
CFLAGS = @CFLAGS@
#XCFLAGS = @CFLAGS@ @EXP_CFLAGS@ @EXP_SHLIB_CFLAGS@ 
XCFLAGS = @CFLAGS@ @EXP_CFLAGS@

# Libraries built with optimization switches have this additional extension
TCL_DBGX =              @TCL_DBGX@
TK_DBGX =		@TK_DBGX@

# From now on, CFLAGS is never used.  Instead, use XCFLAGS.  This is done so
# that we can provide a public interface for CFLAGS thereby allowing users
# to add to it on the Make command-line and still get the rest of the flags
# computed by configure.  Do this at your own risk - it obvious goes against
# the idea of configure's interface, however this is established tradition
# at some sites (e.g., Cygnus)!
90
91
92
93
94
95
96







97
98
99
100
101
102
103
# See the INSTALL file for more information.  (Analogous information
# applies to the next variable as well.)
prefix = @prefix@

# You can specify a separate installation prefix for architecture-specific
# files such as binaries and libraries.
exec_prefix = @exec_prefix@








# The following Expect scripts are not necessary to have installed as
# commands, but are very useful.  Edit out what you don't want installed.
# The INSTALL file describes these and others in more detail.
# Some Make's screw up if you delete all of them because SCRIPTS is a
# target.  If this is a problem, just comment out the SCRIPTS target itself.
SCRIPTS = timed-run timed-read ftp-rfc autopasswd lpunlock weather \







>
>
>
>
>
>
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# See the INSTALL file for more information.  (Analogous information
# applies to the next variable as well.)
prefix = @prefix@

# You can specify a separate installation prefix for architecture-specific
# files such as binaries and libraries.
exec_prefix = @exec_prefix@

# The following definition can be set to non-null for special systems
# like AFS with replication.  It allows the pathnames used for installation
# to be different than those used for actually reference files at
# run-time.  INSTALL_ROOT is prepended to $prefix and $exec_prefix
# when installing files.
INSTALL_ROOT =

# The following Expect scripts are not necessary to have installed as
# commands, but are very useful.  Edit out what you don't want installed.
# The INSTALL file describes these and others in more detail.
# Some Make's screw up if you delete all of them because SCRIPTS is a
# target.  If this is a problem, just comment out the SCRIPTS target itself.
SCRIPTS = timed-run timed-read ftp-rfc autopasswd lpunlock weather \
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

######################################################################
# End of things you may want to change
#
# Do not change anything after this
######################################################################

bindir            = @bindir@
bindir_arch_indep = $(prefix)/bin
tcl_libdir        = @libdir@
libdir            = @libdir@/expect$(VERSION)
libdir_arch_indep = $(prefix)/lib/expect$(VERSION)

mandir 	= @mandir@
man1dir = $(mandir)/man1
man3dir = $(mandir)/man3
infodir = @infodir@
includedir = @includedir@

# Expect's utility script directories - arch-independent and arch-non-
# independent.  These correspond to the variables "exp_library" and
# "exp_exec_library".
SCRIPTDIR	= $(libdir_arch_indep)
EXECSCRIPTDIR	= $(libdir)

SHELL = @EXP_CONFIG_SHELL@

INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@

AR = ar
ARFLAGS = cr

LOCAL_EXPECT=LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH ./expect

# These definitions are used by the "subdirs_do" target to pass
# the compile flags down recursively.
FLAGS_TO_PASS = \
	"CC=$(CC)" \
	"CFLAGS=$(XCFLAGS)" \
	"CFLAGS_INT=$(CFLAGS_INT)" \







|
|
|
|
|

|


|
|
















|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

######################################################################
# End of things you may want to change
#
# Do not change anything after this
######################################################################

bindir            = $(INSTALL_ROOT)@bindir@
bindir_arch_indep = $(INSTALL_ROOT)$(prefix)/bin
tcl_libdir        = $(INSTALL_ROOT)@libdir@
libdir            = $(INSTALL_ROOT)@libdir@/expect$(VERSION)
libdir_arch_indep = $(INSTALL_ROOT)$(prefix)/lib/expect$(VERSION)

mandir 	= $(INSTALL_ROOT)@mandir@
man1dir = $(mandir)/man1
man3dir = $(mandir)/man3
infodir = $(INSTALL_ROOT)@infodir@
includedir = $(INSTALL_ROOT)@includedir@

# Expect's utility script directories - arch-independent and arch-non-
# independent.  These correspond to the variables "exp_library" and
# "exp_exec_library".
SCRIPTDIR	= $(libdir_arch_indep)
EXECSCRIPTDIR	= $(libdir)

SHELL = @EXP_CONFIG_SHELL@

INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@

AR = ar
ARFLAGS = cr

LOCAL_EXPECT=LD_LIBRARY_PATH=.:@TCL_EXEC_PREFIX@/lib:$(tcl_libdir):$$LD_LIBRARY_PATH ./expect

# These definitions are used by the "subdirs_do" target to pass
# the compile flags down recursively.
FLAGS_TO_PASS = \
	"CC=$(CC)" \
	"CFLAGS=$(XCFLAGS)" \
	"CFLAGS_INT=$(CFLAGS_INT)" \
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240

241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
  else echo runtest ;  fi`

PTY_TYPE = @PTY_TYPE@
PTY = pty_$(PTY_TYPE)
CFILES = exp_command.c expect.c $(PTY).c \
	exp_inter.c exp_regexp.c exp_tty.c \
	exp_log.c exp_main_sub.c exp_pty.c \
	exp_printify.c exp_trap.c exp_strf.c \
	exp_console.c exp_glob.c exp_win.c Dbg.c exp_clib.c \
	exp_closetcl.c exp_memmove.c exp_tty_comm.c \
	exp_$(EVENT_TYPE).c exp_$(EVENT_ABLE).c

OFILES = exp_command.o expect.o $(PTY).o exp_inter.o exp_regexp.o exp_tty.o \
	exp_log.o exp_main_sub.o exp_pty.o exp_printify.o exp_trap.o \
	exp_console.o exp_strf.o exp_glob.o exp_win.o Dbg.o exp_clib.o \
	exp_closetcl.o exp_memmove.o exp_tty_comm.o \
	exp_$(EVENT_TYPE).o exp_$(EVENT_ABLE).o

SHARED_OFILES = shared/exp_command.o shared/expect.o shared/$(PTY).o \
	shared/exp_inter.o shared/exp_regexp.o shared/exp_tty.o \
	shared/exp_log.o shared/exp_main_sub.o shared/exp_pty.o \
	shared/exp_printify.o shared/exp_trap.o \
	shared/exp_console.o shared/exp_strf.o shared/exp_glob.o \
	shared/exp_win.o shared/Dbg.o shared/exp_clib.o \
	shared/exp_closetcl.o shared/exp_memmove.o shared/exp_tty_comm.o \
	shared/exp_$(EVENT_TYPE).o shared/exp_$(EVENT_ABLE).o


# Expect libraries (both .a and shared)
EXP_LIB_FILES = @EXP_LIB_FILES@
# default Expect library (shared if possible, otherwise static)
EXP_LIB_FILE = @EXP_LIB_FILE@
# Expect object library (.a)
EXP_UNSHARED_LIB_FILE = @EXP_UNSHARED_LIB_FILE@







|
|

|
>

|
|

|
>



|

|

|
>







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  else echo runtest ;  fi`

PTY_TYPE = @PTY_TYPE@
PTY = pty_$(PTY_TYPE)
CFILES = exp_command.c expect.c $(PTY).c \
	exp_inter.c exp_regexp.c exp_tty.c \
	exp_log.c exp_main_sub.c exp_pty.c \
	exp_trap.c exp_strf.c \
	exp_console.c exp_glob.c exp_win.c exp_clib.c \
	exp_closetcl.c exp_memmove.c exp_tty_comm.c \
	exp_$(EVENT_TYPE).c exp_$(EVENT_ABLE).c \
	exp_chan.c Dbg.c
OFILES = exp_command.o expect.o $(PTY).o exp_inter.o exp_regexp.o exp_tty.o \
	exp_log.o exp_main_sub.o exp_pty.o exp_trap.o \
	exp_console.o exp_strf.o exp_glob.o exp_win.o exp_clib.o \
	exp_closetcl.o exp_memmove.o exp_tty_comm.o \
	exp_$(EVENT_TYPE).o exp_$(EVENT_ABLE).o \
	exp_chan.o Dbg.o
SHARED_OFILES = shared/exp_command.o shared/expect.o shared/$(PTY).o \
	shared/exp_inter.o shared/exp_regexp.o shared/exp_tty.o \
	shared/exp_log.o shared/exp_main_sub.o shared/exp_pty.o \
	shared/exp_trap.o \
	shared/exp_console.o shared/exp_strf.o shared/exp_glob.o \
	shared/exp_win.o shared/exp_clib.o \
	shared/exp_closetcl.o shared/exp_memmove.o shared/exp_tty_comm.o \
	shared/exp_$(EVENT_TYPE).o shared/exp_$(EVENT_ABLE).o \
	shared/exp_chan.o shared/Dbg.o

# Expect libraries (both .a and shared)
EXP_LIB_FILES = @EXP_LIB_FILES@
# default Expect library (shared if possible, otherwise static)
EXP_LIB_FILE = @EXP_LIB_FILE@
# Expect object library (.a)
EXP_UNSHARED_LIB_FILE = @EXP_UNSHARED_LIB_FILE@
312
313
314
315
316
317
318


319
320
321




322
323
324
325

326
327
328
329
330
331
332
	if [ "x$(EXP_UNSHARED_LIB_FILE)" != "x$(EXP_LIB_FILE)" ] ; then \
	   if [ ! -d shared ] ; then \
		mkdir shared ; \
	   else true; fi ; \
	   $(CC) -c $(CFLAGS_INT) @EXP_SHLIB_CFLAGS@ $(STTY) $(HDEFS) $< -o shared/$@ ; \
	fi



all: expect $(EXP_LIB_FILES) ${X11_PROGS}
	@$(MAKE) subdir_do DO=$@  $(FLAGS_TO_PASS)





info:
dvi:

# build expect binary that does not depend on Expect's shared libs

expect:	exp_main_exp.o $(EXP_UNSHARED_LIB_FILE)
	$(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expect exp_main_exp.o $(EXP_UNSHARED_LIB_FILE) $(TCLLIB) $(EXP_AND_TCL_LIBS)
	$(SETUID) expect

# install Expect library
# This is done before the install target because the libraries have to be
# in place before the installed expect is built.  Actually, only the shared







>
>
|


>
>
>
>




>







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
	if [ "x$(EXP_UNSHARED_LIB_FILE)" != "x$(EXP_LIB_FILE)" ] ; then \
	   if [ ! -d shared ] ; then \
		mkdir shared ; \
	   else true; fi ; \
	   $(CC) -c $(CFLAGS_INT) @EXP_SHLIB_CFLAGS@ $(STTY) $(HDEFS) $< -o shared/$@ ; \
	fi

all: binaries libraries doc

binaries: expect $(EXP_LIB_FILES) ${X11_PROGS}
	@$(MAKE) subdir_do DO=$@  $(FLAGS_TO_PASS)

libraries:

doc: info dvi

info:
dvi:

# build expect binary that does not depend on Expect's shared libs
# IFF static Tcl/Tk libraries are available.
expect:	exp_main_exp.o $(EXP_UNSHARED_LIB_FILE)
	$(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expect exp_main_exp.o $(EXP_UNSHARED_LIB_FILE) $(TCLLIB) $(EXP_AND_TCL_LIBS)
	$(SETUID) expect

# install Expect library
# This is done before the install target because the libraries have to be
# in place before the installed expect is built.  Actually, only the shared
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396


397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425


426
427
428
429
430
431
432
433











434
435
436
437
438
439
440
	$(SETUID) expect_installed

# Build Expect with TestCenter
expect.tc: exp_main_exp.o $(OFILES) 
	proof $(CC) $(XCFLAGS) @EXP_SHLIB_CFLAGS@ @TCL_LD_FLAGS@ -o expect.tc $(OFILES) exp_main_exp.o $(TCLLIB) $(EXP_AND_TCL_LIBS) 
	$(SETUID) expect.tc

# Build an executable with both Expect and Tk.

# Yes, I know that the link line can have libraries repeated.  This is a
# consequence of Tcl's configure combining the Tcl and X dependent libs
# together.  I could fix it by testing all the libraries (again, in Expect's
# configure) separately for Expectk, but as far as I know, it doesn't hurt
# anything here, so I'm not worrying about it.
expectk: exp_main_tk.o $(EXP_UNSHARED_LIB_FILE)
	$(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expectk exp_main_tk.o $(EXP_UNSHARED_LIB_FILE) $(TKLIB) $(TCLLIB) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk

expectk_installed: exp_main_tk.o $(EXP_LIB_FILE)
	$(CC) $(XCFLAGS) @EXP_SHLIB_CFLAGS@ @TCL_LD_FLAGS@ -o expectk_installed exp_main_tk.o @EXP_LIB_SPEC@ $(TKLIB_INSTALLED) $(TCLLIB_INSTALLED) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk_installed

# Build Expectk with TestCenter
expectk.tc: exp_main_tk.o $(OFILES) 
	proof $(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expectk.tc $(OFILES) exp_main_tk.o $(TKLIB) $(TCLLIB) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk.tc


$(EXP_UNSHARED_LIB_FILE): $(OFILES)
	-rm -f $(EXP_UNSHARED_LIB_FILE)
	$(AR) $(ARFLAGS) $(EXP_UNSHARED_LIB_FILE) $(OFILES)
	-$(UNSHARED_RANLIB) $(EXP_UNSHARED_LIB_FILE)

# the dependency should really be SHARED_OFILES rather than OFILES
# but there's no way to write a rule that says shared/XYZ.o should
# depend on XYZ.c in a different directory (except by writing the
# rule out for each file, sigh).

$(EXP_SHARED_LIB_FILE): $(OFILES)
	-rm -f $(EXP_SHARED_LIB_FILE)
	@TCL_SHLIB_LD@ -o $(EXP_SHARED_LIB_FILE) $(SHARED_OFILES) @EXP_LD_SEARCH_FLAGS@ @EXP_SHLIB_LD_LIBS@

.PHONY: install-info install info
install-info:



install:	expect expect_installed ${X11_PROGS_INSTALLED} $(SCRIPTS)
	${srcdir}/mkinstalldirs $(man1dir) $(man3dir) $(bindir) $(tcl_libdir) $(includedir)
# install Expect
	$(INSTALL_PROGRAM) expect_installed $(bindir)/expect
# install Expectk (and man page) if present
	-if [ -s expectk_installed ] ; then \
	  $(INSTALL_PROGRAM) expectk_installed $(bindir)/expectk ; \
	  $(INSTALL_DATA) $(srcdir)/expectk.man $(man1dir)/expectk.1 ; \
	else true; fi
# install Expect man page
	$(INSTALL_DATA) $(srcdir)/expect.man $(man1dir)/expect.1
# install man page for Expect and Expectk libraries
	$(INSTALL_DATA) $(srcdir)/libexpect.man $(man3dir)/libexpect.3
# install Expect's public include files
#	$(INSTALL_DATA) expect_cf.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect_tcl.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect_comm.h $(includedir)
# force installation of Tcl's private regexp definition - we simply have to
# make it public in order for people to use Expect's C lib.

	$(INSTALL_DATA) $(TCLHDIR)/tclRegexp.h $(includedir)
# install Debugger's public include file (just in case it's not there)
	$(INSTALL_DATA) $(srcdir)/tcldbg.h $(includedir)
# some people don't install Tcl, sigh
	TCL_LIBRARY=$(TCL_LIBRARY) ; \
	export TCL_LIBRARY ; \
	   if $(LOCAL_EXPECT) $(srcdir)/fixcat ; then \
	      $(INSTALL_DATA) $(srcdir)/fixcat $(EXECSCRIPTDIR)/cat-buffers ; \
	   else true; fi


# install standalone scripts and their man pages, if requested
	${srcdir}/mkinstalldirs $(bindir_arch_indep) $(man1dir) $(SCRIPTDIR) $(EXECSCRIPTDIR)
	-for i in $(SCRIPT_LIST) ; do \
	  if [ -f $$i ] ; then \
	    $(INSTALL_PROGRAM) $$i $(bindir_arch_indep)/$$i ; \
	    rm -f $$i ; \
	  else true; fi ; \
	done











	-for i in $(SCRIPT_MANPAGE_LIST) ; do \
	  if [ -f $(srcdir)/example/$$i.man ] ; then \
	    $(INSTALL_DATA) $(srcdir)/example/$$i.man $(man1dir)/$$i.1 ; \
	  else true; fi ; \
	done

$(SCRIPT_LIST):







|
>


















>









>







>
>
|






<

<
<
<
<







>
|








>
>








>
>
>
>
>
>
>
>
>
>
>







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

427




428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	$(SETUID) expect_installed

# Build Expect with TestCenter
expect.tc: exp_main_exp.o $(OFILES) 
	proof $(CC) $(XCFLAGS) @EXP_SHLIB_CFLAGS@ @TCL_LD_FLAGS@ -o expect.tc $(OFILES) exp_main_exp.o $(TCLLIB) $(EXP_AND_TCL_LIBS) 
	$(SETUID) expect.tc

# Build an executable with both Expect and Tk
# IFF static Tcl/Tk libraries are available.
# Yes, I know that the link line can have libraries repeated.  This is a
# consequence of Tcl's configure combining the Tcl and X dependent libs
# together.  I could fix it by testing all the libraries (again, in Expect's
# configure) separately for Expectk, but as far as I know, it doesn't hurt
# anything here, so I'm not worrying about it.
expectk: exp_main_tk.o $(EXP_UNSHARED_LIB_FILE)
	$(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expectk exp_main_tk.o $(EXP_UNSHARED_LIB_FILE) $(TKLIB) $(TCLLIB) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk

expectk_installed: exp_main_tk.o $(EXP_LIB_FILE)
	$(CC) $(XCFLAGS) @EXP_SHLIB_CFLAGS@ @TCL_LD_FLAGS@ -o expectk_installed exp_main_tk.o @EXP_LIB_SPEC@ $(TKLIB_INSTALLED) $(TCLLIB_INSTALLED) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk_installed

# Build Expectk with TestCenter
expectk.tc: exp_main_tk.o $(OFILES) 
	proof $(CC) $(XCFLAGS) @TCL_LD_FLAGS@ -o expectk.tc $(OFILES) exp_main_tk.o $(TKLIB) $(TCLLIB) $(X11_LD_FLAGS) $(EXP_AND_TK_LIBS) 
	$(SETUID) expectk.tc

expect-unshared-lib-file :: $(EXP_UNSHARED_LIB_FILE)
$(EXP_UNSHARED_LIB_FILE): $(OFILES)
	-rm -f $(EXP_UNSHARED_LIB_FILE)
	$(AR) $(ARFLAGS) $(EXP_UNSHARED_LIB_FILE) $(OFILES)
	-$(UNSHARED_RANLIB) $(EXP_UNSHARED_LIB_FILE)

# the dependency should really be SHARED_OFILES rather than OFILES
# but there's no way to write a rule that says shared/XYZ.o should
# depend on XYZ.c in a different directory (except by writing the
# rule out for each file, sigh).
expect-shared-lib-file :: $(EXP_SHARED_LIB_FILE)
$(EXP_SHARED_LIB_FILE): $(OFILES)
	-rm -f $(EXP_SHARED_LIB_FILE)
	@TCL_SHLIB_LD@ -o $(EXP_SHARED_LIB_FILE) $(SHARED_OFILES) @EXP_LD_SEARCH_FLAGS@ @EXP_SHLIB_LD_LIBS@

.PHONY: install-info install info
install-info:

install: all install-binaries install-libraries install-doc

install-binaries: expect expect_installed ${X11_PROGS_INSTALLED} $(SCRIPTS)
	${srcdir}/mkinstalldirs $(man1dir) $(man3dir) $(bindir) $(tcl_libdir) $(includedir)
# install Expect
	$(INSTALL_PROGRAM) expect_installed $(bindir)/expect
# install Expectk (and man page) if present
	-if [ -s expectk_installed ] ; then \
	  $(INSTALL_PROGRAM) expectk_installed $(bindir)/expectk ; \

	else true; fi




# install Expect's public include files
#	$(INSTALL_DATA) expect_cf.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect_tcl.h $(includedir)
	$(INSTALL_DATA) $(srcdir)/expect_comm.h $(includedir)
# force installation of Tcl's private regexp definition - we simply have to
# make it public in order for people to use Expect's C lib.
# hmm - no longer appropriate for Tcl 8.2+ - work on better solution?
#	$(INSTALL_DATA) $(TCLHDIR)/tclRegexp.h $(includedir)
# install Debugger's public include file (just in case it's not there)
	$(INSTALL_DATA) $(srcdir)/tcldbg.h $(includedir)
# some people don't install Tcl, sigh
	TCL_LIBRARY=$(TCL_LIBRARY) ; \
	export TCL_LIBRARY ; \
	   if $(LOCAL_EXPECT) $(srcdir)/fixcat ; then \
	      $(INSTALL_DATA) $(srcdir)/fixcat $(EXECSCRIPTDIR)/cat-buffers ; \
	   else true; fi

install-libraries:
# install standalone scripts and their man pages, if requested
	${srcdir}/mkinstalldirs $(bindir_arch_indep) $(man1dir) $(SCRIPTDIR) $(EXECSCRIPTDIR)
	-for i in $(SCRIPT_LIST) ; do \
	  if [ -f $$i ] ; then \
	    $(INSTALL_PROGRAM) $$i $(bindir_arch_indep)/$$i ; \
	    rm -f $$i ; \
	  else true; fi ; \
	done

install-doc:
	${srcdir}/mkinstalldirs $(man1dir) $(man3dir)
# install Expectk man page if present
	-if [ -s expectk_installed ] ; then \
	  $(INSTALL_DATA) $(srcdir)/expectk.man $(man1dir)/expectk.1 ; \
	else true; fi
# install Expect man page
	$(INSTALL_DATA) $(srcdir)/expect.man $(man1dir)/expect.1
# install man page for Expect and Expectk libraries
	$(INSTALL_DATA) $(srcdir)/libexpect.man $(man3dir)/libexpect.3
	-for i in $(SCRIPT_MANPAGE_LIST) ; do \
	  if [ -f $(srcdir)/example/$$i.man ] ; then \
	    $(INSTALL_DATA) $(srcdir)/example/$$i.man $(man1dir)/$$i.1 ; \
	  else true; fi ; \
	done

$(SCRIPT_LIST):
600
601
602
603
604
605
606



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
GCCROOT = /depot/gnu/arch/lib/gcc-lib/sparc-sun-sunos4.1/2.3.3
GCCLIB = $(GCCROOT)/libgcc.a
GCCINC = -I$(GCCROOT)/include
# following only on Sparcs
SABERDEFINE = -D__sparc__

# Following target builds expect under CodeCenter.



# If using ObjectCenter, before loading, type: setopt primary_language C
exp:	$(CFILES) exp_main_exp.c
	#load $(CPPFLAGS) $(STTY) $(CFILES) exp_main_exp.c $(TCLLIB) $(GCCLIB) $(EXP_AND_TCL_LIBS)

# Following target builds expectk under CodeCenter.  Notes:
# Because of explicit #includes of <X11/...> in tk.h, you need to create
# a symlink from your X11 include directory to this directory
tk:     $(CFILES) exp_main_tk.c
	#load $(CPPFLAGS) $(STTY) $(CFILES) exp_main_tk.c $(TKLIB) $(TCLLIB) $(EXP_AND_TK_LIBS)

# Follow definitions are for building expect and expectk under ObjectCenter
oexp:   $(CFILES) exp_main_exp.c
	#load $(CPPFLAGS) $(STTY) -C $(CFILES) exp_main_exp.c $(TCLLIB) $(GCCLIB) $(EXP_AND_TCL_LIBS)

otk:    $(CFILES) exp_main_tk.c
	#load $(CPPFLAGS) $(STTY) -C $(CFILES) exp_main_tk.c $(TKLIB) $(TCLLIB) $(EXP_AND_TK_LIBS)

######################################
# Targets for pushing out releases
######################################

# until we are completely switched over, keep updating old ftp site too
OLDFTPDIR = /proj/elib/online/pub/expect
FTPDIR = /proj/itl/www/div826/subject/expect

# make a private tar file for myself
tar:	expect-$(VERSION).tar
	mv expect-$(VERSION).tar expect.tar

# make a release and install it on ftp server

ftp:	expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz
	cp expect-$(VERSION).tar.Z $(FTPDIR)/expect.tar.Z
	cp expect-$(VERSION).tar.gz $(FTPDIR)/expect.tar.gz

	cp HISTORY $(FTPDIR)
	cp README $(FTPDIR)/README.distribution
	cp example/README $(FTPDIR)/example
	cp `pubfile example` $(FTPDIR)/example
	ls -l $(FTPDIR)/expect.tar*
#	update old ftp site too
	cp expect-$(VERSION).tar.Z $(OLDFTPDIR)/expect.tar.Z
	cp expect-$(VERSION).tar.gz $(OLDFTPDIR)/expect.tar.gz
	cp HISTORY $(OLDFTPDIR)
	cp README $(OLDFTPDIR)/README.distribution
	cp example/README $(OLDFTPDIR)/example
	cp `pubfile example` $(OLDFTPDIR)/example
	ls -l $(OLDFTPDIR)/expect.tar*
#	delete temp files
	rm expect-$(VERSION).tar*



# make an alpha release and install it on ftp server
alpha:	expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz
	cp expect-$(VERSION).tar.Z $(FTPDIR)/alpha.tar.Z
	cp expect-$(VERSION).tar.gz $(FTPDIR)/alpha.tar.gz
	cp HISTORY $(FTPDIR)
	rm expect-$(VERSION).tar*







>
>
>


|


















<
<







>
|


>





<
<
<
<
<
<
<
<


<
<







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662


663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679








680
681


682
683
684
685
686
687
688
GCCROOT = /depot/gnu/arch/lib/gcc-lib/sparc-sun-sunos4.1/2.3.3
GCCLIB = $(GCCROOT)/libgcc.a
GCCINC = -I$(GCCROOT)/include
# following only on Sparcs
SABERDEFINE = -D__sparc__

# Following target builds expect under CodeCenter.
# Note that CodeCenter doesn't understand backslashes in STTY - there is a
# default value in the code itself that is used.  So if you don't use the default,
# you'll have to hand-edit the source.
# If using ObjectCenter, before loading, type: setopt primary_language C
exp:	$(CFILES) exp_main_exp.c
	#load $(CPPFLAGS) $(CFILES) exp_main_exp.c $(TCLLIB) $(GCCLIB) $(EXP_AND_TCL_LIBS)

# Following target builds expectk under CodeCenter.  Notes:
# Because of explicit #includes of <X11/...> in tk.h, you need to create
# a symlink from your X11 include directory to this directory
tk:     $(CFILES) exp_main_tk.c
	#load $(CPPFLAGS) $(STTY) $(CFILES) exp_main_tk.c $(TKLIB) $(TCLLIB) $(EXP_AND_TK_LIBS)

# Follow definitions are for building expect and expectk under ObjectCenter
oexp:   $(CFILES) exp_main_exp.c
	#load $(CPPFLAGS) $(STTY) -C $(CFILES) exp_main_exp.c $(TCLLIB) $(GCCLIB) $(EXP_AND_TCL_LIBS)

otk:    $(CFILES) exp_main_tk.c
	#load $(CPPFLAGS) $(STTY) -C $(CFILES) exp_main_tk.c $(TKLIB) $(TCLLIB) $(EXP_AND_TK_LIBS)

######################################
# Targets for pushing out releases
######################################



FTPDIR = /proj/itl/www/div826/subject/expect

# make a private tar file for myself
tar:	expect-$(VERSION).tar
	mv expect-$(VERSION).tar expect.tar

# make a release and install it on ftp server
# update web page to reflect new version
ftp:	expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz install-html
	cp expect-$(VERSION).tar.Z $(FTPDIR)/expect.tar.Z
	cp expect-$(VERSION).tar.gz $(FTPDIR)/expect.tar.gz
	cp expect-$(VERSION).tar.gz $(FTPDIR)/old/expect-@[email protected]
	cp HISTORY $(FTPDIR)
	cp README $(FTPDIR)/README.distribution
	cp example/README $(FTPDIR)/example
	cp `pubfile example` $(FTPDIR)/example
	ls -l $(FTPDIR)/expect.tar*








#	delete temp files
	rm expect-$(VERSION).tar*



# make an alpha release and install it on ftp server
alpha:	expect-$(VERSION).tar.Z expect-$(VERSION).tar.gz
	cp expect-$(VERSION).tar.Z $(FTPDIR)/alpha.tar.Z
	cp expect-$(VERSION).tar.gz $(FTPDIR)/alpha.tar.gz
	cp HISTORY $(FTPDIR)
	rm expect-$(VERSION).tar*
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
test:   expect
	rm -f .tmp
	echo "set objdir" `pwd` > .tmp
	if [ "$(srcdir)" = "." ] ; then \
	   echo "set srcdir" `pwd` >> .tmp ; \
	else echo "set srcdir" $(srcdir) >> .tmp ; fi
	echo "cd \$${srcdir}/tests" >> .tmp
	echo "source all" >> .tmp
	rootme=`pwd`; export rootme; \
	srcdir=${srcdir} ; export srcdir ; \
	if [ -f ./expect ] ; then  \
	   TCL_LIBRARY=$(TCL_LIBRARY) ; \
	   export TCL_LIBRARY ; fi ; \
	$(LOCAL_EXPECT) -f .tmp
	rm -f .tmp







|







712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
test:   expect
	rm -f .tmp
	echo "set objdir" `pwd` > .tmp
	if [ "$(srcdir)" = "." ] ; then \
	   echo "set srcdir" `pwd` >> .tmp ; \
	else echo "set srcdir" $(srcdir) >> .tmp ; fi
	echo "cd \$${srcdir}/tests" >> .tmp
	echo "source all.tcl" >> .tmp
	rootme=`pwd`; export rootme; \
	srcdir=${srcdir} ; export srcdir ; \
	if [ -f ./expect ] ; then  \
	   TCL_LIBRARY=$(TCL_LIBRARY) ; \
	   export TCL_LIBRARY ; fi ; \
	$(LOCAL_EXPECT) -f .tmp
	rm -f .tmp
744
745
746
747
748
749
750
751



752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
Dbg.o: $(srcdir)/Dbg.c tcldbg.h 
exp_$(EVENT_ABLE).o: $(srcdir)/exp_$(EVENT_ABLE).c expect_cf.h expect.h \
	exp_command.h exp_event.h 
exp_$(EVENT_TYPE).o: $(srcdir)/exp_$(EVENT_TYPE).c expect_cf.h expect.h \
	exp_command.h exp_event.h 
exp_command.o: $(srcdir)/exp_command.c expect_cf.h exp_tty.h \
	exp_rename.h expect.h exp_command.h \
	exp_log.h exp_printify.h exp_event.h exp_pty.h 



exp_inter.o: $(srcdir)/exp_inter.c expect_cf.h \
	exp_tty_in.h exp_tty.h exp_rename.h expect.h exp_command.h \
	exp_log.h exp_printify.h exp_regexp.h exp_tstamp.h
exp_log.o: $(srcdir)/exp_log.c expect_cf.h expect.h \
	exp_rename.h exp_log.h exp_printify.h 
exp_main_exp.o: $(srcdir)/exp_main_exp.c expect_cf.h \
	expect.h exp_rename.h exp_command.h exp_log.h exp_printify.h
exp_main_sub.o: $(srcdir)/exp_main_sub.c expect_cf.h \
	exp_rename.h \
	expect.h exp_command.h exp_tty_in.h exp_tty.h exp_log.h \
	exp_printify.h exp_event.h 
exp_main_tk.o: $(srcdir)/exp_main_tk.c expect_cf.h tcldbg.h
	$(CC) -c @TK_DEFS@ $(CFLAGS_INT) $(HDEFS) $<	
shared/exp_main_tk.o: $(srcdir)/exp_main_tk.c expect_cf.h tcldbg.h
	$(CC) -c @TK_DEFS@ $(CFLAGS_INT) $(HDEFS) $<	
exp_noevent.o: $(srcdir)/exp_noevent.c expect_cf.h exp_prog.h exp_command.h \
	exp_event.h
exp_poll.o: $(srcdir)/exp_poll.c expect_cf.h expect.h \
	exp_command.h exp_event.h 
	$(CC) -c $(CFLAGS_INT) @TCL_DEFS@ $(HDEFS) $<
shared/exp_poll.o: $(srcdir)/exp_poll.c expect_cf.h expect.h \
	exp_command.h exp_event.h 
	$(CC) -c $(CFLAGS_INT) @EXP_SHLIB_CFLAGS@ @TCL_DEFS@ $(HDEFS) $< -o shared/$@
exp_printify.o: $(srcdir)/exp_printify.c expect_cf.h 
exp_pty.o: $(srcdir)/exp_pty.c expect_cf.h exp_rename.h exp_pty.h 
exp_regexp.o: $(srcdir)/exp_regexp.c expect_cf.h \
	expect.h exp_regexp.h 
exp_select.o: $(srcdir)/exp_select.c expect_cf.h \
	expect.h exp_command.h exp_event.h 
exp_simple.o: $(srcdir)/exp_simple.c expect_cf.h \
	expect.h exp_command.h exp_event.h 
exp_strf.o: $(srcdir)/exp_strf.c
exp_trap.o: $(srcdir)/exp_trap.c expect_cf.h expect.h \
	exp_command.h exp_log.h exp_printify.h 
exp_tty.o: $(srcdir)/exp_tty.c expect_cf.h \
	expect.h exp_rename.h exp_tty_in.h exp_tty.h exp_log.h \
	exp_printify.h exp_command.h 
exp_win.o: $(srcdir)/exp_win.c exp_win.h 
expect.o: $(srcdir)/expect.c expect_cf.h \
	exp_rename.h expect.h exp_command.h \
	exp_log.h exp_printify.h exp_event.h exp_tty.h exp_tstamp.h
lib_exp.o: $(srcdir)/lib_exp.c expect_cf.h exp_rename.h expect.h \
	exp_printify.h
pty_sgttyb.o: $(srcdir)/pty_sgttyb.c expect_cf.h exp_rename.h exp_tty_in.h \
	exp_tty.h exp_pty.h 
pty_termios.o: $(srcdir)/pty_termios.c expect_cf.h exp_win.h \
	exp_tty_in.h exp_tty.h exp_rename.h exp_pty.h 
pty_unicos.o: $(srcdir)/pty_unicos.c expect_cf.h exp_rename.h 







|
>
>
>


|

|

|



|












<







|

|


|
|


|
|
<





769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
Dbg.o: $(srcdir)/Dbg.c tcldbg.h 
exp_$(EVENT_ABLE).o: $(srcdir)/exp_$(EVENT_ABLE).c expect_cf.h expect.h \
	exp_command.h exp_event.h 
exp_$(EVENT_TYPE).o: $(srcdir)/exp_$(EVENT_TYPE).c expect_cf.h expect.h \
	exp_command.h exp_event.h 
exp_command.o: $(srcdir)/exp_command.c expect_cf.h exp_tty.h \
	exp_rename.h expect.h exp_command.h \
	exp_log.h exp_event.h exp_pty.h 
exp_console.o: $(srcdir)/exp_console.c expect_cf.h exp_rename.h exp_prog.h \
	exp_log.h
exp_glob.o: $(srcdir)/exp_glob.c expect_cf.h
exp_inter.o: $(srcdir)/exp_inter.c expect_cf.h \
	exp_tty_in.h exp_tty.h exp_rename.h expect.h exp_command.h \
	exp_log.h exp_regexp.h exp_tstamp.h
exp_log.o: $(srcdir)/exp_log.c expect_cf.h expect.h \
	exp_rename.h exp_log.h
exp_main_exp.o: $(srcdir)/exp_main_exp.c expect_cf.h \
	expect.h exp_rename.h exp_command.h exp_log.h
exp_main_sub.o: $(srcdir)/exp_main_sub.c expect_cf.h \
	exp_rename.h \
	expect.h exp_command.h exp_tty_in.h exp_tty.h exp_log.h \
	exp_event.h 
exp_main_tk.o: $(srcdir)/exp_main_tk.c expect_cf.h tcldbg.h
	$(CC) -c @TK_DEFS@ $(CFLAGS_INT) $(HDEFS) $<	
shared/exp_main_tk.o: $(srcdir)/exp_main_tk.c expect_cf.h tcldbg.h
	$(CC) -c @TK_DEFS@ $(CFLAGS_INT) $(HDEFS) $<	
exp_noevent.o: $(srcdir)/exp_noevent.c expect_cf.h exp_prog.h exp_command.h \
	exp_event.h
exp_poll.o: $(srcdir)/exp_poll.c expect_cf.h expect.h \
	exp_command.h exp_event.h 
	$(CC) -c $(CFLAGS_INT) @TCL_DEFS@ $(HDEFS) $<
shared/exp_poll.o: $(srcdir)/exp_poll.c expect_cf.h expect.h \
	exp_command.h exp_event.h 
	$(CC) -c $(CFLAGS_INT) @EXP_SHLIB_CFLAGS@ @TCL_DEFS@ $(HDEFS) $< -o shared/$@

exp_pty.o: $(srcdir)/exp_pty.c expect_cf.h exp_rename.h exp_pty.h 
exp_regexp.o: $(srcdir)/exp_regexp.c expect_cf.h \
	expect.h exp_regexp.h 
exp_select.o: $(srcdir)/exp_select.c expect_cf.h \
	expect.h exp_command.h exp_event.h 
exp_simple.o: $(srcdir)/exp_simple.c expect_cf.h \
	expect.h exp_command.h exp_event.h 
exp_strf.o: $(srcdir)/exp_strf.c expect_cf.h
exp_trap.o: $(srcdir)/exp_trap.c expect_cf.h expect.h \
	exp_command.h exp_log.h
exp_tty.o: $(srcdir)/exp_tty.c expect_cf.h \
	expect.h exp_rename.h exp_tty_in.h exp_tty.h exp_log.h \
	exp_command.h 
exp_win.o: $(srcdir)/exp_win.c exp_win.h expect_cf.h
expect.o: $(srcdir)/expect.c expect_cf.h \
	exp_rename.h expect.h exp_command.h \
	exp_log.h exp_event.h exp_tty.h exp_tstamp.h
lib_exp.o: $(srcdir)/lib_exp.c expect_cf.h exp_rename.h expect.h

pty_sgttyb.o: $(srcdir)/pty_sgttyb.c expect_cf.h exp_rename.h exp_tty_in.h \
	exp_tty.h exp_pty.h 
pty_termios.o: $(srcdir)/pty_termios.c expect_cf.h exp_win.h \
	exp_tty_in.h exp_tty.h exp_rename.h exp_pty.h 
pty_unicos.o: $(srcdir)/pty_unicos.c expect_cf.h exp_rename.h 

Changes to NEWS.

1
2
3
4
5




























































































































































6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This file is the NEWS file from the Expect distribution.

======================================================================
======================================================================





























































































































































Date: 8/18/96

Expect now works with Tcl 8.0.

No changes were made to take advantage of 8.0 features such as
namespaces.  (If you want to put the Expect commands in a namespace,
declare a namespace before loading them in.)

Even thought Tcl allows embedded nulls in commands, Expect still does
not.  Tcl still doesn't support embedded in patterns and regexps.
I'll wait til Tcl supports that before rewriting Expect's null
support.


======================================================================
======================================================================





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
This file is the NEWS file from the Expect distribution.

======================================================================
======================================================================

Date: 08/01/00

** SUMMARY

Expect 5.32 is being released in conjuction with Tcl 8.3.2.
This is a fairly minor update with no feature changes but with
a number of useful bug fixes in the way expects uses the new
regular expression engine and the UTF-8 features of Tcl.
Details are in the HISTORY and ChangeLog files.

======================================================================
======================================================================

Date: 10/22/99

** SUMMARY

Expect 5.31 now works with Tcl 8.2.  Expect 5.31 does NOT work with
prior releases of Tcl.  Thanks to an incredible amount of work by
Scott Stanton, Henry Spencer, Melissa Hirschl, and funding from
Scriptics for making this possible.

** NEW FEATURES

What?  You mean that working with Tcl 8.2 isn't enough?????

Expect supports Tcl's new regexp engine.

Expect supports null bytes in strings directly.  (You no longer have
to use the "null" keyword to send or match nulls.  Of course, the
"null" keyword will continue to be supported.)  Null removal (on
input) is still enabled by default since nulls are almost never
intended for end-user consumption in interactive dialogues.

** CHANGES IN BEHAVIOR (POTENTIAL INCOMPATIBILITIES)

The interpreter command used to exit upon eof.  Now it uses "-eof
script" to control this behavior.  The default behavior is to return.
(This change was required because Expect now gives control to Tcl upon
exit and Tcl waits (potentially forever) for all processes to die on
exit.)  Explicit calls to interpreter are almost non-existent.
However, you should look for *implicit* calls via interact commands
with a pattern but no action.  This required changes in the examples:
dislocate, dvorak, kibitz, and xkibitz.

Indirect variables can no longer start with "exp".  Such variables
will be interpreted as channel names.

Old-style regexps may need conversion.  If you have been protecting
regexps containing backslashes with {}, then you need to examine all
your backslashes since the new regexp engine interprets backslash
sequences (such as \n) itself.  For example:

	expect "\n"         (works the same in Tcl 8.0 and 8.1)
	expect {\n}         (works differently in Tcl 8.0 and 8.1)

Scriptics has also created a new-regexp-features page which you should
read: http://www.scriptics.com/support/howto/regexp81.html.  Some of
the new features allow much more efficient regexps than before.  For
example, non-greedy quantifiers can replace [split] looping
constructions with a single regexp, enabling Tcl to parse very
efficiently.  For the whole story, read the re_syntax man page.

The interact command's regexp matching no longer skips nulls.  (I'd be
surprised if anyone misses this.  At least I hope ....)

Expect's C library now reports failures in spawn's underlying exec
directly (by returning -1) rather than the way it used to (as data in
the pty).  This makes user code more robust.  However, it requires you
to simplify your code, alas.  See the chesslib.c example.

Linking with Expect's C library no longer requires the Tcl library
(unless, of course, you make Tcl calls yourself).  Tcl is still
required to build the library in the first place, however.

** CHANGES IN BEHAVIOR (SHOULD NOT CAUSE INCOMPATIBILITIES)

The match_max command now controls by bytes, not chars.  This won't
cause problems unless your existing scripts are interacting using
sizeable chunks of multibyte characters.  (If you don't know what I'm
talking about, ignore this.)

The Make/configure suite now corresponds to the TEA conventions (at
least in theory; the conventions are changing regularly so it's hard
to be less vague on this point).  Significantly, this means that you
should be able to use the same configure flags as when compiling Tcl
or any other TEA-compatible extension.  (See the INSTALL file.)

The values of special variables such as exp_spawn_id_any have changed.
(The values were never documented so you shouldn't have been using
them anyway.)

Spawn ids now appear as "exp...".  (They used to be small integers.)
Do not assume that spawn ids will continue to be represented in any
particular way (other than unique strings).

** OTHER NOTES

Expect uses channels.  There is an Expect channel type.  It is
possible to use Tcl's channel commands, such as fconfigure, to change
the encoding.  However, Expect layers its own buffering system on top
of Tcl's channel handler so don't expect intuitive behavior when using
commands such as gets and puts.  Unless you know what you're doing, I
recommend manipulating the Expect channels only with the expect
commands.

Some effort was made to make Expect support threads, however it is not
complete.  You can compile Expect with threads enabled but don't run
Expect in multiple threads just yet.

So much code has changed, there are bound to be bugs in dark corners.
Please let me know of such cases.  The best response will come by
supplying a simple test case that can be added to Expect's test suite.

In places where the behavior of Expect was not precisely documented,
full advantage was taken to do something different :-)

Several esoteric bugs were fixed.

Although Expect itself uses Henry Spencer's new regexp engine,
Expect's C library still uses his original regexp engine.

No testing has been done of the poll and non-event subsystems.  (These
are used on systems which don't support select on ptys or ttys.  Some
minor work needs to be done on them (because the event subsystem was
rewritten) which I'll probably do only if anyone requests it.

Many deprecated features (deprecated for many years!) have been
removed.  All such features were deprecated prior to Exploring Expect
so if that's how you learned Expect, you have nothing to worry about.
For example, Expect's getpid command predates Tcl's pid command and
it's been deprecated for, oh.... 6 years - wow!  Other deprecated features
include:
  expect -timestamp (flag only; behavior itself was removed years ago)
  expect -iwrite (flag only; behavior occurs all the time)
  expect_version (use "exp_version" command)
  expect_library (use "exp_library" global variable)
  interact -eof (use "eof" keyword)
  interact -timeout (use "timeout" keyword)
  interact -timestamp (use "clock" command)
  getpid (use "pid" command)
  system stty (use "stty" command)

With this release, the following are deprecated:
  timestamp (use "clock" command)
  debugger (use a different one; there are very nice replacements
     around.  Fortunately the Expect debugger is not something anyone
     is wiring into their scripts, so for now, consider it on the
     endangered species list.  Anyone still want this debugger?)

From now on, the most current snapshots of Expect will be found in the
Scriptics CVS repository.  Not all snapshots are official releases.

======================================================================
======================================================================

Date: 8/18/96

Expect now works with Tcl 8.0.

No changes were made to take advantage of 8.0 features such as
namespaces.  (If you want to put the Expect commands in a namespace,
declare a namespace before loading them in.)

Even though Tcl allows embedded nulls in commands, Expect still does
not.  Tcl still doesn't support embedded in patterns and regexps.
I'll wait til Tcl supports that before rewriting Expect's null
support.


======================================================================
======================================================================
548
549
550
551
552
553
554
555
556
557
558
559

3) String manipulation can be reduced or avoided entirely if you use
expect -re.

4) exec is no longer necessary to retrieve environment variables, since
they can now be retrieved from $env.

5) If you have been really anal about testing for timeout and eof, you
can dramatically reduce the size of your scripts by using expect_before
and expect_after.  This is more efficient, as well, since those actions
are only parsed once.








|
|
|
|

704
705
706
707
708
709
710
711
712
713
714
715

3) String manipulation can be reduced or avoided entirely if you use
expect -re.

4) exec is no longer necessary to retrieve environment variables, since
they can now be retrieved from $env.

5) If you have been really careful about testing for timeout and eof,
you can dramatically reduce the size of your scripts by using
expect_before and expect_after.  This is more efficient, as well,
since those actions are only parsed once.

Changes to README.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
NOTE: ALPHA AND BETA RELEASES OF TCL/TK ARE NOT SUPPORTED!

--------------------
Introduction
--------------------

This is the README file for Expect, a program that performs programmed
dialogue with other interactive programs.  It is briefly described by
its man page, expect(1).  This directory contains the source and man
page for Expect.

This is Expect 5 for Tcl 7.5, 7.6, and 8.0.  Tk 4.1, 4.2, 8.0 and the
Tcl Debugger are also supported.  Significant changes and other news
can be found in the NEWS file.

The Expect home page is: http://expect.nist.gov
The Expect FAQ is:       http://expect.nist.gov/FAQ.html

--------------------
Getting Started - The Preferable Way
--------------------











|
<
|







1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
NOTE: ALPHA AND BETA RELEASES OF TCL/TK ARE NOT SUPPORTED!

--------------------
Introduction
--------------------

This is the README file for Expect, a program that performs programmed
dialogue with other interactive programs.  It is briefly described by
its man page, expect(1).  This directory contains the source and man
page for Expect.

This is Expect 5.32 for Tcl 8.2 and Tk 8.2 (and Tcl and Tk 8.3).

Significant changes and other news can be found in the NEWS file.

The Expect home page is: http://expect.nist.gov
The Expect FAQ is:       http://expect.nist.gov/FAQ.html

--------------------
Getting Started - The Preferable Way
--------------------
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

The usual way of using Expect is as a standalone program with Tcl as
the control language.  Since you may already have Tcl, it is available
separately.  Tcl may be retrieved as tcl.tar.Z in the same way as
described above for Expect.  When new releases of Tcl appear, I will
try to check them out for Expect as soon as possible.  If you would
like to get the newest Tcl release without waiting, ftp it from
ftp.smli.com (directory pub/tcl).

Expect may also be built using the Tk library, a Tcl interface to the
X Window System.  Tk is available in the same way as Tcl.

It is possible to embed the Expect/Tcl core and optionally Tk in your
own C programs.  This is described in libexpect(3).








|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

The usual way of using Expect is as a standalone program with Tcl as
the control language.  Since you may already have Tcl, it is available
separately.  Tcl may be retrieved as tcl.tar.Z in the same way as
described above for Expect.  When new releases of Tcl appear, I will
try to check them out for Expect as soon as possible.  If you would
like to get the newest Tcl release without waiting, ftp it from
ftp.scriptics.com (directory pub/tcl).

Expect may also be built using the Tk library, a Tcl interface to the
X Window System.  Tk is available in the same way as Tcl.

It is possible to embed the Expect/Tcl core and optionally Tk in your
own C programs.  This is described in libexpect(3).

Changes to aclocal.m4.

96
97
98
99
100
101
102
103

104
105

106
107

108
109
110
111
112
113
114
115
116
117
118
119

120

121
122
123
124
125
126
127

# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[[7-9]].[[0-9]].[[0-9]] ${srcdir}/../tcl[[7-9]].[[0-9]] 2>/dev/null` \

		${srcdir}/../../tcl \
		`ls -dr ${srcdir}/../../tcl[[7-9]].[[0-9]].[[0-9]] ${srcdir}/../../tcl[[7-9]].[[0-9]] 2>/dev/null` \

		${srcdir}/../../../tcl \
		`ls -dr ${srcdir}/../../../tcl[[7-9]].[[0-9]].[[0-9]] ${srcdir}/../../../tcl[[7-9]].[[0-9]] 2>/dev/null ` ; do

    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tcl[[7-9]].[[0-9]].[[0-9]] /usr/local/src/tcl[[7-9]].[[0-9]] 2>/dev/null` \

		`ls -dr /usr/local/lib/tcl[[7-9]].[[0-9]].[[0-9]] /usr/local/lib/tcl[[7-9]].[[0-9]] 2>/dev/null` \

		/usr/local/src/tcl \
		/usr/local/lib/tcl \
		${prefix}/include ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi







|
>

|
>

|
>











|
>
|
>







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[[9]].[[0-9]].[[0-9]] ${srcdir}/../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../tcl[[8]].[[2-9]].[[0-9]] ${srcdir}/../tcl[[8]].[[2-9]] 2>/dev/null` \
		${srcdir}/../../tcl \
		`ls -dr ${srcdir}/../../tcl[[9]].[[0-9]].[[0-9]] ${srcdir}/../../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../../tcl[[8]].[[2-9]].[[0-9]] ${srcdir}/../../tcl[[8]].[[2-9]] 2>/dev/null` \
		${srcdir}/../../../tcl \
		`ls -dr ${srcdir}/../../../tcl[[9]].[[0-9]].[[0-9]] ${srcdir}/../../../tcl[[9]].[[0-9]] 2>/dev/null ` \
		`ls -dr ${srcdir}/../../../tcl[[8]].[[2-9]].[[0-9]] ${srcdir}/../../../tcl[[8]].[[2-9]] 2>/dev/null ` ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tcl[[9]].[[0-9]].[[0-9]] /usr/local/src/tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr /usr/local/src/tcl[[8]].[[2-9]].[[0-9]] /usr/local/src/tcl[[8]].[[2-9]] 2>/dev/null` \
		`ls -dr /usr/local/lib/tcl[[9]].[[0-9]].[[0-9]] /usr/local/lib/tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr /usr/local/lib/tcl[[8]].[[2-9]].[[0-9]] /usr/local/lib/tcl[[8]].[[2-9]] 2>/dev/null` \
		/usr/local/src/tcl \
		/usr/local/lib/tcl \
		${prefix}/include ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

191
192

193
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
])


AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tclconfig
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  AC_ARG_WITH(tclconfig, [  --with-tclconfig           directory containing tcl configuration (tclConfig.sh)],
         with_tclconfig=${withval})
  AC_MSG_CHECKING([for Tcl configuration])
  AC_CACHE_VAL(ac_cv_c_tclconfig,[

  # First check to see if --with-tclconfig was specified.
  if test x"${with_tclconfig}" != x ; then
    if test -f "${with_tclconfig}/tclConfig.sh" ; then
      ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
    else
      AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
    fi
  fi

  # then check for a private Tcl installation
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		../tcl \
		`ls -dr ../tcl[[7-9]].[[0-9]].[[0-9]] ../tcl[[7-9]].[[0-9]] 2>/dev/null` \

		../../tcl \
		`ls -dr ../../tcl[[7-9]].[[0-9]].[[0-9]] ../../tcl[[7-9]].[[0-9]] 2>/dev/null` \

		../../../tcl \
		`ls -dr ../../../tcl[[7-9]].[[0-9]].[[0-9]] ../../../tcl[[7-9]].[[0-9]] 2>/dev/null` ; do

      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[[7-9]].[[0-9]].[[0-9]] ${srcdir}/../tcl[[7-9]].[[0-9]] 2>/dev/null` ; do

      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  ])







|





|




|












|
>

|
>

|
>



















|
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
])


AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tcl
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  AC_ARG_WITH(tcl, [  --with-tcl           directory containing tcl configuration (tclConfig.sh)],
         with_tclconfig=${withval})
  AC_MSG_CHECKING([for Tcl configuration])
  AC_CACHE_VAL(ac_cv_c_tclconfig,[

  # First check to see if --with-tcl was specified.
  if test x"${with_tclconfig}" != x ; then
    if test -f "${with_tclconfig}/tclConfig.sh" ; then
      ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
    else
      AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
    fi
  fi

  # then check for a private Tcl installation
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		../tcl \
		`ls -dr ../tcl[[9]].[[0-9]].[[0-9]] ../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../tcl[[8]].[[2-9]].[[0-9]] ../tcl[[8]].[[2-9]] 2>/dev/null` \
		../../tcl \
		`ls -dr ../../tcl[[9]].[[0-9]].[[0-9]] ../../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../../tcl[[8]].[[2-9]].[[0-9]] ../../tcl[[8]].[[2-9]] 2>/dev/null` \
		../../../tcl \
		`ls -dr ../../../tcl[[9]].[[0-9]].[[0-9]] ../../../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../../../tcl[[8]].[[2-9]].[[0-9]] ../../../tcl[[8]].[[2-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[[9]].[[0-9]].[[0-9]] ${srcdir}/../tcl[[9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../tcl[[8]].[[2-9]].[[0-9]] ${srcdir}/../tcl[[8]].[[2-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  ])
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
dnl    AC_SUBST(TCL_LIB_FILE)

dnl don't export, not used outside of configure
dnl     AC_SUBST(TCL_LIBS)
dnl not used, don't export to save symbols
dnl    AC_SUBST(TCL_PREFIX)

dnl not used, don't export to save symbols
dnl    AC_SUBST(TCL_EXEC_PREFIX)


dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_SHLIB_CFLAGS)
    AC_SUBST(TCL_SHLIB_LD)
dnl don't export, not used outside of configure
dnl AC_SUBST(TCL_SHLIB_LD_LIBS)








<
|
<







257
258
259
260
261
262
263

264

265
266
267
268
269
270
271
dnl    AC_SUBST(TCL_LIB_FILE)

dnl don't export, not used outside of configure
dnl     AC_SUBST(TCL_LIBS)
dnl not used, don't export to save symbols
dnl    AC_SUBST(TCL_PREFIX)


    AC_SUBST(TCL_EXEC_PREFIX)


dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_SHLIB_CFLAGS)
    AC_SUBST(TCL_SHLIB_LD)
dnl don't export, not used outside of configure
dnl AC_SUBST(TCL_SHLIB_LD_LIBS)

276
277
278
279
280
281
282



283
284
285
286
287
288
289
dnl AC_SUBST(TCL_RANLIB)

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""



AC_CHECK_FUNC(Tcl_CreateCommand,[
	AC_MSG_CHECKING([if Tcl library build specification is valid])
	AC_MSG_RESULT(yes)
],[
	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.







>
>
>







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
dnl AC_SUBST(TCL_RANLIB)

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""
AC_MSG_CHECKING([Tcl build library])
AC_MSG_RESULT($LIBS)

AC_CHECK_FUNC(Tcl_CreateCommand,[
	AC_MSG_CHECKING([if Tcl library build specification is valid])
	AC_MSG_RESULT(yes)
],[
	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
])

# Warning: Tk definitions are very similar to Tcl definitions but
# are not precisely the same.  There are a couple of differences,
# so don't do changes to Tcl thinking you can cut and paste it do 
# the Tk differences and later simply substitute "Tk" for "Tcl".
# Known differences:
#  - Acceptable Tcl major version #s is 7-9 while Tk is 4-9
#  - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
#  - Computing major/minor versions is different because Tk depends on
#    headers to Tcl, Tk, and X.
#  - Symbols in tkConfig.sh are different than tclConfig.sh
#  - Acceptable for Tk to be missing but not Tcl.

AC_DEFUN(CY_AC_PATH_TKH, [







|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
])

# Warning: Tk definitions are very similar to Tcl definitions but
# are not precisely the same.  There are a couple of differences,
# so don't do changes to Tcl thinking you can cut and paste it do 
# the Tk differences and later simply substitute "Tk" for "Tcl".
# Known differences:
#  - Acceptable Tcl major version #s is 8.2-9.* while Tk is 8.2-9.*
#  - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
#  - Computing major/minor versions is different because Tk depends on
#    headers to Tcl, Tk, and X.
#  - Symbols in tkConfig.sh are different than tclConfig.sh
#  - Acceptable for Tk to be missing but not Tcl.

AC_DEFUN(CY_AC_PATH_TKH, [
353
354
355
356
357
358
359

360
361

362

363
364
365
366
367
368
369
370
371
372
373
374
375


376
377
378
379
380
381
382
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` \

		${srcdir}/../../tk \
		`ls -dr ${srcdir}/../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../tk[[4-9]].[[0-9]] 2>/dev/null` \

		${srcdir}/../../../tk \

		`ls -dr ${srcdir}/../../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../../tk[[4-9]].[[0-9]] 2>/dev/null ` ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/src/tk[[4-9]].[[0-9]] 2>/dev/null` \


		`ls -dr /usr/local/lib/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/lib/tk[[4-9]].[[0-9]] 2>/dev/null` \
		/usr/local/src/tk \
		/usr/local/lib/tk \
		${prefix}/include ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break







>


>

>













>
>







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` \
		${srcdir}/../../tk \
		`ls -dr ${srcdir}/../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../tk[[4-9]].[[0-9]] 2>/dev/null` \
		${srcdir}/../../../tk \
		`ls -dr ${srcdir}/../../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../../tk[[4-9]].[[0-9]] 2>/dev/null ` \
		`ls -dr ${srcdir}/../../../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../../../tk[[4-9]].[[0-9]] 2>/dev/null ` ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/src/tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr /usr/local/src/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/src/tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr /usr/local/lib/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/lib/tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr /usr/local/lib/tk[[4-9]].[[0-9]].[[0-9]] /usr/local/lib/tk[[4-9]].[[0-9]] 2>/dev/null` \
		/usr/local/src/tk \
		/usr/local/lib/tk \
		${prefix}/include ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

440
441

442

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

463
464
465
466
467
468
469
])


AC_DEFUN(CY_AC_PATH_TKCONFIG, [
#
# Ok, lets find the tk configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tkconfig
#

if test x"${no_tk}" = x ; then
  # we reset no_tk in case something fails here
  no_tk=true
  AC_ARG_WITH(tkconfig, [  --with-tkconfig           directory containing tk configuration (tkConfig.sh)],
         with_tkconfig=${withval})
  AC_MSG_CHECKING([for Tk configuration])
  AC_CACHE_VAL(ac_cv_c_tkconfig,[

  # First check to see if --with-tkconfig was specified.
  if test x"${with_tkconfig}" != x ; then
    if test -f "${with_tkconfig}/tkConfig.sh" ; then
      ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
    else
      AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
    fi
  fi

  # then check for a private Tk library
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		../tk \
		`ls -dr ../tk[[4-9]].[[0-9]].[[0-9]] ../tk[[4-9]].[[0-9]] 2>/dev/null` \

		../../tk \
		`ls -dr ../../tk[[4-9]].[[0-9]].[[0-9]] ../../tk[[4-9]].[[0-9]] 2>/dev/null` \

		../../../tk \

		`ls -dr ../../../tk[[4-9]].[[0-9]].[[0-9]] ../../../tk[[4-9]].[[0-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		${srcdir}/../tk \

		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi







|





|




|













>


>

>




















>







423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
])


AC_DEFUN(CY_AC_PATH_TKCONFIG, [
#
# Ok, lets find the tk configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tk
#

if test x"${no_tk}" = x ; then
  # we reset no_tk in case something fails here
  no_tk=true
  AC_ARG_WITH(tk, [  --with-tk           directory containing tk configuration (tkConfig.sh)],
         with_tkconfig=${withval})
  AC_MSG_CHECKING([for Tk configuration])
  AC_CACHE_VAL(ac_cv_c_tkconfig,[

  # First check to see if --with-tk was specified.
  if test x"${with_tkconfig}" != x ; then
    if test -f "${with_tkconfig}/tkConfig.sh" ; then
      ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
    else
      AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
    fi
  fi

  # then check for a private Tk library
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		../tk \
		`ls -dr ../tk[[4-9]].[[0-9]].[[0-9]] ../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../tk[[4-9]].[[0-9]].[[0-9]] ../tk[[4-9]].[[0-9]] 2>/dev/null` \
		../../tk \
		`ls -dr ../../tk[[4-9]].[[0-9]].[[0-9]] ../../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../../tk[[4-9]].[[0-9]].[[0-9]] ../../tk[[4-9]].[[0-9]] 2>/dev/null` \
		../../../tk \
		`ls -dr ../../../tk[[4-9]].[[0-9]].[[0-9]] ../../../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ../../../tk[[4-9]].[[0-9]].[[0-9]] ../../../tk[[4-9]].[[0-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` \
		`ls -dr ${srcdir}/../tk[[4-9]].[[0-9]].[[0-9]] ${srcdir}/../tk[[4-9]].[[0-9]] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
489
490
491
492
493
494
495

496
497
498
499
500
501
502
503
504
505
506
507
508


















509
510
511
512





















































    AC_SUBST(TK_VERSION)
dnl not actually used, don't export to save symbols
dnl    AC_SUBST(TK_MAJOR_VERSION)
dnl    AC_SUBST(TK_MINOR_VERSION)
    AC_SUBST(TK_DEFS)


dnl not used, don't export to save symbols
    dnl AC_SUBST(TK_LIB_FILE)

dnl not used outside of configure
dnl    AC_SUBST(TK_LIBS)
dnl not used, don't export to save symbols
dnl    AC_SUBST(TK_PREFIX)

dnl not used, don't export to save symbols
dnl    AC_SUBST(TK_EXEC_PREFIX)

    AC_SUBST(TK_XINCLUDES)
    AC_SUBST(TK_XLIBSW)


















    AC_SUBST(TK_BUILD_LIB_SPEC)
    AC_SUBST(TK_LIB_SPEC)
])




























































>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602

    AC_SUBST(TK_VERSION)
dnl not actually used, don't export to save symbols
dnl    AC_SUBST(TK_MAJOR_VERSION)
dnl    AC_SUBST(TK_MINOR_VERSION)
    AC_SUBST(TK_DEFS)

    AC_SUBST(TK_DBGX)
dnl not used, don't export to save symbols
    dnl AC_SUBST(TK_LIB_FILE)

dnl not used outside of configure
dnl    AC_SUBST(TK_LIBS)
dnl not used, don't export to save symbols
dnl    AC_SUBST(TK_PREFIX)

dnl not used, don't export to save symbols
dnl    AC_SUBST(TK_EXEC_PREFIX)

    AC_SUBST(TK_XINCLUDES)
    AC_SUBST(TK_XLIBSW)

# if Tk's build directory has been removed, TK_LIB_SPEC should
# be used instead of TK_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TK_DBGX
eval "LIBS=\"$TK_BUILD_LIB_SPEC $TCL_BUILD_LIB_SPEC $TK_LIBS\""
AC_CHECK_FUNC(Tk_Init,[
	AC_MSG_CHECKING([if Tk library build specification is valid])
	AC_MSG_RESULT(yes)
],[
	TK_BUILD_LIB_SPEC=$TK_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	AC_MSG_CHECKING([if Tk library build specification is valid])
	AC_MSG_RESULT(no)
])
LIBS=$SAVELIBS

    AC_SUBST(TK_BUILD_LIB_SPEC)
    AC_SUBST(TK_LIB_SPEC)
])

#------------------------------------------------------------------------
# SC_ENABLE_THREADS --
#
#	Specify if thread support should be enabled
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-threads
#
#	Sets the following vars:
#		THREADS_LIBS	Thread library(s)
#
#	Defines the following vars:
#		TCL_THREADS
#		_REENTRANT
#
#------------------------------------------------------------------------

AC_DEFUN(SC_ENABLE_THREADS, [
    AC_MSG_CHECKING(for building with threads)
    AC_ARG_ENABLE(threads, [  --enable-threads        build with threads (not supported)],
	[tcl_ok=$enableval], [tcl_ok=no])

    if test "$tcl_ok" = "yes"; then
	  AC_MSG_WARN([Expect is not fully thread-enabled.  Although significant work has been done towards that goal, it is not complete.  Continue compiling at your own risk.])
    fi
#    if test "$tcl_ok" = "yes"; then
#	AC_MSG_RESULT(yes)
#	TCL_THREADS=1
#	AC_DEFINE(TCL_THREADS)
#	AC_DEFINE(_REENTRANT)
#
#	AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
#	if test "$tcl_ok" = "yes"; then
#	    # The space is needed
#	    THREADS_LIBS=" -lpthread"
#	else
#	    TCL_THREADS=0
#	    AC_MSG_WARN("Don t know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...")
#	fi
#    else
#	TCL_THREADS=0
#	AC_MSG_RESULT(no (default))
#    fi

    AC_MSG_RESULT(no (default))

])

Changes to config.guess.

431
432
433
434
435
436
437



438
439
440
441
442
443
444
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit 0 ;;



esac

#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2

cat >dummy.c <<EOF
#ifdef _SEQUENT_







>
>
>







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
	if uname -p 2>/dev/null >/dev/null ; then
		UNAME_MACHINE=`(uname -p) 2>/dev/null`
		echo ${UNAME_MACHINE}-sni-sysv4
	else
		echo ns32k-sni-sysv
	fi
	exit 0 ;;
    Power*Macintosh:Darwin:*:*)
        echo powerpc-darwin${UNAME_RELEASE}
        exit 0 ;;
esac

#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2

cat >dummy.c <<EOF
#ifdef _SEQUENT_

Changes to configure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17


18
19
20
21
22
23
24
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.11 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help


  --with-tclconfig           directory containing tcl configuration (tclConfig.sh)"
ac_help="$ac_help
  --with-tkconfig           directory containing tk configuration (tkConfig.sh)"


ac_help="$ac_help
  --with-tclinclude       directory where tcl private headers are"
ac_help="$ac_help
  --enable-shared     build libexpect as a shared library"
ac_help="$ac_help
  --with-x               whether or not to use X (default yes)"
ac_help="$ac_help



|










>
>
|

|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.13 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
  --enable-threads        build with threads (not supported)"
ac_help="$ac_help
  --with-tcl           directory containing tcl configuration (tclConfig.sh)"
ac_help="$ac_help
  --with-tk           directory containing tk configuration (tkConfig.sh)"
ac_help="$ac_help
  --enable-symbols   allow use of symbols if available"
ac_help="$ac_help
  --with-tclinclude       directory where tcl private headers are"
ac_help="$ac_help
  --enable-shared     build libexpect as a shared library"
ac_help="$ac_help
  --with-x               whether or not to use X (default yes)"
ac_help="$ac_help
61
62
63
64
65
66
67

68
69
70
71
72
73
74
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=

# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12

ac_prev=
for ac_option
do








>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12

ac_prev=
for ac_option
do

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.11"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }







|







349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.13"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
446
447
448
449
450
451
452
453
454
455



456
457

458
459
460
461
462
463
464
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.
# Only set LANG and LC_ALL to C if already set.
# These must not be set unconditionally because not all systems understand
# e.g. LANG=C (notably SCO).



if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi


# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that







<
|
|
>
>
>

|
>







451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.

# Only set these to C if already set.  These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that
504
505
506
507
508
509
510
511

512


513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540






















































541
542
543
544
545
546
547
done


ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'




if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says [email protected].
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi



# note when updating version numbers here, also update pkgIndex.in (see
# comments in Makefile)
EXP_MAJOR_VERSION=5
EXP_MINOR_VERSION=28
EXP_MICRO_VERSION=1
EXP_VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION
EXP_VERSION_NODOTS=$EXP_MAJOR_VERSION$EXP_MINOR_VERSION
EXP_VERSION_FULL=$EXP_VERSION.$EXP_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION

# Too many people send me configure output without identifying the version.
# This forced identification should reduce my pain significantly.
echo "configuring Expect $EXP_MAJOR_VERSION.$EXP_MINOR_VERSION.$EXP_MICRO_VERSION"























































ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
  if test -f $ac_dir/install-sh; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install-sh -c"
    break







|
>

>
>

















|
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
done


ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

ac_exeext=
ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says [email protected].
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi



# note when updating version numbers here, also update pkgIndex.in (see
# comments in Makefile)
EXP_MAJOR_VERSION=5
EXP_MINOR_VERSION=34
EXP_MICRO_VERSION=0
EXP_VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION
EXP_VERSION_NODOTS=$EXP_MAJOR_VERSION$EXP_MINOR_VERSION
EXP_VERSION_FULL=$EXP_VERSION.$EXP_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION

# Too many people send me configure output without identifying the version.
# This forced identification should reduce my pain significantly.
echo "configuring Expect $EXP_MAJOR_VERSION.$EXP_MINOR_VERSION.$EXP_MICRO_VERSION"

# People (when downloading Expect from CVS archive) sometimes run into
# Make thinking configure is old and needs to be rebuilt.  If they
# don't have a clue about autoconf, they get confused.  This is
# particular irritating because the problem only crops up after
# configure has successfully completed.  Help them out by checking it
# right now and giving some advice.  Alas, we cannot summarily fix the
# problem because it might conceivably be someone doing real
# development.
# Test if configure is older than configure.in and explain if no autoconf
# Extract the first word of "autoconf", so it can be a program name with args.
set dummy autoconf; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:566: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_found'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$found"; then
  ac_cv_prog_found="$found" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_found="yes"
      break
    fi
  done
  IFS="$ac_save_ifs"
  test -z "$ac_cv_prog_found" && ac_cv_prog_found="no"
fi
fi
found="$ac_cv_prog_found"
if test -n "$found"; then
  echo "$ac_t""$found" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking configure up to date""... $ac_c" 1>&6
echo "configure:594: checking configure up to date" >&5
for i in `ls -tr ${srcdir}/configure ${srcdir}/configure.in ${srcdir}/Makefile.in` ; do
  newest=$i
done
if test "$srcdir/configure" = "$newest" ; then
  echo "$ac_t""yes" 1>&6
else
  echo "$ac_t""no" 1>&6
fi
if test $found = "no" -a "$newest" != "$srcdir/configure" ; then
  echo "configure: warning: $srcdir/configure appears to be old ($srcdir/configure.in and/or $srcdir/Makefile.in are newer) and the autoconf program to fix this situation was not found.  If you've no idea what this means, enter the command \"touch $srcdir/configure\" and restart $srcdir/configure." 1>&2
  exit
fi

ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
  if test -f $ac_dir/install-sh; then
    ac_aux_dir=$ac_dir
    ac_install_sh="$ac_aux_dir/install-sh -c"
    break
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
case $host---$target---$nonopt in
NONE---*---* | *---NONE---* | *---*---NONE) ;;
*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
esac


# Make sure we can run config.sub.
if $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi

echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:590: checking host system type" >&5

host_alias=$host
case "$host_alias" in
NONE)
  case $nonopt in
  NONE)
    if host_alias=`$ac_config_guess`; then :
    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
    fi ;;
  *) host_alias=$nonopt ;;
  esac ;;
esac

host=`$ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6

echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:611: checking target system type" >&5

target_alias=$target
case "$target_alias" in
NONE)
  case $nonopt in
  NONE) target_alias=$host_alias ;;
  *) target_alias=$nonopt ;;
  esac ;;
esac

target=`$ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6

echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:629: checking build system type" >&5

build_alias=$build
case "$build_alias" in
NONE)
  case $nonopt in
  NONE) build_alias=$host_alias ;;
  *) build_alias=$nonopt ;;
  esac ;;
esac

build=`$ac_config_sub $build_alias`
build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$build" 1>&6

test "$host_alias" != "$target_alias" &&
  test "$program_prefix$program_suffix$program_transform_name" = \
    NONENONEs,x,x, &&
  program_prefix=${target_alias}-




# /bin/sh on some systems is too deficient (in particular, Ultrix 4.3
# sh lacks unset and we *need* that), but all these systems come with
# alternatives, so take user's choice or whatever we're using here and
# allow it to be seen by Make.
echo $ac_n "checking shell to use within Make""... $ac_c" 1>&6
echo "configure:659: checking shell to use within Make" >&5
EXP_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
echo "$ac_t""$CONFIG_SHELL" 1>&6

# If `configure' is invoked (in)directly via `make', ensure that it
# encounters no `make' conflicts.
#
MFLAGS=
MAKEFLAGS=


#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tclconfig
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  # Check whether --with-tclconfig or --without-tclconfig was given.
if test "${with_tclconfig+set}" = set; then
  withval="$with_tclconfig"
  with_tclconfig=${withval}
fi

  echo $ac_n "checking for Tcl configuration""... $ac_c" 1>&6
echo "configure:686: checking for Tcl configuration" >&5
  if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tclconfig was specified.
  if test x"${with_tclconfig}" != x ; then
    if test -f "${with_tclconfig}/tclConfig.sh" ; then
      ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
    else
      { echo "configure: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" 1>&2; exit 1; }
    fi
  fi

  # then check for a private Tcl installation
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		../tcl \
		`ls -dr ../tcl[7-9].[0-9].[0-9] ../tcl[7-9].[0-9] 2>/dev/null` \
		../../tcl \
		`ls -dr ../../tcl[7-9].[0-9].[0-9] ../../tcl[7-9].[0-9] 2>/dev/null` \
		../../../tcl \
		`ls -dr ../../../tcl[7-9].[0-9].[0-9] ../../../tcl[7-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[7-9].[0-9].[0-9] ${srcdir}/../tcl[7-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  
fi

  if test x"${ac_cv_c_tclconfig}" = x ; then
    TCLCONFIG="# no Tcl configs found"
    echo "configure: warning: Can't find Tcl configuration definitions" 1>&2
  else
    no_tcl=
    TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
    echo "$ac_t""found $TCLCONFIG" 1>&6
  fi
fi


    . $TCLCONFIG

    
    
    





    

# Tcl defines TCL_SHLIB_SUFFIX but TCL_SHARED_LIB_SUFFIX then looks for it
# as just SHLIB_SUFFIX.  How bizarre.
    SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
    

    

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""
echo $ac_n "checking for Tcl_CreateCommand""... $ac_c" 1>&6
echo "configure:775: checking for Tcl_CreateCommand" >&5
if eval "test \"`echo '$''{'ac_cv_func_Tcl_CreateCommand'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 780 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char Tcl_CreateCommand(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char Tcl_CreateCommand();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_Tcl_CreateCommand) || defined (__stub___Tcl_CreateCommand)
choke me
#else
Tcl_CreateCommand();
#endif

; return 0; }
EOF
if { (eval echo configure:803: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'Tcl_CreateCommand`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:819: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""yes" 1>&6

else
  echo "$ac_t""no" 1>&6

	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:829: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""no" 1>&6

fi

LIBS=$SAVELIBS

    
    

    


CC=$TCL_CC
EXP_AND_TCL_LIBS=$TCL_LIBS

#
# Ok, lets find the tk configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tkconfig
#

if test x"${no_tk}" = x ; then
  # we reset no_tk in case something fails here
  no_tk=true
  # Check whether --with-tkconfig or --without-tkconfig was given.
if test "${with_tkconfig+set}" = set; then
  withval="$with_tkconfig"
  with_tkconfig=${withval}
fi

  echo $ac_n "checking for Tk configuration""... $ac_c" 1>&6
echo "configure:861: checking for Tk configuration" >&5
  if eval "test \"`echo '$''{'ac_cv_c_tkconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tkconfig was specified.
  if test x"${with_tkconfig}" != x ; then
    if test -f "${with_tkconfig}/tkConfig.sh" ; then
      ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
    else
      { echo "configure: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" 1>&2; exit 1; }
    fi
  fi

  # then check for a private Tk library
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		../tk \
		`ls -dr ../tk[4-9].[0-9].[0-9] ../tk[4-9].[0-9] 2>/dev/null` \
		../../tk \
		`ls -dr ../../tk[4-9].[0-9].[0-9] ../../tk[4-9].[0-9] 2>/dev/null` \
		../../../tk \
		`ls -dr ../../../tk[4-9].[0-9].[0-9] ../../../tk[4-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  
fi

  if test x"${ac_cv_c_tkconfig}" = x ; then
    TKCONFIG="# no Tk configs found"
    echo "configure: warning: Can't find Tk configuration definitions" 1>&2
  else
    no_tk=
    TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
    echo "$ac_t""found $TKCONFIG" 1>&6
  fi
fi



    if test -f "$TKCONFIG" ; then
      . $TKCONFIG
    fi

    
    

    


    
    
    
    

EXP_AND_TK_LIBS=$TK_LIBS

# An explanation is in order for the strange things going on with the
# various LIBS.  There are three separate definitions for LIBS.  The
# reason is that some systems require shared libraries include
# references to their dependent libraries, i.e., any additional
# libraries that must be linked to.  And some systems get upset if the
# references are repeated on the link line.  So therefore, we create
# one for Expect and Tk (EXP_AND_TK_LIBS), one for Expect and Tcl







|




|






|






|






|










|






|










|


















|









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732


















































































































































































































































































733
734
735
736
737
738
739
case $host---$target---$nonopt in
NONE---*---* | *---NONE---* | *---*---NONE) ;;
*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
esac


# Make sure we can run config.sub.
if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi

echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:655: checking host system type" >&5

host_alias=$host
case "$host_alias" in
NONE)
  case $nonopt in
  NONE)
    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
    fi ;;
  *) host_alias=$nonopt ;;
  esac ;;
esac

host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6

echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:676: checking target system type" >&5

target_alias=$target
case "$target_alias" in
NONE)
  case $nonopt in
  NONE) target_alias=$host_alias ;;
  *) target_alias=$nonopt ;;
  esac ;;
esac

target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6

echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:694: checking build system type" >&5

build_alias=$build
case "$build_alias" in
NONE)
  case $nonopt in
  NONE) build_alias=$host_alias ;;
  *) build_alias=$nonopt ;;
  esac ;;
esac

build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$build" 1>&6

test "$host_alias" != "$target_alias" &&
  test "$program_prefix$program_suffix$program_transform_name" = \
    NONENONEs,x,x, &&
  program_prefix=${target_alias}-




# /bin/sh on some systems is too deficient (in particular, Ultrix 4.3
# sh lacks unset and we *need* that), but all these systems come with
# alternatives, so take user's choice or whatever we're using here and
# allow it to be seen by Make.
echo $ac_n "checking shell to use within Make""... $ac_c" 1>&6
echo "configure:724: checking shell to use within Make" >&5
EXP_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
echo "$ac_t""$CONFIG_SHELL" 1>&6

# If `configure' is invoked (in)directly via `make', ensure that it
# encounters no `make' conflicts.
#
MFLAGS=
MAKEFLAGS=



















































































































































































































































































# An explanation is in order for the strange things going on with the
# various LIBS.  There are three separate definitions for LIBS.  The
# reason is that some systems require shared libraries include
# references to their dependent libraries, i.e., any additional
# libraries that must be linked to.  And some systems get upset if the
# references are repeated on the link line.  So therefore, we create
# one for Expect and Tk (EXP_AND_TK_LIBS), one for Expect and Tcl
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009
1010
1011
# are swapping out the one for Expect's shared library, we save it in
# EXP_LIBS.  Sigh.

OLD_CFLAGS=$CFLAGS
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:967: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"

  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:996: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  ac_prog_rejected=no

  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"







|






|
>
|




















|






|

>
|







750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
# are swapping out the one for Expect's shared library, we save it in
# EXP_LIBS.  Sigh.

OLD_CFLAGS=$CFLAGS
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:758: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:788: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_prog_rejected=no
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"
1032
1033
1034
1035
1036
1037
1038


































1039
1040
1041
1042
1043
1044




























1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096




1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125



1126
1127
1128















































































































































































































































































































































































































1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206


1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241


1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256

1257
1258
1259
1260
1261
1262
1263
1264
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi



































  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:1044: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5





























ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'

cat > conftest.$ac_ext <<EOF
#line 1053 "configure"
#include "confdefs.h"

int main() {

; return 0; }
EOF
if { (eval echo configure:1060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  ac_cv_prog_cc_works=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_prog_cc_works=no

fi
rm -f conftest*


echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: Installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi

echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:1078: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1087: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes




  ac_test_CFLAGS="${CFLAGS+set}"
  ac_save_CFLAGS="$CFLAGS"
  CFLAGS=
  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1102: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_gcc_g=yes
else
  ac_cv_prog_gcc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
  if test "$ac_test_CFLAGS" = set; then
    CFLAGS="$ac_save_CFLAGS"
  elif test $ac_cv_prog_gcc_g = yes; then

    CFLAGS="-g -O2"
  else
    CFLAGS="-O2"
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"



fi

CFLAGS=$OLD_CFLAGS
















































































































































































































































































































































































































# If we cannot compile and link a trivial program, we can't expect anything to work
echo $ac_n "checking whether the compiler ($CC) actually works""... $ac_c" 1>&6
echo "configure:1133: checking whether the compiler ($CC) actually works" >&5
cat > conftest.$ac_ext <<EOF
#line 1135 "configure"
#include "confdefs.h"

int main() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:1142: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  c_compiles=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_compiles=no
fi
rm -f conftest*


cat > conftest.$ac_ext <<EOF
#line 1155 "configure"
#include "confdefs.h"

int main() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:1162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  c_links=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_links=no
fi
rm -f conftest*


if test x"${c_compiles}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't compile." 1>&2; exit 1; }
fi

if test x"${c_links}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't link." 1>&2; exit 1; }
fi
echo "$ac_t""yes" 1>&6


# this'll use a BSD compatible install or our included install-sh
# Find a good install program.  We prefer a C program (faster),
# so one script is as good as another.  But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install

# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1196: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  for ac_dir in $PATH; do
    # Account for people who put trailing slashes in PATH elements.
    case "$ac_dir/" in
    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
    *)
      # OSF1 and SCO ODT 3.0 have their own names for install.


      for ac_prog in ginstall installbsd scoinst install; do
        if test -f $ac_dir/$ac_prog; then
	  if test $ac_prog = install &&
            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
	    # AIX install.  It has an incompatible calling convention.
	    # OSF/1 installbsd also uses dspmsg, but is usable.
	    :
	  else
	    ac_cv_path_install="$ac_dir/$ac_prog -c"
	    break 2
	  fi
	fi
      done
      ;;
    esac
  done
  IFS="$ac_save_ifs"

fi
  if test "${ac_cv_path_install+set}" = set; then
    INSTALL="$ac_cv_path_install"
  else
    # As a last resort, use the slow shell script.  We don't cache a
    # path for INSTALL within a source directory, because that will
    # break other packages using the cache if that directory is
    # removed, or if the path is relative.
    INSTALL="$ac_install_sh"
  fi
fi
echo "$ac_t""$INSTALL" 1>&6

# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'



test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'


# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1250: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"

  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_RANLIB="ranlib"
      break
    fi
  done
  IFS="$ac_save_ifs"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
|
<
<
<

<
<
<
<
<
<
|
<
<
<
<
|
>

<
|
|
|
|
<
<


|








|










>
>
>
>
|
|
|
|
|
|




|

|





|
|
|
|
>


|


|
|
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|

|






|










<

|






|









<



















>




|




|






>
>
|




<










|


















>
>







|






|
>
|







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905



906






907




908
909
910

911
912
913
914


915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398

1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

  if test -z "$CC"; then
    case "`uname -s`" in
    *win32* | *WIN32*)
      # Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:839: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="cl"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi
 ;;
    esac
  fi
  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:871: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

cat > conftest.$ac_ext << EOF

#line 882 "configure"
#include "confdefs.h"

main(){return(0);}
EOF
if { (eval echo configure:887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  ac_cv_prog_cc_works=yes
  # If we can't run a trivial program, we are probably using a cross compiler.
  if (./conftest; exit) 2>/dev/null; then
    ac_cv_prog_cc_cross=no
  else
    ac_cv_prog_cc_cross=yes
  fi
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  ac_cv_prog_cc_works=no
fi
rm -fr conftest*
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross










echo "$ac_t""$ac_cv_prog_cc_works" 1>&6




if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:913: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross



echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:918: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes
else
  GCC=
fi

ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:946: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_cc_g=yes
else
  ac_cv_prog_cc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
if test "$ac_test_CFLAGS" = set; then
  CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi
else
  if test "$GCC" = yes; then
    CFLAGS="-O2"
  else
    CFLAGS=
  fi
fi

CFLAGS=$OLD_CFLAGS

#------------------------------------------------------------------------
# Hook for when threading is supported in Expect.  The --enable-threads
# flag currently has no effect.
#------------------------------------------------------------------------


    echo $ac_n "checking for building with threads""... $ac_c" 1>&6
echo "configure:986: checking for building with threads" >&5
    # Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
  enableval="$enable_threads"
  tcl_ok=$enableval
else
  tcl_ok=no
fi


    if test "$tcl_ok" = "yes"; then
	  echo "configure: warning: Expect is not fully thread-enabled.  Although significant work has been done towards that goal, it is not complete.  Continue compiling at your own risk." 1>&2
    fi
#    if test "$tcl_ok" = "yes"; then
#	AC_MSG_RESULT(yes)
#	TCL_THREADS=1
#	AC_DEFINE(TCL_THREADS)
#	AC_DEFINE(_REENTRANT)
#
#	AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
#	if test "$tcl_ok" = "yes"; then
#	    # The space is needed
#	    THREADS_LIBS=" -lpthread"
#	else
#	    TCL_THREADS=0
#	    AC_MSG_WARN("Don t know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...")
#	fi
#    else
#	TCL_THREADS=0
#	AC_MSG_RESULT(no (default))
#    fi

    echo "$ac_t""no (default)" 1>&6




#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tcl
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  # Check whether --with-tcl or --without-tcl was given.
if test "${with_tcl+set}" = set; then
  withval="$with_tcl"
  with_tclconfig=${withval}
fi

  echo $ac_n "checking for Tcl configuration""... $ac_c" 1>&6
echo "configure:1039: checking for Tcl configuration" >&5
  if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tcl was specified.
  if test x"${with_tclconfig}" != x ; then
    if test -f "${with_tclconfig}/tclConfig.sh" ; then
      ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
    else
      { echo "configure: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" 1>&2; exit 1; }
    fi
  fi

  # then check for a private Tcl installation
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		../tcl \
		`ls -dr ../tcl[9].[0-9].[0-9] ../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ../tcl[8].[2-9].[0-9] ../tcl[8].[2-9] 2>/dev/null` \
		../../tcl \
		`ls -dr ../../tcl[9].[0-9].[0-9] ../../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ../../tcl[8].[2-9].[0-9] ../../tcl[8].[2-9] 2>/dev/null` \
		../../../tcl \
		`ls -dr ../../../tcl[9].[0-9].[0-9] ../../../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ../../../tcl[8].[2-9].[0-9] ../../../tcl[8].[2-9] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[9].[0-9].[0-9] ${srcdir}/../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../tcl[8].[2-9].[0-9] ${srcdir}/../tcl[8].[2-9] 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  
fi

  if test x"${ac_cv_c_tclconfig}" = x ; then
    TCLCONFIG="# no Tcl configs found"
    echo "configure: warning: Can't find Tcl configuration definitions" 1>&2
  else
    no_tcl=
    TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
    echo "$ac_t""found $TCLCONFIG" 1>&6
  fi
fi


    . $TCLCONFIG

    
    
    



    

    

# Tcl defines TCL_SHLIB_SUFFIX but TCL_SHARED_LIB_SUFFIX then looks for it
# as just SHLIB_SUFFIX.  How bizarre.
    SHLIB_SUFFIX=$TCL_SHLIB_SUFFIX
    

    

# if Tcl's build directory has been removed, TCL_LIB_SPEC should
# be used instead of TCL_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TCL_DBGX
eval "LIBS=\"$TCL_BUILD_LIB_SPEC $TCL_LIBS\""
echo $ac_n "checking Tcl build library""... $ac_c" 1>&6
echo "configure:1132: checking Tcl build library" >&5
echo "$ac_t""$LIBS" 1>&6

echo $ac_n "checking for Tcl_CreateCommand""... $ac_c" 1>&6
echo "configure:1136: checking for Tcl_CreateCommand" >&5
if eval "test \"`echo '$''{'ac_cv_func_Tcl_CreateCommand'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1141 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char Tcl_CreateCommand(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char Tcl_CreateCommand();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_Tcl_CreateCommand) || defined (__stub___Tcl_CreateCommand)
choke me
#else
Tcl_CreateCommand();
#endif

; return 0; }
EOF
if { (eval echo configure:1164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_Tcl_CreateCommand=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'Tcl_CreateCommand`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:1180: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""yes" 1>&6

else
  echo "$ac_t""no" 1>&6

	TCL_BUILD_LIB_SPEC=$TCL_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	echo $ac_n "checking if Tcl library build specification is valid""... $ac_c" 1>&6
echo "configure:1190: checking if Tcl library build specification is valid" >&5
	echo "$ac_t""no" 1>&6

fi

LIBS=$SAVELIBS

    
    

    


CC=$TCL_CC
EXP_AND_TCL_LIBS=$TCL_LIBS

#
# Ok, lets find the tk configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tk
#

if test x"${no_tk}" = x ; then
  # we reset no_tk in case something fails here
  no_tk=true
  # Check whether --with-tk or --without-tk was given.
if test "${with_tk+set}" = set; then
  withval="$with_tk"
  with_tkconfig=${withval}
fi

  echo $ac_n "checking for Tk configuration""... $ac_c" 1>&6
echo "configure:1222: checking for Tk configuration" >&5
  if eval "test \"`echo '$''{'ac_cv_c_tkconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tk was specified.
  if test x"${with_tkconfig}" != x ; then
    if test -f "${with_tkconfig}/tkConfig.sh" ; then
      ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
    else
      { echo "configure: error: ${with_tkconfig} directory doesn't contain tkConfig.sh" 1>&2; exit 1; }
    fi
  fi

  # then check for a private Tk library
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		../tk \
		`ls -dr ../tk[4-9].[0-9].[0-9] ../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ../tk[4-9].[0-9].[0-9] ../tk[4-9].[0-9] 2>/dev/null` \
		../../tk \
		`ls -dr ../../tk[4-9].[0-9].[0-9] ../../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ../../tk[4-9].[0-9].[0-9] ../../tk[4-9].[0-9] 2>/dev/null` \
		../../../tk \
		`ls -dr ../../../tk[4-9].[0-9].[0-9] ../../../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ../../../tk[4-9].[0-9].[0-9] ../../../tk[4-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tkconfig}" = x ; then
    for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` ; do
      if test -f "$i/unix/tkConfig.sh" ; then
        ac_cv_c_tkconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  
fi

  if test x"${ac_cv_c_tkconfig}" = x ; then
    TKCONFIG="# no Tk configs found"
    echo "configure: warning: Can't find Tk configuration definitions" 1>&2
  else
    no_tk=
    TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
    echo "$ac_t""found $TKCONFIG" 1>&6
  fi
fi



    if test -f "$TKCONFIG" ; then
      . $TKCONFIG
    fi

    
    

    
    


    
    

# if Tk's build directory has been removed, TK_LIB_SPEC should
# be used instead of TK_BUILD_LIB_SPEC
SAVELIBS=$LIBS
# eval used to expand out TK_DBGX
eval "LIBS=\"$TK_BUILD_LIB_SPEC $TCL_BUILD_LIB_SPEC $TK_LIBS\""
echo $ac_n "checking for Tk_Init""... $ac_c" 1>&6
echo "configure:1311: checking for Tk_Init" >&5
if eval "test \"`echo '$''{'ac_cv_func_Tk_Init'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1316 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char Tk_Init(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char Tk_Init();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_Tk_Init) || defined (__stub___Tk_Init)
choke me
#else
Tk_Init();
#endif

; return 0; }
EOF
if { (eval echo configure:1339: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_Tk_Init=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_Tk_Init=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'Tk_Init`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  
	echo $ac_n "checking if Tk library build specification is valid""... $ac_c" 1>&6
echo "configure:1355: checking if Tk library build specification is valid" >&5
	echo "$ac_t""yes" 1>&6

else
  echo "$ac_t""no" 1>&6

	TK_BUILD_LIB_SPEC=$TK_LIB_SPEC
	# Can't pull the following CHECKING call out since it will be
	# broken up by the CHECK_FUNC just above.
	echo $ac_n "checking if Tk library build specification is valid""... $ac_c" 1>&6
echo "configure:1365: checking if Tk library build specification is valid" >&5
	echo "$ac_t""no" 1>&6

fi

LIBS=$SAVELIBS

    
    

EXP_AND_TK_LIBS=$TK_LIBS


# If we cannot compile and link a trivial program, we can't expect anything to work
echo $ac_n "checking whether the compiler ($CC) actually works""... $ac_c" 1>&6
echo "configure:1380: checking whether the compiler ($CC) actually works" >&5
cat > conftest.$ac_ext <<EOF
#line 1382 "configure"
#include "confdefs.h"

int main() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:1389: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  c_compiles=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_compiles=no
fi
rm -f conftest*


cat > conftest.$ac_ext <<EOF
#line 1401 "configure"
#include "confdefs.h"

int main() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:1408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  c_links=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  c_links=no
fi
rm -f conftest*


if test x"${c_compiles}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't compile." 1>&2; exit 1; }
fi

if test x"${c_links}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't link." 1>&2; exit 1; }
fi
echo "$ac_t""yes" 1>&6


# this'll use a BSD compatible install or our included install-sh
# Find a good install program.  We prefer a C program (faster),
# so one script is as good as another.  But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1442: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    IFS="${IFS= 	}"; ac_save_IFS="$IFS"; IFS=":"
  for ac_dir in $PATH; do
    # Account for people who put trailing slashes in PATH elements.
    case "$ac_dir/" in
    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
    *)
      # OSF1 and SCO ODT 3.0 have their own names for install.
      # Don't use installbsd from OSF since it installs stuff as root
      # by default.
      for ac_prog in ginstall scoinst install; do
        if test -f $ac_dir/$ac_prog; then
	  if test $ac_prog = install &&
            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
	    # AIX install.  It has an incompatible calling convention.

	    :
	  else
	    ac_cv_path_install="$ac_dir/$ac_prog -c"
	    break 2
	  fi
	fi
      done
      ;;
    esac
  done
  IFS="$ac_save_IFS"

fi
  if test "${ac_cv_path_install+set}" = set; then
    INSTALL="$ac_cv_path_install"
  else
    # As a last resort, use the slow shell script.  We don't cache a
    # path for INSTALL within a source directory, because that will
    # break other packages using the cache if that directory is
    # removed, or if the path is relative.
    INSTALL="$ac_install_sh"
  fi
fi
echo "$ac_t""$INSTALL" 1>&6

# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'

test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'

test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'


# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1499: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$RANLIB"; then
  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_RANLIB="ranlib"
      break
    fi
  done
  IFS="$ac_save_ifs"
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320

















1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335


1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
# This is for LynxOS, which needs a flag to force true POSIX when
# building.  The flag varies depending how old the compiler is.
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1289: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 1304 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1310: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 1321 "configure"

















#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1327: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP=/lib/cpp


fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if running LynxOS""... $ac_c" 1>&6
echo "configure:1351: checking if running LynxOS" >&5
if eval "test \"`echo '$''{'ac_cv_os_lynx'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1356 "configure"
#include "confdefs.h"
/*
 * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
 */
#if defined(__Lynx__) || defined(Lynx)
yes
#endif







|














|





|
|









|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|








>
>














|




|







1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
# This is for LynxOS, which needs a flag to force true POSIX when
# building.  The flag varies depending how old the compiler is.
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1539: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 1554 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1560: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 1571 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1577: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP="${CC-cc} -nologo -E"
  cat > conftest.$ac_ext <<EOF
#line 1588 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1594: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if running LynxOS""... $ac_c" 1>&6
echo "configure:1620: checking if running LynxOS" >&5
if eval "test \"`echo '$''{'ac_cv_os_lynx'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1625 "configure"
#include "confdefs.h"
/*
 * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
 */
#if defined(__Lynx__) || defined(Lynx)
yes
#endif
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
if test "$ac_cv_os_lynx" = "yes" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define LYNX 1
EOF

  echo $ac_n "checking whether -mposix or -X is available""... $ac_c" 1>&6
echo "configure:1386: checking whether -mposix or -X is available" >&5
  if eval "test \"`echo '$''{'ac_cv_c_posix_flag'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1391 "configure"
#include "confdefs.h"

int main() {

  /*
   * This flag varies depending on how old the compiler is.
   * -X is for the old "cc" and "gcc" (based on 1.42).
   * -mposix is for the new gcc (at least 2.5.8).
   */
  #if defined(__GNUC__) && __GNUC__ >= 2
  choke me
  #endif
  
; return 0; }
EOF
if { (eval echo configure:1407: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_c_posix_flag=" -mposix"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_c_posix_flag=" -X"
fi
rm -f conftest*

fi

  CC="$CC $ac_cv_c_posix_flag"
  echo "$ac_t""$ac_cv_c_posix_flag" 1>&6
  else
  echo "$ac_t""no" 1>&6
fi


# If we cannot run a trivial program, we are probably using a cross compiler.
echo $ac_n "checking whether using a cross-compiler""... $ac_c" 1>&6
echo "configure:1429: checking whether using a cross-compiler" >&5
if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test "$cross_compiling" = yes; then
  ac_cv_c_cross=yes
else
  cat > conftest.$ac_ext <<EOF
#line 1437 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
{ (eval echo configure:1441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  ac_cv_c_cross=no
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  ac_cv_c_cross=yes
fi
rm -fr conftest*
fi

fi

echo "$ac_t""$ac_cv_c_cross" 1>&6
cross_compiling=$ac_cv_c_cross

echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:1459: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1464 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1472: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  ac_cv_header_stdc=yes
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1489 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "memchr" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1507 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "free" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then
  :
else
  cat > conftest.$ac_ext <<EOF
#line 1528 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int main () { int i; for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }

EOF
{ (eval echo configure:1539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  :
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  ac_cv_header_stdc=no
fi







|




|















|









<









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|




|







|
|















|

















|




















|










|
|







1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684

1685
1686
1687
1688
1689
1690
1691
1692
1693































1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
if test "$ac_cv_os_lynx" = "yes" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define LYNX 1
EOF

  echo $ac_n "checking whether -mposix or -X is available""... $ac_c" 1>&6
echo "configure:1655: checking whether -mposix or -X is available" >&5
  if eval "test \"`echo '$''{'ac_cv_c_posix_flag'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1660 "configure"
#include "confdefs.h"

int main() {

  /*
   * This flag varies depending on how old the compiler is.
   * -X is for the old "cc" and "gcc" (based on 1.42).
   * -mposix is for the new gcc (at least 2.5.8).
   */
  #if defined(__GNUC__) && __GNUC__ >= 2
  choke me
  #endif
  
; return 0; }
EOF
if { (eval echo configure:1676: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_c_posix_flag=" -mposix"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_c_posix_flag=" -X"
fi
rm -f conftest*

fi

  CC="$CC $ac_cv_c_posix_flag"
  echo "$ac_t""$ac_cv_c_posix_flag" 1>&6
  else
  echo "$ac_t""no" 1>&6
fi

































echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:1696: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1701 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1709: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  ac_cv_header_stdc=yes
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

if test $ac_cv_header_stdc = yes; then
  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1726 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "memchr" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1744 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "free" >/dev/null 2>&1; then
  :
else
  rm -rf conftest*
  ac_cv_header_stdc=no
fi
rm -f conftest*

fi

if test $ac_cv_header_stdc = yes; then
  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then
  :
else
  cat > conftest.$ac_ext <<EOF
#line 1765 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int main () { int i; for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }

EOF
if { (eval echo configure:1776: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  :
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  ac_cv_header_stdc=no
fi
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715









1716





1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
  cat >> confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF

fi

echo $ac_n "checking for pid_t""... $ac_c" 1>&6
echo "configure:1563: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1568 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_pid_t=yes
else
  rm -rf conftest*
  ac_cv_type_pid_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_pid_t" 1>&6
if test $ac_cv_type_pid_t = no; then
  cat >> confdefs.h <<\EOF
#define pid_t int
EOF

fi

echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
echo "configure:1596: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1601 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif

int main() {
int i;
; return 0; }
EOF
if { (eval echo configure:1618: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_type_signal=void
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_type_signal=int
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_type_signal" 1>&6
cat >> confdefs.h <<EOF
#define RETSIGTYPE $ac_cv_type_signal
EOF


echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
echo "configure:1638: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1643 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int main() {
struct tm *tp;
; return 0; }
EOF
if { (eval echo configure:1652: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_header_time=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_time=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_header_time" 1>&6
if test $ac_cv_header_time = yes; then
  cat >> confdefs.h <<\EOF
#define TIME_WITH_SYS_TIME 1
EOF

fi

echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
echo "configure:1674: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1679 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
int main() {
int s;
wait (&s);
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
if { (eval echo configure:1695: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_header_sys_wait_h=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_sys_wait_h=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
if test $ac_cv_header_sys_wait_h = yes; then
  cat >> confdefs.h <<\EOF
#define HAVE_SYS_WAIT_H 1
EOF

fi











EXP_CFLAGS=-g





case "${host}" in
 # Use -g on all systems but Linux where it upsets the dynamic X libraries.
  i[3456]86-*-linux*)	EXP_CFLAGS="" ;;
esac

echo $ac_n "checking if running Mach""... $ac_c" 1>&6
echo "configure:1724: checking if running Mach" >&5
mach=0
case "${host}" in
  # Both Next and pure Mach behave identically with respect
  # to a few things, so just lump them together as "mach"
  *-*-mach*)		mach=1 ;;
  *-*-next*)		mach=1 ; next=1 ;;
esac

if test $mach -eq 1 ; then
  echo "$ac_t""yes" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking if running MachTen""... $ac_c" 1>&6
echo "configure:1740: checking if running MachTen" >&5
# yet another Mach clone
if test -r /MachTen ; then
  echo "$ac_t""yes" 1>&6
  mach=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking if on Pyramid""... $ac_c" 1>&6
echo "configure:1750: checking if on Pyramid" >&5
if test -r /bin/pyr ; then
  echo "$ac_t""yes" 1>&6
  pyr=1
else
  echo "$ac_t""no" 1>&6
  pyr=0
fi

echo $ac_n "checking if on Apollo""... $ac_c" 1>&6
echo "configure:1760: checking if on Apollo" >&5
if test -r /usr/apollo/bin ; then
  echo "$ac_t""yes" 1>&6
  apollo=1
else
  echo "$ac_t""no" 1>&6
  apollo=0
fi

echo $ac_n "checking if on Interactive""... $ac_c" 1>&6
echo "configure:1770: checking if on Interactive" >&5
if test "x`(uname -s) 2>/dev/null`" = xIUNIX; then
  echo "$ac_t""yes" 1>&6
  iunix=1
else
  echo "$ac_t""no" 1>&6
  iunix=0
fi

echo $ac_n "checking if stty reads stdout""... $ac_c" 1>&6
echo "configure:1780: checking if stty reads stdout" >&5

# On some systems stty can't be run in the background (svr4) or get it
# wrong because they fail to complain (next, mach), so don't attempt
# the test on some systems.

stty_reads_stdout=""
case "${host}" in







|




|








|


















|




|
















|









<









|




|








|









<











|




|















|









<











>
>
>
>
>
>
>
>
>
|
>
>
>
>
>






|















|









|









|









|









|







1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863

1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
  cat >> confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF

fi

echo $ac_n "checking for pid_t""... $ac_c" 1>&6
echo "configure:1800: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1805 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#endif
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_type_pid_t=yes
else
  rm -rf conftest*
  ac_cv_type_pid_t=no
fi
rm -f conftest*

fi
echo "$ac_t""$ac_cv_type_pid_t" 1>&6
if test $ac_cv_type_pid_t = no; then
  cat >> confdefs.h <<\EOF
#define pid_t int
EOF

fi

echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
echo "configure:1833: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1838 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
#ifdef signal
#undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif

int main() {
int i;
; return 0; }
EOF
if { (eval echo configure:1855: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_type_signal=void
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_type_signal=int
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_type_signal" 1>&6
cat >> confdefs.h <<EOF
#define RETSIGTYPE $ac_cv_type_signal
EOF


echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
echo "configure:1874: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1879 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int main() {
struct tm *tp;
; return 0; }
EOF
if { (eval echo configure:1888: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_header_time=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_time=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_header_time" 1>&6
if test $ac_cv_header_time = yes; then
  cat >> confdefs.h <<\EOF
#define TIME_WITH_SYS_TIME 1
EOF

fi

echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
echo "configure:1909: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1914 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
int main() {
int s;
wait (&s);
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
if { (eval echo configure:1930: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_header_sys_wait_h=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  ac_cv_header_sys_wait_h=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
if test $ac_cv_header_sys_wait_h = yes; then
  cat >> confdefs.h <<\EOF
#define HAVE_SYS_WAIT_H 1
EOF

fi


# Check whether --enable-symbols or --disable-symbols was given.
if test "${enable_symbols+set}" = set; then
  enableval="$enable_symbols"
  enable_symbols=$enableval
else
  enable_symbols=no
fi

if test "$enable_symbols" = "no"; then
  EXP_CFLAGS="$TCL_EXTRA_CFLAGS"
else
  EXP_CFLAGS="-g $TCL_EXTRA_CFLAGS"
  # This is always "g" for unix.
  DBGX=g
fi
case "${host}" in
 # Use -g on all systems but Linux where it upsets the dynamic X libraries.
  i[3456]86-*-linux*)	EXP_CFLAGS="" ;;
esac

echo $ac_n "checking if running Mach""... $ac_c" 1>&6
echo "configure:1972: checking if running Mach" >&5
mach=0
case "${host}" in
  # Both Next and pure Mach behave identically with respect
  # to a few things, so just lump them together as "mach"
  *-*-mach*)		mach=1 ;;
  *-*-next*)		mach=1 ; next=1 ;;
esac

if test $mach -eq 1 ; then
  echo "$ac_t""yes" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking if running MachTen""... $ac_c" 1>&6
echo "configure:1988: checking if running MachTen" >&5
# yet another Mach clone
if test -r /MachTen ; then
  echo "$ac_t""yes" 1>&6
  mach=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking if on Pyramid""... $ac_c" 1>&6
echo "configure:1998: checking if on Pyramid" >&5
if test -r /bin/pyr ; then
  echo "$ac_t""yes" 1>&6
  pyr=1
else
  echo "$ac_t""no" 1>&6
  pyr=0
fi

echo $ac_n "checking if on Apollo""... $ac_c" 1>&6
echo "configure:2008: checking if on Apollo" >&5
if test -r /usr/apollo/bin ; then
  echo "$ac_t""yes" 1>&6
  apollo=1
else
  echo "$ac_t""no" 1>&6
  apollo=0
fi

echo $ac_n "checking if on Interactive""... $ac_c" 1>&6
echo "configure:2018: checking if on Interactive" >&5
if test "x`(uname -s) 2>/dev/null`" = xIUNIX; then
  echo "$ac_t""yes" 1>&6
  iunix=1
else
  echo "$ac_t""no" 1>&6
  iunix=0
fi

echo $ac_n "checking if stty reads stdout""... $ac_c" 1>&6
echo "configure:2028: checking if stty reads stdout" >&5

# On some systems stty can't be run in the background (svr4) or get it
# wrong because they fail to complain (next, mach), so don't attempt
# the test on some systems.

stty_reads_stdout=""
case "${host}" in
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
else
  echo "$ac_t""no" 1>&6
fi

# Solaris 2.4 and later requires __EXTENSIONS__ in order to see all sorts
# of traditional but nonstandard stuff in header files.
echo $ac_n "checking if running Solaris""... $ac_c" 1>&6
echo "configure:1836: checking if running Solaris" >&5
solaris=0
case "${host}" in
  *-*-solaris*)		solaris=1;;
esac

if test $solaris -eq 1 ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define SOLARIS 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


# On a few systems, libm.a is the same as libc.a
# Don't bother to test against Tcl and Tk libs, they always include -lm
echo $ac_n "checking for sin""... $ac_c" 1>&6
echo "configure:1856: checking for sin" >&5
if eval "test \"`echo '$''{'ac_cv_func_sin'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1861 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char sin(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|



















|




|







2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
else
  echo "$ac_t""no" 1>&6
fi

# Solaris 2.4 and later requires __EXTENSIONS__ in order to see all sorts
# of traditional but nonstandard stuff in header files.
echo $ac_n "checking if running Solaris""... $ac_c" 1>&6
echo "configure:2084: checking if running Solaris" >&5
solaris=0
case "${host}" in
  *-*-solaris*)		solaris=1;;
esac

if test $solaris -eq 1 ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define SOLARIS 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


# On a few systems, libm.a is the same as libc.a
# Don't bother to test against Tcl and Tk libs, they always include -lm
echo $ac_n "checking for sin""... $ac_c" 1>&6
echo "configure:2104: checking for sin" >&5
if eval "test \"`echo '$''{'ac_cv_func_sin'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2109 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char sin(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894

1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
choke me
#else
sin();
#endif

; return 0; }
EOF
if { (eval echo configure:1884: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_sin=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_sin=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'sin`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
LIBS="${LIBS} -lm" 
fi


# On Interactive UNIX, -Xp must be added to LIBS in order to find strftime.
# This test should really be done by Tcl.  So just check Tcl's definition.
# If defective, add to all three LIBS.  (It's not actually necessary for
# EXP_LIBS since -Xp will just be ignored the way that EXP_LIBS is used in
# the Makefile, but we include it for consistency.)
if test $iunix -eq 1 ; then
  EXP_LIBS=$LIBS
  LIBS=$EXP_AND_TCL_LIBS
  echo $ac_n "checking for strftime""... $ac_c" 1>&6
echo "configure:1914: checking for strftime" >&5
if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1919 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strftime(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>


















|




|







2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
choke me
#else
sin();
#endif

; return 0; }
EOF
if { (eval echo configure:2132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_sin=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_sin=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'sin`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
LIBS="${LIBS} -lm" 
fi


# On Interactive UNIX, -Xp must be added to LIBS in order to find strftime.
# This test should really be done by Tcl.  So just check Tcl's definition.
# If defective, add to all three LIBS.  (It's not actually necessary for
# EXP_LIBS since -Xp will just be ignored the way that EXP_LIBS is used in
# the Makefile, but we include it for consistency.)
if test $iunix -eq 1 ; then
  EXP_LIBS=$LIBS
  LIBS=$EXP_AND_TCL_LIBS
  echo $ac_n "checking for strftime""... $ac_c" 1>&6
echo "configure:2162: checking for strftime" >&5
if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2167 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strftime(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952

1953
1954
1955
1956
1957
1958
1959
choke me
#else
strftime();
#endif

; return 0; }
EOF
if { (eval echo configure:1942: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_strftime=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strftime=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6

	EXP_LIBS="${LIBS} -Xp" 







|









<

>







2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198

2199
2200
2201
2202
2203
2204
2205
2206
2207
choke me
#else
strftime();
#endif

; return 0; }
EOF
if { (eval echo configure:2190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_strftime=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strftime=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6

	EXP_LIBS="${LIBS} -Xp" 
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
echo $ac_n "checking for Tcl private headers""... $ac_c" 1>&6
echo "configure:1982: checking for Tcl private headers" >&5
# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
  withval="$with_tclinclude"
  with_tclinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tclh'+set}'`\" = set"; then







|







2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
echo $ac_n "checking for Tcl private headers""... $ac_c" 1>&6
echo "configure:2230: checking for Tcl private headers" >&5
# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
  withval="$with_tclinclude"
  with_tclinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tclh'+set}'`\" = set"; then
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018

2019
2020

2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032

2033

2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065

# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[7-9].[0-9].[0-9] ${srcdir}/../tcl[7-9].[0-9] 2>/dev/null` \

		${srcdir}/../../tcl \
		`ls -dr ${srcdir}/../../tcl[7-9].[0-9].[0-9] ${srcdir}/../../tcl[7-9].[0-9] 2>/dev/null` \

		${srcdir}/../../../tcl \
		`ls -dr ${srcdir}/../../../tcl[7-9].[0-9].[0-9] ${srcdir}/../../../tcl[7-9].[0-9] 2>/dev/null ` ; do

    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tcl[7-9].[0-9].[0-9] /usr/local/src/tcl[7-9].[0-9] 2>/dev/null` \

		`ls -dr /usr/local/lib/tcl[7-9].[0-9].[0-9] /usr/local/lib/tcl[7-9].[0-9] 2>/dev/null` \

		/usr/local/src/tcl \
		/usr/local/lib/tcl \
		${prefix}/include ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
   ac_safe=`echo "tclInt.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tclInt.h""... $ac_c" 1>&6
echo "configure:2048: checking for tclInt.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2053 "configure"
#include "confdefs.h"
#include <tclInt.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|
>

|
>

|
>











|
>
|
>













|




|




|
|







2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318

# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[9].[0-9].[0-9] ${srcdir}/../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../tcl[8].[2-9].[0-9] ${srcdir}/../tcl[8].[2-9] 2>/dev/null` \
		${srcdir}/../../tcl \
		`ls -dr ${srcdir}/../../tcl[9].[0-9].[0-9] ${srcdir}/../../tcl[9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../../tcl[8].[2-9].[0-9] ${srcdir}/../../tcl[8].[2-9] 2>/dev/null` \
		${srcdir}/../../../tcl \
		`ls -dr ${srcdir}/../../../tcl[9].[0-9].[0-9] ${srcdir}/../../../tcl[9].[0-9] 2>/dev/null ` \
		`ls -dr ${srcdir}/../../../tcl[8].[2-9].[0-9] ${srcdir}/../../../tcl[8].[2-9] 2>/dev/null ` ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tcl[9].[0-9].[0-9] /usr/local/src/tcl[9].[0-9] 2>/dev/null` \
		`ls -dr /usr/local/src/tcl[8].[2-9].[0-9] /usr/local/src/tcl[8].[2-9] 2>/dev/null` \
		`ls -dr /usr/local/lib/tcl[9].[0-9].[0-9] /usr/local/lib/tcl[9].[0-9] 2>/dev/null` \
		`ls -dr /usr/local/lib/tcl[8].[2-9].[0-9] /usr/local/lib/tcl[8].[2-9] 2>/dev/null` \
		/usr/local/src/tcl \
		/usr/local/lib/tcl \
		${prefix}/include ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
   ac_safe=`echo "tclInt.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tclInt.h""... $ac_c" 1>&6
echo "configure:2301: checking for tclInt.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2306 "configure"
#include "confdefs.h"
#include <tclInt.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2311: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
    echo "	If Tcl is installed, see INSTALL on how to tell"
    echo "	configure where Tcl is installed."
    exit 1
fi

# have to know whether we're generating shared libs before configuring debugger
echo $ac_n "checking type of library to build""... $ac_c" 1>&6
echo "configure:2119: checking type of library to build" >&5
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  enable_shared=$enableval
else
  enable_shared=no
fi







|







2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
    echo "	If Tcl is installed, see INSTALL on how to tell"
    echo "	configure where Tcl is installed."
    exit 1
fi

# have to know whether we're generating shared libs before configuring debugger
echo $ac_n "checking type of library to build""... $ac_c" 1>&6
echo "configure:2372: checking type of library to build" >&5
# Check whether --enable-shared or --disable-shared was given.
if test "${enable_shared+set}" = set; then
  enableval="$enable_shared"
  enable_shared=$enableval
else
  enable_shared=no
fi
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
echo "up to three times.  First test is for building Expect's shared library."
echo "Second set is for building with Tcl.  Third is for building with Tk."

######################################################################
# required by Sequent ptx2
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2198: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2203 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
echo "up to three times.  First test is for building Expect's shared library."
echo "Second set is for building with Tcl.  Third is for building with Tk."

######################################################################
# required by Sequent ptx2
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2451: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2456 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236

2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2226: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2249: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2257 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487

2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2502: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2510 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2521: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2294: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2299 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2547: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2552 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332

2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2322: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2345: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2353 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2364: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583

2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2598: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2606 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2390: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2395 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_gethostname
echo $ac_n "checking for gethostname""... $ac_c" 1>&6
echo "configure:2643: checking for gethostname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2648 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char gethostname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2441: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2449 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2460: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679

2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
choke me
#else
gethostname();
#endif

; return 0; }
EOF
if { (eval echo configure:2671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_gethostname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_gethostname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'gethostname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  gethostname=1 
else
  echo "$ac_t""no" 1>&6
gethostname=0
fi

if test $gethostname -eq 0 ; then
  unset ac_cv_lib_inet_gethostname
  echo $ac_n "checking for gethostname in -linet""... $ac_c" 1>&6
echo "configure:2694: checking for gethostname in -linet" >&5
ac_lib_var=`echo inet'_'gethostname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2702 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char gethostname();

int main() {
gethostname()
; return 0; }
EOF
if { (eval echo configure:2713: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# required by Fischman's ISC 4.0
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2489: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2494 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# required by Fischman's ISC 4.0
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2742: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2747 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527

2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2540: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2548 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:2559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778

2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2770: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2793: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2801 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:2812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2585: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2590 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2838: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2843 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623

2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2636: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2644 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:2655: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874

2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2889: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2897 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:2908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2681: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2686 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_socket
echo $ac_n "checking for socket""... $ac_c" 1>&6
echo "configure:2934: checking for socket" >&5
if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2939 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char socket(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719

2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2732: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2740 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:2751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970

2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
choke me
#else
socket();
#endif

; return 0; }
EOF
if { (eval echo configure:2962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_socket=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_socket=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  socket=1 
else
  echo "$ac_t""no" 1>&6
socket=0
fi

if test $socket -eq 0 ; then
  unset ac_cv_lib_inet_socket
  echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
echo "configure:2985: checking for socket in -linet" >&5
ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2993 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char socket();

int main() {
socket()
; return 0; }
EOF
if { (eval echo configure:3004: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:2779: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2784 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:3032: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3037 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817

2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:2807: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:2830: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2838 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:2849: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068

3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:3060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:3083: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3091 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:3102: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:2875: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2880 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:3128: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3133 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913

2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:2903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:2926: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2934 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:2945: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164

3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:3156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:3179: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3187 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:3198: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:2971: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 2976 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:3224: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3229 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009

3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:2999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:3022: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3030 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:3041: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260

3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:3252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1 
else
  echo "$ac_t""no" 1>&6
select=0
fi

if test $select -eq 0 ; then
  unset ac_cv_lib_inet_select
  echo $ac_n "checking for select in -linet""... $ac_c" 1>&6
echo "configure:3275: checking for select in -linet" >&5
ac_lib_var=`echo inet'_'select | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-linet  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3283 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char select();

int main() {
select()
; return 0; }
EOF
if { (eval echo configure:3294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3069: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3074 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3322: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3327 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107

3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3120: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3128 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358

3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3350: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3373: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3381 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3172: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3177 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3425: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3430 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210

3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3223: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3231 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461

3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3476: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3484 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3275: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3280 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_getpseudotty
echo $ac_n "checking for getpseudotty""... $ac_c" 1>&6
echo "configure:3528: checking for getpseudotty" >&5
if eval "test \"`echo '$''{'ac_cv_func_getpseudotty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3533 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char getpseudotty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313

3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3303: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3326: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3334 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
choke me
#else
getpseudotty();
#endif

; return 0; }
EOF
if { (eval echo configure:3556: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_getpseudotty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'getpseudotty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  getpseudotty=1 
else
  echo "$ac_t""no" 1>&6
getpseudotty=0
fi

if test $getpseudotty -eq 0 ; then
  unset ac_cv_lib_seq_getpseudotty
  echo $ac_n "checking for getpseudotty in -lseq""... $ac_c" 1>&6
echo "configure:3579: checking for getpseudotty in -lseq" >&5
ac_lib_var=`echo seq'_'getpseudotty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lseq  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3587 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char getpseudotty();

int main() {
getpseudotty()
; return 0; }
EOF
if { (eval echo configure:3598: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# Check for FreeBSD/NetBSD openpty()
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3381: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3386 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# Check for FreeBSD/NetBSD openpty()
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3634: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3639 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419

3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3432: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3440 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670

3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3685: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3693 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3486: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3491 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750

fi
# save results and retry for Tcl
EXP_LIBS=$LIBS
LIBS=$EXP_AND_TCL_LIBS
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3739: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3744 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524

3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3537: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3545 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3556: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775

3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3767: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3790: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3798 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3588: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3593 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852

fi
# save Tcl results and retry for Tk
EXP_AND_TCL_LIBS=$LIBS
LIBS=$EXP_AND_TK_LIBS
unset ac_cv_func_openpty
echo $ac_n "checking for openpty""... $ac_c" 1>&6
echo "configure:3841: checking for openpty" >&5
if eval "test \"`echo '$''{'ac_cv_func_openpty'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3846 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char openpty(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626

3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3639: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3647 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"







|









<

>











|







|










|







3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
choke me
#else
openpty();
#endif

; return 0; }
EOF
if { (eval echo configure:3869: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_openpty=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_openpty=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'openpty`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  openpty=1 
else
  echo "$ac_t""no" 1>&6
openpty=0
fi

if test $openpty -eq 0 ; then
  unset ac_cv_lib_util_openpty
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
echo "configure:3892: checking for openpty in -lutil" >&5
ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lutil  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3900 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char openpty();

int main() {
openpty()
; return 0; }
EOF
if { (eval echo configure:3911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
3684
3685
3686
3687
3688
3689
3690











3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# End of library/func checking
######################################################################












######################################################################
#
# Look for various header files
#
ac_safe=`echo "sys/sysmacros.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/sysmacros.h""... $ac_c" 1>&6
echo "configure:3699: checking for sys/sysmacros.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3704 "configure"
#include "confdefs.h"
#include <sys/sysmacros.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3709: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







>
>
>
>
>
>
>
>
>
>
>







|




|




|
|







3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# End of library/func checking
######################################################################

# Hand patches to library/func checking.

echo $ac_n "checking if running Sequent running SVR4""... $ac_c" 1>&6
echo "configure:3949: checking if running Sequent running SVR4" >&5
if test "$host_alias" = "i386-sequent-sysv4" ; then
 EXP_AND_TCL_LIBS="-lnsl -lsocket -lm"
  echo "$ac_t""yes" 1>&6
else
 echo "$ac_t""no" 1>&6
fi

######################################################################
#
# Look for various header files
#
ac_safe=`echo "sys/sysmacros.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/sysmacros.h""... $ac_c" 1>&6
echo "configure:3963: checking for sys/sysmacros.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3968 "configure"
#include "confdefs.h"
#include <sys/sysmacros.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6
echo "configure:3735: checking for stdlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3740 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3745: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6
echo "configure:3999: checking for stdlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4004 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4009: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
#define NO_STDLIB_H 1
EOF

fi

ac_safe=`echo "inttypes.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
echo "configure:3772: checking for inttypes.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3777 "configure"
#include "confdefs.h"
#include <inttypes.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
#define NO_STDLIB_H 1
EOF

fi

ac_safe=`echo "inttypes.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
echo "configure:4036: checking for inttypes.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4041 "configure"
#include "confdefs.h"
#include <inttypes.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4046: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829


# Oddly, some systems have stdarg but don't support prototypes
# Tcl avoids the whole issue by not using stdarg on UNIX at all!

ac_safe=`echo "varargs.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for varargs.h""... $ac_c" 1>&6
echo "configure:3812: checking for varargs.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3817 "configure"
#include "confdefs.h"
#include <varargs.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3822: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093


# Oddly, some systems have stdarg but don't support prototypes
# Tcl avoids the whole issue by not using stdarg on UNIX at all!

ac_safe=`echo "varargs.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for varargs.h""... $ac_c" 1>&6
echo "configure:4076: checking for varargs.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4081 "configure"
#include "confdefs.h"
#include <varargs.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4086: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "unistd.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for unistd.h""... $ac_c" 1>&6
echo "configure:3848: checking for unistd.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3853 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3858: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "unistd.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for unistd.h""... $ac_c" 1>&6
echo "configure:4112: checking for unistd.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4117 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4122: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3874
3875
3876
3877
3878
3879
3880


3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914

3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
#define HAVE_UNISTD_H 1
EOF

else
  echo "$ac_t""no" 1>&6
fi



ac_safe=`echo "sys/stropts.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/stropts.h""... $ac_c" 1>&6
echo "configure:3884: checking for sys/stropts.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3889 "configure"
#include "confdefs.h"
#include <sys/stropts.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3894: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STROPTS_H 1
EOF

else
  echo "$ac_t""no" 1>&6

fi

ac_safe=`echo "sys/sysconfig.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/sysconfig.h""... $ac_c" 1>&6
echo "configure:3920: checking for sys/sysconfig.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3925 "configure"
#include "confdefs.h"
#include <sys/sysconfig.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3930: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







>
>


|




|




|
|




















>




|




|




|
|







4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
#define HAVE_UNISTD_H 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

# If no stropts.h, then the svr4 implementation is broken.
# At least it is on my Debian "potato" system. - Rob Savoye
ac_safe=`echo "sys/stropts.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/stropts.h""... $ac_c" 1>&6
echo "configure:4150: checking for sys/stropts.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4155 "configure"
#include "confdefs.h"
#include <sys/stropts.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4160: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STROPTS_H 1
EOF

else
  echo "$ac_t""no" 1>&6
svr4_ptys_broken=1
fi

ac_safe=`echo "sys/sysconfig.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/sysconfig.h""... $ac_c" 1>&6
echo "configure:4187: checking for sys/sysconfig.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4192 "configure"
#include "confdefs.h"
#include <sys/sysconfig.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4197: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/fcntl.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/fcntl.h""... $ac_c" 1>&6
echo "configure:3956: checking for sys/fcntl.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3961 "configure"
#include "confdefs.h"
#include <sys/fcntl.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3966: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/fcntl.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/fcntl.h""... $ac_c" 1>&6
echo "configure:4223: checking for sys/fcntl.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4228 "configure"
#include "confdefs.h"
#include <sys/fcntl.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4233: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/select.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/select.h""... $ac_c" 1>&6
echo "configure:3992: checking for sys/select.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 3997 "configure"
#include "confdefs.h"
#include <sys/select.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/select.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/select.h""... $ac_c" 1>&6
echo "configure:4259: checking for sys/select.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4264 "configure"
#include "confdefs.h"
#include <sys/select.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4269: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/time.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/time.h""... $ac_c" 1>&6
echo "configure:4028: checking for sys/time.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4033 "configure"
#include "confdefs.h"
#include <sys/time.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4038: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/time.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/time.h""... $ac_c" 1>&6
echo "configure:4295: checking for sys/time.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4300 "configure"
#include "confdefs.h"
#include <sys/time.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4305: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/ptem.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/ptem.h""... $ac_c" 1>&6
echo "configure:4064: checking for sys/ptem.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4069 "configure"
#include "confdefs.h"
#include <sys/ptem.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4074: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/ptem.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/ptem.h""... $ac_c" 1>&6
echo "configure:4331: checking for sys/ptem.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4336 "configure"
#include "confdefs.h"
#include <sys/ptem.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4341: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/strredir.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/strredir.h""... $ac_c" 1>&6
echo "configure:4100: checking for sys/strredir.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4105 "configure"
#include "confdefs.h"
#include <sys/strredir.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4110: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/strredir.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/strredir.h""... $ac_c" 1>&6
echo "configure:4367: checking for sys/strredir.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4372 "configure"
#include "confdefs.h"
#include <sys/strredir.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/strpty.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/strpty.h""... $ac_c" 1>&6
echo "configure:4136: checking for sys/strpty.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4141 "configure"
#include "confdefs.h"
#include <sys/strpty.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|




|




|
|







4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420

else
  echo "$ac_t""no" 1>&6
fi

ac_safe=`echo "sys/strpty.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for sys/strpty.h""... $ac_c" 1>&6
echo "configure:4403: checking for sys/strpty.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4408 "configure"
#include "confdefs.h"
#include <sys/strpty.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4413: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
else
  echo "$ac_t""no" 1>&6
fi



echo $ac_n "checking for sys/bsdtypes.h""... $ac_c" 1>&6
echo "configure:4173: checking for sys/bsdtypes.h" >&5
if test "ISC_${ISC}" = "ISC_1"   ;    then
   echo "$ac_t""yes" 1>&6
   # if on ISC 1, we need <sys/bsdtypes.h> to get FD_SET macros
   for ac_hdr in sys/bsdtypes.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:4181: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4186 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4191: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|







|




|




|
|







4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
else
  echo "$ac_t""no" 1>&6
fi



echo $ac_n "checking for sys/bsdtypes.h""... $ac_c" 1>&6
echo "configure:4440: checking for sys/bsdtypes.h" >&5
if test "ISC_${ISC}" = "ISC_1"   ;    then
   echo "$ac_t""yes" 1>&6
   # if on ISC 1, we need <sys/bsdtypes.h> to get FD_SET macros
   for ac_hdr in sys/bsdtypes.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:4448: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4453 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:4458: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
   echo "$ac_t""no" 1>&6
fi

#
# Look for functions that may be missing
#
echo $ac_n "checking for memmove""... $ac_c" 1>&6
echo "configure:4225: checking for memmove" >&5
if eval "test \"`echo '$''{'ac_cv_func_memmove'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4230 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char memmove(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
   echo "$ac_t""no" 1>&6
fi

#
# Look for functions that may be missing
#
echo $ac_n "checking for memmove""... $ac_c" 1>&6
echo "configure:4492: checking for memmove" >&5
if eval "test \"`echo '$''{'ac_cv_func_memmove'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4497 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char memmove(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263

4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
choke me
#else
memmove();
#endif

; return 0; }
EOF
if { (eval echo configure:4253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_memmove=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_memmove=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'memmove`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_MEMMOVE 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for sysconf""... $ac_c" 1>&6
echo "configure:4276: checking for sysconf" >&5
if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4281 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char sysconf(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>











|




|







4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528

4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
choke me
#else
memmove();
#endif

; return 0; }
EOF
if { (eval echo configure:4520: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_memmove=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_memmove=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'memmove`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_MEMMOVE 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for sysconf""... $ac_c" 1>&6
echo "configure:4543: checking for sysconf" >&5
if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4548 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char sysconf(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314

4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
choke me
#else
sysconf();
#endif

; return 0; }
EOF
if { (eval echo configure:4304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_sysconf=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_sysconf=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'sysconf`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_SYSCONF 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for strftime""... $ac_c" 1>&6
echo "configure:4327: checking for strftime" >&5
if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4332 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strftime(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>











|




|







4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579

4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
choke me
#else
sysconf();
#endif

; return 0; }
EOF
if { (eval echo configure:4571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_sysconf=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_sysconf=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'sysconf`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_SYSCONF 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for strftime""... $ac_c" 1>&6
echo "configure:4594: checking for strftime" >&5
if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4599 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strftime(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365

4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
choke me
#else
strftime();
#endif

; return 0; }
EOF
if { (eval echo configure:4355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_strftime=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strftime=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRFTIME 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for strchr""... $ac_c" 1>&6
echo "configure:4378: checking for strchr" >&5
if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4383 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strchr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>











|




|







4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
choke me
#else
strftime();
#endif

; return 0; }
EOF
if { (eval echo configure:4622: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_strftime=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strftime=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRFTIME 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for strchr""... $ac_c" 1>&6
echo "configure:4645: checking for strchr" >&5
if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4650 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char strchr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416

4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
choke me
#else
strchr();
#endif

; return 0; }
EOF
if { (eval echo configure:4406: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_strchr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strchr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRCHR 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for timezone""... $ac_c" 1>&6
echo "configure:4429: checking for timezone" >&5
if eval "test \"`echo '$''{'ac_cv_func_timezone'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4434 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char timezone(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>











|




|







4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681

4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
choke me
#else
strchr();
#endif

; return 0; }
EOF
if { (eval echo configure:4673: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_strchr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_strchr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_STRCHR 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for timezone""... $ac_c" 1>&6
echo "configure:4696: checking for timezone" >&5
if eval "test \"`echo '$''{'ac_cv_func_timezone'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4701 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char timezone(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465

4466








4467










































4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
choke me
#else
timezone();
#endif

; return 0; }
EOF
if { (eval echo configure:4457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_timezone=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_timezone=no"
fi
rm -f conftest*










fi










































if eval "test \"`echo '$ac_cv_func_'timezone`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_TIMEZONE 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


# dnl check for memcpy by hand
# because Unixware 2.0 handles it specially and refuses to compile
# autoconf's automatic test that is a call with no arguments
echo $ac_n "checking for memcpy""... $ac_c" 1>&6
echo "configure:4484: checking for memcpy" >&5
cat > conftest.$ac_ext <<EOF
#line 4486 "configure"
#include "confdefs.h"

int main() {

char *s1, *s2;
memcpy(s1,s2,0);

; return 0; }
EOF
if { (eval echo configure:4496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define HAVE_MEMCPY 1
EOF

	
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  echo "$ac_t""no" 1>&6

fi
rm -f conftest*


# Some systems only define WNOHANG if _POSIX_SOURCE is defined
# The following merely tests that sys/wait.h can be included
# and if so that WNOHANG is not defined.  The only place I've
# seen this is ISC.
echo $ac_n "checking if WNOHANG requires _POSIX_SOURCE""... $ac_c" 1>&6
echo "configure:4519: checking if WNOHANG requires _POSIX_SOURCE" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 4525 "configure"
#include "confdefs.h"

#include <sys/wait.h>
main() {
#ifndef WNOHANG
	return 0;
#else
	return 1;
#endif
}
EOF
{ (eval echo configure:4537: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define WNOHANG_REQUIRES_POSIX_SOURCE 1
EOF


else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


echo $ac_n "checking if any value exists for WNOHANG""... $ac_c" 1>&6
echo "configure:4557: checking if any value exists for WNOHANG" >&5
rm -rf wnohang
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 4564 "configure"
#include "confdefs.h"

#include <stdio.h>
#include <sys/wait.h>
main() {
#ifdef WNOHANG
	FILE *fp = fopen("wnohang","w");
	fprintf(fp,"%d",WNOHANG);
	fclose(fp);
	return 0;
#else
	return 1;
#endif
}
EOF
{ (eval echo configure:4580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<EOF
#define WNOHANG_BACKUP_VALUE `cat wnohang`
EOF

	rm -f wnohang








|









>

>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|











|

|









|
















<





|





|











|
|


















|






|















|
|







4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829

4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
choke me
#else
timezone();
#endif

; return 0; }
EOF
if { (eval echo configure:4724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_timezone=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_timezone=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'timezone`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_TIMEZONE 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for siglongjmp""... $ac_c" 1>&6
echo "configure:4747: checking for siglongjmp" >&5
if eval "test \"`echo '$''{'ac_cv_func_siglongjmp'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4752 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char siglongjmp(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char siglongjmp();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_siglongjmp) || defined (__stub___siglongjmp)
choke me
#else
siglongjmp();
#endif

; return 0; }
EOF
if { (eval echo configure:4775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_siglongjmp=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_siglongjmp=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'siglongjmp`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_SIGLONGJMP 1
EOF

else
  echo "$ac_t""no" 1>&6
fi


# dnl check for memcpy by hand
# because Unixware 2.0 handles it specially and refuses to compile
# autoconf's automatic test that is a call with no arguments
echo $ac_n "checking for memcpy""... $ac_c" 1>&6
echo "configure:4802: checking for memcpy" >&5
cat > conftest.$ac_ext <<EOF
#line 4804 "configure"
#include "confdefs.h"

int main() {

char *s1, *s2;
memcpy(s1,s2,0);

; return 0; }
EOF
if { (eval echo configure:4814: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define HAVE_MEMCPY 1
EOF

	
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  echo "$ac_t""no" 1>&6

fi
rm -f conftest*


# Some systems only define WNOHANG if _POSIX_SOURCE is defined
# The following merely tests that sys/wait.h can be included
# and if so that WNOHANG is not defined.  The only place I've
# seen this is ISC.
echo $ac_n "checking if WNOHANG requires _POSIX_SOURCE""... $ac_c" 1>&6
echo "configure:4836: checking if WNOHANG requires _POSIX_SOURCE" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 4842 "configure"
#include "confdefs.h"

#include <sys/wait.h>
main() {
#ifndef WNOHANG
	return 0;
#else
	return 1;
#endif
}
EOF
if { (eval echo configure:4854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define WNOHANG_REQUIRES_POSIX_SOURCE 1
EOF


else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


echo $ac_n "checking if any value exists for WNOHANG""... $ac_c" 1>&6
echo "configure:4874: checking if any value exists for WNOHANG" >&5
rm -rf wnohang
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 4881 "configure"
#include "confdefs.h"

#include <stdio.h>
#include <sys/wait.h>
main() {
#ifdef WNOHANG
	FILE *fp = fopen("wnohang","w");
	fprintf(fp,"%d",WNOHANG);
	fclose(fp);
	return 0;
#else
	return 1;
#endif
}
EOF
if { (eval echo configure:4897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<EOF
#define WNOHANG_BACKUP_VALUE `cat wnohang`
EOF

	rm -f wnohang

4595
4596
4597
4598
4599
4600
4601











































4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
EOF


fi
rm -fr conftest*
fi













































#
# check how signals work
#

# Check for the data type of the mask used in select().
# This picks up HP braindamage which defines fd_set and then 
# proceeds to ignore it and use int.
# Pattern matching on int could be loosened.
# Can't use ac_header_egrep since that doesn't see prototypes with K&R cpp.
echo $ac_n "checking mask type of select""... $ac_c" 1>&6
echo "configure:4614: checking mask type of select" >&5
if egrep "select\(size_t, int" /usr/include/sys/time.h >/dev/null 2>&1; then
  echo "$ac_t""int" 1>&6
  cat >> confdefs.h <<\EOF
#define SELECT_MASK_TYPE int
EOF

else
  echo "$ac_t""none" 1>&6
fi


# FIXME: check if alarm exists
echo $ac_n "checking if signals need to be re-armed""... $ac_c" 1>&6
echo "configure:4628: checking if signals need to be re-armed" >&5
if test "$cross_compiling" = yes; then
  echo "configure: warning: Expect can't be cross compiled" 1>&2

else
  cat > conftest.$ac_ext <<EOF
#line 4634 "configure"
#include "confdefs.h"

#include <signal.h>
#define RETSIGTYPE $retsigtype

int signal_rearms = 0;








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|













|





|







4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
EOF


fi
rm -fr conftest*
fi


#-----Stolen from Tcl's configure file-------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

echo $ac_n "checking union wait""... $ac_c" 1>&6
echo "configure:4930: checking union wait" >&5
cat > conftest.$ac_ext <<EOF
#line 4932 "configure"
#include "confdefs.h"
#include <sys/types.h> 
#include <sys/wait.h>
int main() {

union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */

; return 0; }
EOF
if { (eval echo configure:4944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  tcl_ok=yes
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  tcl_ok=no
fi
rm -f conftest*
echo "$ac_t""$tcl_ok" 1>&6
if test $tcl_ok = no; then
    cat >> confdefs.h <<\EOF
#define NO_UNION_WAIT 1
EOF

fi



#
# check how signals work
#

# Check for the data type of the mask used in select().
# This picks up HP braindamage which defines fd_set and then 
# proceeds to ignore it and use int.
# Pattern matching on int could be loosened.
# Can't use ac_header_egrep since that doesn't see prototypes with K&R cpp.
echo $ac_n "checking mask type of select""... $ac_c" 1>&6
echo "configure:4974: checking mask type of select" >&5
if egrep "select\(size_t, int" /usr/include/sys/time.h >/dev/null 2>&1; then
  echo "$ac_t""int" 1>&6
  cat >> confdefs.h <<\EOF
#define SELECT_MASK_TYPE int
EOF

else
  echo "$ac_t""none" 1>&6
fi


# FIXME: check if alarm exists
echo $ac_n "checking if signals need to be re-armed""... $ac_c" 1>&6
echo "configure:4988: checking if signals need to be re-armed" >&5
if test "$cross_compiling" = yes; then
  echo "configure: warning: Expect can't be cross compiled" 1>&2

else
  cat > conftest.$ac_ext <<EOF
#line 4994 "configure"
#include "confdefs.h"

#include <signal.h>
#define RETSIGTYPE $retsigtype

int signal_rearms = 0;

4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680

		wait(&status);
		unlink("core");
		exit(signal_rearms);
	}
}
EOF
{ (eval echo configure:4673: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define REARM_SIG 1
EOF


else







|
|







5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040

		wait(&status);
		unlink("core");
		exit(signal_rearms);
	}
}
EOF
if { (eval echo configure:5033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  echo "$ac_t""yes" 1>&6
	cat >> confdefs.h <<\EOF
#define REARM_SIG 1
EOF


else
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
#

# There are multiple versions of getpty, alas.
# I don't remember who has the first one, but Convex just added one
# so check for it.  Unfortunately, there is no header so the only
# reasonable way to make sure is to look it we are on a Convex.
echo $ac_n "checking if on Convex""... $ac_c" 1>&6
echo "configure:4704: checking if on Convex" >&5
convex=0
case "${host}" in
  c[12]-*-*)		convex=1;;
esac

if test $convex -eq 1 ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define CONVEX 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

EXP_LDFLAGS=

echo $ac_n "checking if on NeXT""... $ac_c" 1>&6
echo "configure:4723: checking if on NeXT" >&5
if test -r /NextApps ; then
  echo "$ac_t""yes" 1>&6
  # "-m" flag suppresses complaints about multiple strtod
  EXP_LDFLAGS="$EXP_LDFLAGS -m"
else
  echo "$ac_t""no" 1>&6
fi


echo $ac_n "checking if on HP""... $ac_c" 1>&6
echo "configure:4734: checking if on HP" >&5
if test "x`(uname) 2>/dev/null`" = xHP-UX; then
  echo "$ac_t""yes" 1>&6
  hp=1
else
  echo "$ac_t""no" 1>&6
  hp=0
fi

echo $ac_n "checking sane default stty arguments""... $ac_c" 1>&6
echo "configure:4744: checking sane default stty arguments" >&5
DEFAULT_STTY_ARGS="sane"

if test $mach -eq 1 ; then
	DEFAULT_STTY_ARGS="cooked"
fi

if test $hp -eq 1 ; then
	DEFAULT_STTY_ARGS="sane kill "
fi

echo "$ac_t""$DEFAULT_STTY_ARG" 1>&6

# Look for various features to determine what kind of pty
# we have. For some weird reason, ac_compile_check would not
# work, but ac_test_program does.
#
echo $ac_n "checking for HP style pty allocation""... $ac_c" 1>&6
echo "configure:4762: checking for HP style pty allocation" >&5
# following test fails on DECstations and other things that don't grok -c
# but that's ok, since they don't have PTYMs anyway
if test -r /dev/ptym/ptyp0 2>/dev/null ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTYM 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for HP style pty trapping""... $ac_c" 1>&6
echo "configure:4776: checking for HP style pty trapping" >&5
cat > conftest.$ac_ext <<EOF
#line 4778 "configure"
#include "confdefs.h"
#include <sys/ptyio.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "struct.*request_info" >/dev/null 2>&1; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&6







|















|


|










|









|

















|













|

|







5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
#

# There are multiple versions of getpty, alas.
# I don't remember who has the first one, but Convex just added one
# so check for it.  Unfortunately, there is no header so the only
# reasonable way to make sure is to look it we are on a Convex.
echo $ac_n "checking if on Convex""... $ac_c" 1>&6
echo "configure:5064: checking if on Convex" >&5
convex=0
case "${host}" in
  c[12]-*-*)		convex=1;;
esac

if test $convex -eq 1 ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define CONVEX 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

EXP_LDFLAGS="$LDFLAGS"

echo $ac_n "checking if on NeXT""... $ac_c" 1>&6
echo "configure:5083: checking if on NeXT" >&5
if test -r /NextApps ; then
  echo "$ac_t""yes" 1>&6
  # "-m" flag suppresses complaints about multiple strtod
  EXP_LDFLAGS="$EXP_LDFLAGS -m"
else
  echo "$ac_t""no" 1>&6
fi


echo $ac_n "checking if on HP""... $ac_c" 1>&6
echo "configure:5094: checking if on HP" >&5
if test "x`(uname) 2>/dev/null`" = xHP-UX; then
  echo "$ac_t""yes" 1>&6
  hp=1
else
  echo "$ac_t""no" 1>&6
  hp=0
fi

echo $ac_n "checking sane default stty arguments""... $ac_c" 1>&6
echo "configure:5104: checking sane default stty arguments" >&5
DEFAULT_STTY_ARGS="sane"

if test $mach -eq 1 ; then
	DEFAULT_STTY_ARGS="cooked"
fi

if test $hp -eq 1 ; then
	DEFAULT_STTY_ARGS="sane kill "
fi

echo "$ac_t""$DEFAULT_STTY_ARG" 1>&6

# Look for various features to determine what kind of pty
# we have. For some weird reason, ac_compile_check would not
# work, but ac_test_program does.
#
echo $ac_n "checking for HP style pty allocation""... $ac_c" 1>&6
echo "configure:5122: checking for HP style pty allocation" >&5
# following test fails on DECstations and other things that don't grok -c
# but that's ok, since they don't have PTYMs anyway
if test -r /dev/ptym/ptyp0 2>/dev/null ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTYM 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for HP style pty trapping""... $ac_c" 1>&6
echo "configure:5136: checking for HP style pty trapping" >&5
cat > conftest.$ac_ext <<EOF
#line 5138 "configure"
#include "confdefs.h"
#include <sys/ptyio.h>
EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "struct.*request_info" >/dev/null 2>&1; then
  rm -rf conftest*
  echo "$ac_t""yes" 1>&6
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852








































4853
4854


















































4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
  echo "$ac_t""no" 1>&6

fi
rm -f conftest*


echo $ac_n "checking for AIX new-style pty allocation""... $ac_c" 1>&6
echo "configure:4800: checking for AIX new-style pty allocation" >&5
if test -r /dev/ptc -a -r /dev/pts ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTC_PTS 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for SGI old-style pty allocation""... $ac_c" 1>&6
echo "configure:4812: checking for SGI old-style pty allocation" >&5
if test -r /dev/ptc -a ! -r /dev/pts ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTC 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

# On SCO OpenServer, two types of ptys are available: SVR4 streams and c-list.
# The library routines to open the SVR4 ptys are broken on certain systems and
# the SCO command to increase the number of ptys only configure c-list ones
# anyway.  So we chose these, which have a special numbering scheme.
#
echo $ac_n "checking for SCO style pty allocation""... $ac_c" 1>&6
echo "configure:4829: checking for SCO style pty allocation" >&5
sco_ptys=""
case "${host}" in
  *-sco3.2v[45]*)	sco_clist_ptys=1 svr4_ptys_broken=1;;
esac

if test x"${sco_clist_ptys}" != x"" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_SCO_CLIST_PTYS 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for SVR4 style pty allocation""... $ac_c" 1>&6
echo "configure:4846: checking for SVR4 style pty allocation" >&5
if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_PTMX 1
EOF

  # aargg. Some systems need libpt.a to use /dev/ptmx








































  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:4855: checking for ptsname" >&5


















































if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4860 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|











|
















|
















|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|







5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
  echo "$ac_t""no" 1>&6

fi
rm -f conftest*


echo $ac_n "checking for AIX new-style pty allocation""... $ac_c" 1>&6
echo "configure:5160: checking for AIX new-style pty allocation" >&5
if test -r /dev/ptc -a -r /dev/pts ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTC_PTS 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for SGI old-style pty allocation""... $ac_c" 1>&6
echo "configure:5172: checking for SGI old-style pty allocation" >&5
if test -r /dev/ptc -a ! -r /dev/pts ; then
    echo "$ac_t""yes" 1>&6
    cat >> confdefs.h <<\EOF
#define HAVE_PTC 1
EOF

else
    echo "$ac_t""no" 1>&6
fi

# On SCO OpenServer, two types of ptys are available: SVR4 streams and c-list.
# The library routines to open the SVR4 ptys are broken on certain systems and
# the SCO command to increase the number of ptys only configure c-list ones
# anyway.  So we chose these, which have a special numbering scheme.
#
echo $ac_n "checking for SCO style pty allocation""... $ac_c" 1>&6
echo "configure:5189: checking for SCO style pty allocation" >&5
sco_ptys=""
case "${host}" in
  *-sco3.2v[45]*)	sco_clist_ptys=1 svr4_ptys_broken=1;;
esac

if test x"${sco_clist_ptys}" != x"" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_SCO_CLIST_PTYS 1
EOF

else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for SVR4 style pty allocation""... $ac_c" 1>&6
echo "configure:5206: checking for SVR4 style pty allocation" >&5
if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define HAVE_PTMX 1
EOF

  # aargg. Some systems need libpt.a to use /dev/ptmx
  echo $ac_n "checking for libpts="-lpt" in -lpt""... $ac_c" 1>&6
echo "configure:5215: checking for libpts="-lpt" in -lpt" >&5
ac_lib_var=`echo pt'_'libpts="-lpt" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_save_LIBS="$LIBS"
LIBS="-lpt  $LIBS"
cat > conftest.$ac_ext <<EOF
#line 5223 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char libpts="-lpt"();

int main() {
libpts="-lpt"()
; return 0; }
EOF
if { (eval echo configure:5234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_lib_$ac_lib_var=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"

fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  libpts=""
else
  echo "$ac_t""no" 1>&6
fi

  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:5255: checking for ptsname" >&5
if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5260 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char ptsname();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_ptsname) || defined (__stub___ptsname)
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:5283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*
fi

if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
LIBS="${LIBS} $libpts"
fi

  # I've never seen Tcl or Tk include -lpt so don't bother with explicit test
  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:5305: checking for ptsname" >&5
if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5310 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:4883: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
LIBS="${LIBS} -lpt"
fi

  # I've never seen Tcl or Tk include -lpt so don't bother with explicit test
  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:4905: checking for ptsname" >&5
if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4910 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
char ptsname();

int main() {

/* The GNU C library defines this for functions which it implements
    to always fail with ENOSYS.  Some functions are actually named
    something starting with __ and the normal name is an alias.  */
#if defined (__stub_ptsname) || defined (__stub___ptsname)
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:4933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*

fi
if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
EXP_AND_TCL_LIBS="${EXP_AND_TCL_LIBS} -lpt"
fi

  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:4954: checking for ptsname" >&5
if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 4959 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|



|




|







5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341

5342


5343















































5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:5333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*

fi


















































if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
EXP_AND_TCL_LIBS="${EXP_AND_TCL_LIBS} $libpts"
fi

  echo $ac_n "checking for ptsname""... $ac_c" 1>&6
echo "configure:5354: checking for ptsname" >&5
if eval "test \"`echo '$''{'ac_cv_func_ptsname'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5359 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char ptsname(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992

4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:4982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
EXP_AND_TK_LIBS="${EXP_AND_TK_LIBS} -lpt"
fi

else
  echo "$ac_t""no" 1>&6
fi

# In OSF/1 case, SVR4 are somewhat different.
# Gregory Depp <[email protected]> 17Aug93
echo $ac_n "checking for OSF/1 style pty allocation""... $ac_c" 1>&6
echo "configure:5009: checking for OSF/1 style pty allocation" >&5
if test -r /dev/ptmx_bsd ; then
    cat >> confdefs.h <<\EOF
#define HAVE_PTMX_BSD 1
EOF

    echo "$ac_t""yes" 1>&6
else
    echo "$ac_t""no" 1>&6
fi

tcgetattr=0
tcsetattr=0
echo $ac_n "checking for tcgetattr""... $ac_c" 1>&6
echo "configure:5023: checking for tcgetattr" >&5
if eval "test \"`echo '$''{'ac_cv_func_tcgetattr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5028 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char tcgetattr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>





|









|













|




|







5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390

5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
choke me
#else
ptsname();
#endif

; return 0; }
EOF
if { (eval echo configure:5382: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_ptsname=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_ptsname=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'ptsname`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  :
else
  echo "$ac_t""no" 1>&6
EXP_AND_TK_LIBS="${EXP_AND_TK_LIBS} $libpts"
fi

else
  echo "$ac_t""no" 1>&6
fi

# In OSF/1 case, SVR4 are somewhat different.
# Gregory Depp <[email protected]> 17Aug93
echo $ac_n "checking for OSF/1 style pty allocation""... $ac_c" 1>&6
echo "configure:5409: checking for OSF/1 style pty allocation" >&5
if test -r /dev/ptmx_bsd ; then
    cat >> confdefs.h <<\EOF
#define HAVE_PTMX_BSD 1
EOF

    echo "$ac_t""yes" 1>&6
else
    echo "$ac_t""no" 1>&6
fi

tcgetattr=0
tcsetattr=0
echo $ac_n "checking for tcgetattr""... $ac_c" 1>&6
echo "configure:5423: checking for tcgetattr" >&5
if eval "test \"`echo '$''{'ac_cv_func_tcgetattr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5428 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char tcgetattr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061

5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
choke me
#else
tcgetattr();
#endif

; return 0; }
EOF
if { (eval echo configure:5051: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_tcgetattr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_tcgetattr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'tcgetattr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  tcgetattr=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for tcsetattr""... $ac_c" 1>&6
echo "configure:5071: checking for tcsetattr" >&5
if eval "test \"`echo '$''{'ac_cv_func_tcsetattr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5076 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char tcsetattr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>








|




|







5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459

5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
choke me
#else
tcgetattr();
#endif

; return 0; }
EOF
if { (eval echo configure:5451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_tcgetattr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_tcgetattr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'tcgetattr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  tcgetattr=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for tcsetattr""... $ac_c" 1>&6
echo "configure:5471: checking for tcsetattr" >&5
if eval "test \"`echo '$''{'ac_cv_func_tcsetattr'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5476 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char tcsetattr(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109

5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
choke me
#else
tcsetattr();
#endif

; return 0; }
EOF
if { (eval echo configure:5099: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_tcsetattr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_tcsetattr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'tcsetattr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  tcsetattr=1
else
  echo "$ac_t""no" 1>&6
fi

if test $tcgetattr -eq 1 -a $tcsetattr -eq 1 ; then
    cat >> confdefs.h <<\EOF
#define HAVE_TCSETATTR 1
EOF

    cat >> confdefs.h <<\EOF
#define POSIX 1
EOF

fi

# first check for the pure bsd
echo $ac_n "checking for struct sgttyb""... $ac_c" 1>&6
echo "configure:5131: checking for struct sgttyb" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5137 "configure"
#include "confdefs.h"

#include <sgtty.h>
main()
{
  struct sgttyb tmp;
  exit(0);
}
EOF
{ (eval echo configure:5147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  echo "$ac_t""yes" 1>&6
        cat >> confdefs.h <<\EOF
#define HAVE_SGTTYB 1
EOF

        PTY_TYPE=sgttyb








|









<

>




















|





|









|
|







5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507

5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
choke me
#else
tcsetattr();
#endif

; return 0; }
EOF
if { (eval echo configure:5499: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_tcsetattr=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_tcsetattr=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'tcsetattr`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  tcsetattr=1
else
  echo "$ac_t""no" 1>&6
fi

if test $tcgetattr -eq 1 -a $tcsetattr -eq 1 ; then
    cat >> confdefs.h <<\EOF
#define HAVE_TCSETATTR 1
EOF

    cat >> confdefs.h <<\EOF
#define POSIX 1
EOF

fi

# first check for the pure bsd
echo $ac_n "checking for struct sgttyb""... $ac_c" 1>&6
echo "configure:5531: checking for struct sgttyb" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5537 "configure"
#include "confdefs.h"

#include <sgtty.h>
main()
{
  struct sgttyb tmp;
  exit(0);
}
EOF
if { (eval echo configure:5547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  echo "$ac_t""yes" 1>&6
        cat >> confdefs.h <<\EOF
#define HAVE_SGTTYB 1
EOF

        PTY_TYPE=sgttyb

5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
if test $mach -eq 0 ; then

  # next check for the older style ttys
  # note that if we detect termio.h (only), we still set PTY_TYPE=termios
  # since that just controls which of pty_XXXX.c file is use and
  # pty_termios.c is set up to handle pty_termio.
  echo $ac_n "checking for struct termio""... $ac_c" 1>&6
echo "configure:5176: checking for struct termio" >&5
  if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5182 "configure"
#include "confdefs.h"
#include <termio.h>
  main()
  {
    struct termio tmp;
    exit(0);
  }
EOF
{ (eval echo configure:5191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  cat >> confdefs.h <<\EOF
#define HAVE_TERMIO 1
EOF

        PTY_TYPE=termios
        echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


  # now check for the new style ttys (not yet posix)
  echo $ac_n "checking for struct termios""... $ac_c" 1>&6
echo "configure:5213: checking for struct termios" >&5
  if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }
  
else
  cat > conftest.$ac_ext <<EOF
#line 5219 "configure"
#include "confdefs.h"

  /* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#  ifdef HAVE_INTTYPES_H
#  include <inttypes.h>
#  endif
#  include <termios.h>
  main()
  {
    struct termios tmp;
    exit(0);
  }
EOF
{ (eval echo configure:5233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  cat >> confdefs.h <<\EOF
#define HAVE_TERMIOS 1
EOF

        PTY_TYPE=termios
        echo "$ac_t""yes" 1>&6
  
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6
  
fi
rm -fr conftest*
fi

fi

echo $ac_n "checking if TCGETS or TCGETA in termios.h""... $ac_c" 1>&6
echo "configure:5255: checking if TCGETS or TCGETA in termios.h" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5261 "configure"
#include "confdefs.h"

/* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <termios.h>
main() {
#if defined(TCGETS) || defined(TCGETA)
	return 0;
#else
	return 1;
#endif
}
EOF
{ (eval echo configure:5277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  cat >> confdefs.h <<\EOF
#define HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H 1
EOF

	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


echo $ac_n "checking if TIOCGWINSZ in termios.h""... $ac_c" 1>&6
echo "configure:5297: checking if TIOCGWINSZ in termios.h" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5303 "configure"
#include "confdefs.h"

/* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <termios.h>
main() {
#ifdef TIOCGWINSZ
	return 0;
#else
	return 1;
#endif
}
EOF
{ (eval echo configure:5319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  cat >> confdefs.h <<\EOF
#define HAVE_TIOCGWINSZ_IN_TERMIOS_H 1
EOF

	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


# finally check for Cray style ttys
echo $ac_n "checking for Cray-style ptys""... $ac_c" 1>&6
echo "configure:5340: checking for Cray-style ptys" >&5
SETUID=":"
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5347 "configure"
#include "confdefs.h"

main(){
#ifdef CRAY
	return 0;
#else
	return 1;
#endif
}

EOF
{ (eval echo configure:5359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  PTY_TYPE=unicos
	SETUID="chmod u+s"
	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







|





|








|
|




















|





|













|
|




















|





|















|
|


















|





|















|
|



















|






|











|
|







5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
if test $mach -eq 0 ; then

  # next check for the older style ttys
  # note that if we detect termio.h (only), we still set PTY_TYPE=termios
  # since that just controls which of pty_XXXX.c file is use and
  # pty_termios.c is set up to handle pty_termio.
  echo $ac_n "checking for struct termio""... $ac_c" 1>&6
echo "configure:5576: checking for struct termio" >&5
  if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5582 "configure"
#include "confdefs.h"
#include <termio.h>
  main()
  {
    struct termio tmp;
    exit(0);
  }
EOF
if { (eval echo configure:5591: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  cat >> confdefs.h <<\EOF
#define HAVE_TERMIO 1
EOF

        PTY_TYPE=termios
        echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


  # now check for the new style ttys (not yet posix)
  echo $ac_n "checking for struct termios""... $ac_c" 1>&6
echo "configure:5613: checking for struct termios" >&5
  if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }
  
else
  cat > conftest.$ac_ext <<EOF
#line 5619 "configure"
#include "confdefs.h"

  /* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#  ifdef HAVE_INTTYPES_H
#  include <inttypes.h>
#  endif
#  include <termios.h>
  main()
  {
    struct termios tmp;
    exit(0);
  }
EOF
if { (eval echo configure:5633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  cat >> confdefs.h <<\EOF
#define HAVE_TERMIOS 1
EOF

        PTY_TYPE=termios
        echo "$ac_t""yes" 1>&6
  
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6
  
fi
rm -fr conftest*
fi

fi

echo $ac_n "checking if TCGETS or TCGETA in termios.h""... $ac_c" 1>&6
echo "configure:5655: checking if TCGETS or TCGETA in termios.h" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5661 "configure"
#include "confdefs.h"

/* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <termios.h>
main() {
#if defined(TCGETS) || defined(TCGETA)
	return 0;
#else
	return 1;
#endif
}
EOF
if { (eval echo configure:5677: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  cat >> confdefs.h <<\EOF
#define HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H 1
EOF

	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


echo $ac_n "checking if TIOCGWINSZ in termios.h""... $ac_c" 1>&6
echo "configure:5697: checking if TIOCGWINSZ in termios.h" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5703 "configure"
#include "confdefs.h"

/* including termios.h on Solaris 5.6 fails unless inttypes.h included */
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <termios.h>
main() {
#ifdef TIOCGWINSZ
	return 0;
#else
	return 1;
#endif
}
EOF
if { (eval echo configure:5719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  cat >> confdefs.h <<\EOF
#define HAVE_TIOCGWINSZ_IN_TERMIOS_H 1
EOF

	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  echo "$ac_t""no" 1>&6

fi
rm -fr conftest*
fi


# finally check for Cray style ttys
echo $ac_n "checking for Cray-style ptys""... $ac_c" 1>&6
echo "configure:5740: checking for Cray-style ptys" >&5
SETUID=":"
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5747 "configure"
#include "confdefs.h"

main(){
#ifdef CRAY
	return 0;
#else
	return 1;
#endif
}

EOF
if { (eval echo configure:5759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  PTY_TYPE=unicos
	SETUID="chmod u+s"
	echo "$ac_t""yes" 1>&6

else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
# Check for select and/or poll. If both exist, we prefer select.
# if neither exists, define SIMPLE_EVENT.
#
select=0
poll=0
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:5384: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5389 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
# Check for select and/or poll. If both exist, we prefer select.
# if neither exists, define SIMPLE_EVENT.
#
select=0
poll=0
unset ac_cv_func_select
echo $ac_n "checking for select""... $ac_c" 1>&6
echo "configure:5784: checking for select" >&5
if eval "test \"`echo '$''{'ac_cv_func_select'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5789 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char select(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422

5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:5412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for poll""... $ac_c" 1>&6
echo "configure:5432: checking for poll" >&5
if eval "test \"`echo '$''{'ac_cv_func_poll'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5437 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char poll(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>








|




|







5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820

5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
choke me
#else
select();
#endif

; return 0; }
EOF
if { (eval echo configure:5812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_select=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_select=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'select`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  select=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking for poll""... $ac_c" 1>&6
echo "configure:5832: checking for poll" >&5
if eval "test \"`echo '$''{'ac_cv_func_poll'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5837 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char poll(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470

5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
choke me
#else
poll();
#endif

; return 0; }
EOF
if { (eval echo configure:5460: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_poll=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_poll=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'poll`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  poll=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking event handling""... $ac_c" 1>&6
echo "configure:5480: checking event handling" >&5
if test $select -eq 1 ; then
  EVENT_TYPE=select
  EVENT_ABLE=event
  echo "$ac_t""via select" 1>&6
elif test $poll -eq 1 ; then
  EVENT_TYPE=poll
  EVENT_ABLE=event







|









<

>








|







5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868

5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
choke me
#else
poll();
#endif

; return 0; }
EOF
if { (eval echo configure:5860: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_poll=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_poll=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'poll`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  poll=1
else
  echo "$ac_t""no" 1>&6
fi

echo $ac_n "checking event handling""... $ac_c" 1>&6
echo "configure:5880: checking event handling" >&5
if test $select -eq 1 ; then
  EVENT_TYPE=select
  EVENT_ABLE=event
  echo "$ac_t""via select" 1>&6
elif test $poll -eq 1 ; then
  EVENT_TYPE=poll
  EVENT_ABLE=event
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
EOF

fi

for ac_func in _getpty
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5502: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5507 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|




|







5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
EOF

fi

for ac_func in _getpty
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5902: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5907 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540

5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
choke me
#else
$ac_func();
#endif

; return 0; }
EOF
if { (eval echo configure:5530: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
 
else
  echo "$ac_t""no" 1>&6
fi
done

for ac_func in getpty
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5557: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5562 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */







|









<

>















|




|







5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938

5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
choke me
#else
$ac_func();
#endif

; return 0; }
EOF
if { (eval echo configure:5930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
 
else
  echo "$ac_t""no" 1>&6
fi
done

for ac_func in getpty
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5957: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5962 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
    which can conflict with char $ac_func(); below.  */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error.  */
/* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595

5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608












5609










































5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
choke me
#else
$ac_func();
#endif

; return 0; }
EOF
if { (eval echo configure:5585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
 
else
  echo "$ac_t""no" 1>&6
fi
done














#










































# check for timezones
#
echo $ac_n "checking for SV-style timezone""... $ac_c" 1>&6
echo "configure:5614: checking for SV-style timezone" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 5620 "configure"
#include "confdefs.h"

extern char *tzname[2];
extern int daylight;
main()
{
  int *x = &daylight;
  char **y = tzname;

  exit(0);
}
EOF
{ (eval echo configure:5633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
  cat >> confdefs.h <<\EOF
#define HAVE_SV_TIMEZONE 1
EOF

	echo "$ac_t""yes" 1>&6
else
  echo "configure: failed program was:" >&5







|









<

>













>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|





|












|
|







5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993

5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
choke me
#else
$ac_func();
#endif

; return 0; }
EOF
if { (eval echo configure:5985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=yes"
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -rf conftest*
  eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*

fi

if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
  echo "$ac_t""yes" 1>&6
    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
  cat >> confdefs.h <<EOF
#define $ac_tr_func 1
EOF
 
else
  echo "$ac_t""no" 1>&6
fi
done


# following test sets SETPGRP_VOID if setpgrp takes 0 args, else takes 2
echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6
echo "configure:6012: checking whether setpgrp takes no argument" >&5
if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test "$cross_compiling" = yes; then
  { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; }
else
  cat > conftest.$ac_ext <<EOF
#line 6020 "configure"
#include "confdefs.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

/*
 * If this system has a BSD-style setpgrp, which takes arguments, exit
 * successfully.
 */
main()
{
    if (setpgrp(1,1) == -1)
	exit(0);
    else
	exit(1);
}

EOF
if { (eval echo configure:6040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  ac_cv_func_setpgrp_void=no
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  rm -fr conftest*
  ac_cv_func_setpgrp_void=yes
fi
rm -fr conftest*
fi


fi

echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6
if test $ac_cv_func_setpgrp_void = yes; then
  cat >> confdefs.h <<\EOF
#define SETPGRP_VOID 1
EOF

fi


#
# check for timezones
#
echo $ac_n "checking for SV-style timezone""... $ac_c" 1>&6
echo "configure:6068: checking for SV-style timezone" >&5
if test "$cross_compiling" = yes; then
  { echo "configure: error: Expect can't be cross compiled" 1>&2; exit 1; }

else
  cat > conftest.$ac_ext <<EOF
#line 6074 "configure"
#include "confdefs.h"

extern char *tzname[2];
extern int daylight;
main()
{
  int *x = &daylight;
  char **y = tzname;

  exit(0);
}
EOF
if { (eval echo configure:6087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
  cat >> confdefs.h <<\EOF
#define HAVE_SV_TIMEZONE 1
EOF

	echo "$ac_t""yes" 1>&6
else
  echo "configure: failed program was:" >&5
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
# recursive cache variables for the path will work right. We check all
# the possible paths in one loop rather than many seperate loops to speed
# things up.
# the alternative search directory is involked by --with-tkinclude
#
#no_tk=true
echo $ac_n "checking for Tk private headers""... $ac_c" 1>&6
echo "configure:5679: checking for Tk private headers" >&5
# Check whether --with-tkinclude or --without-tkinclude was given.
if test "${with_tkinclude+set}" = set; then
  withval="$with_tkinclude"
  with_tkinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tkh'+set}'`\" = set"; then







|







6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
# recursive cache variables for the path will work right. We check all
# the possible paths in one loop rather than many seperate loops to speed
# things up.
# the alternative search directory is involked by --with-tkinclude
#
#no_tk=true
echo $ac_n "checking for Tk private headers""... $ac_c" 1>&6
echo "configure:6133: checking for Tk private headers" >&5
# Check whether --with-tkinclude or --without-tkinclude was given.
if test "${with_tkinclude+set}" = set; then
  withval="$with_tkinclude"
  with_tkinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tkh'+set}'`\" = set"; then
5707
5708
5709
5710
5711
5712
5713

5714
5715

5716

5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729


5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` \

		${srcdir}/../../tk \
		`ls -dr ${srcdir}/../../tk[4-9].[0-9].[0-9] ${srcdir}/../../tk[4-9].[0-9] 2>/dev/null` \

		${srcdir}/../../../tk \

		`ls -dr ${srcdir}/../../../tk[4-9].[0-9].[0-9] ${srcdir}/../../../tk[4-9].[0-9] 2>/dev/null ` ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tk[4-9].[0-9].[0-9] /usr/local/src/tk[4-9].[0-9] 2>/dev/null` \


		`ls -dr /usr/local/lib/tk[4-9].[0-9].[0-9] /usr/local/lib/tk[4-9].[0-9] 2>/dev/null` \
		/usr/local/src/tk \
		/usr/local/lib/tk \
		${prefix}/include ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tkh}" = x ; then
   ac_safe=`echo "tk.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tk.h""... $ac_c" 1>&6
echo "configure:5745: checking for tk.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 5750 "configure"
#include "confdefs.h"
#include <tk.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:5755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5







>


>

>













>
>














|




|




|
|







6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		${srcdir}/../tk \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../tk[4-9].[0-9].[0-9] ${srcdir}/../tk[4-9].[0-9] 2>/dev/null` \
		${srcdir}/../../tk \
		`ls -dr ${srcdir}/../../tk[4-9].[0-9].[0-9] ${srcdir}/../../tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr ${srcdir}/../../tk[4-9].[0-9].[0-9] ${srcdir}/../../tk[4-9].[0-9] 2>/dev/null` \
		${srcdir}/../../../tk \
		`ls -dr ${srcdir}/../../../tk[4-9].[0-9].[0-9] ${srcdir}/../../../tk[4-9].[0-9] 2>/dev/null ` \
		`ls -dr ${srcdir}/../../../tk[4-9].[0-9].[0-9] ${srcdir}/../../../tk[4-9].[0-9] 2>/dev/null ` ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tk[4-9].[0-9].[0-9] /usr/local/src/tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr /usr/local/src/tk[4-9].[0-9].[0-9] /usr/local/src/tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr /usr/local/lib/tk[4-9].[0-9].[0-9] /usr/local/lib/tk[4-9].[0-9] 2>/dev/null` \
		`ls -dr /usr/local/lib/tk[4-9].[0-9].[0-9] /usr/local/lib/tk[4-9].[0-9] 2>/dev/null` \
		/usr/local/src/tk \
		/usr/local/lib/tk \
		${prefix}/include ; do
    if test -f $i/generic/tk.h ; then
      ac_cv_c_tkh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tkh}" = x ; then
   ac_safe=`echo "tk.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for tk.h""... $ac_c" 1>&6
echo "configure:6204: checking for tk.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 6209 "configure"
#include "confdefs.h"
#include <tk.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:6214: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
if test $iunix -eq 1 ; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

# also remove dots on systems that don't support filenames > 14
# (are there systems which support shared libs and restrict filename lengths!?)
echo $ac_n "checking for long file names""... $ac_c" 1>&6
echo "configure:5854: checking for long file names" >&5
if eval "test \"`echo '$''{'ac_cv_sys_long_file_names'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_cv_sys_long_file_names=yes
# Test for long file names in all the places we know might matter:
#      .		the current directory, where building will happen
#      $prefix/lib	where we will be installing things







|







6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
if test $iunix -eq 1 ; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

# also remove dots on systems that don't support filenames > 14
# (are there systems which support shared libs and restrict filename lengths!?)
echo $ac_n "checking for long file names""... $ac_c" 1>&6
echo "configure:6313: checking for long file names" >&5
if eval "test \"`echo '$''{'ac_cv_sys_long_file_names'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  ac_cv_sys_long_file_names=yes
# Test for long file names in all the places we know might matter:
#      .		the current directory, where building will happen
#      $prefix/lib	where we will be installing things
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903





5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939

fi

if test $ac_cv_sys_long_file_names = no; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

EXP_BUILD_LIB_SPEC="-L`pwd` -lexpect${EXP_LIB_VERSION}"
EXP_LIB_SPEC="-L\${exec_prefix}/lib -lexpect${EXP_LIB_VERSION}"
EXP_UNSHARED_LIB_FILE=libexpect${EXP_LIB_VERSION}.a






echo $ac_n "checking for type of library to build""... $ac_c" 1>&6
echo "configure:5906: checking for type of library to build" >&5
if test "$enable_shared" = "yes" && test "x${TCL_SHLIB_SUFFIX}" != "x" ; then
  EXP_SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
#  EXP_SHARED_LIB_FILE=libexpect$EXP_LIB_VERSION$TCL_SHLIB_SUFFIX
  eval "EXP_SHARED_LIB_FILE=libexpect${TCL_SHARED_LIB_SUFFIX}"
  EXP_LIB_FILE=$EXP_SHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_SHARED_LIB_FILE $EXP_UNSHARED_LIB_FILE"
  echo "$ac_t""both shared and unshared" 1>&6
else
  EXP_SHLIB_CFLAGS=
  EXP_SHARED_LIB_FILE="reconfigure_Tcl_for_shared_library"
  EXP_LIB_FILE=$EXP_UNSHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_UNSHARED_LIB_FILE"
  echo "$ac_t""unshared" 1>&6
fi

# now broken out into EXP_AND_TCL_LIBS and EXP_AND_TK_LIBS.  Had to do this
# in order to avoid repeating lib specs to which some systems object.
EXP_AND_TCL_LIBS="$EXP_AND_TCL_LIBS $TCL_LD_SEARCH_FLAGS"
EXP_AND_TK_LIBS="$EXP_AND_TK_LIBS $TCL_LD_SEARCH_FLAGS"

# Sigh - Tcl defines SHLIB_LD_LIBS to be either empty or ${LIBS} and
# LIBS is intended to be expanded by Make.  But since we're too close
# to hitting config's max symbols, pack everything together here and
# do test ourselves.  Ugh.  
#
if test "x$TCL_SHLIB_LD_LIBS" = "x" ; then
	EXP_SHLIB_LD_LIBS=""
else
	# seems a little strange to build in Tcl's build-lib, but
	# that's what Tk does.
	EXP_SHLIB_LD_LIBS="$TCL_BUILD_LIB_SPEC $TCL_DL_LIBS $LIBS -lc"
fi

#--------------------------------------------------------------------







|
|
|

>
>
>
>
>

|


<












<
<
<
<
<






|







6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371

6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383





6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397

fi

if test $ac_cv_sys_long_file_names = no; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

EXP_BUILD_LIB_SPEC="-L`pwd` -lexpect${EXP_LIB_VERSION}${DBGX}"
EXP_LIB_SPEC="-L\${INSTALL_ROOT}\${exec_prefix}/lib -lexpect${EXP_LIB_VERSION}${DBGX}"
EXP_UNSHARED_LIB_FILE=libexpect${EXP_LIB_VERSION}${DBGX}.a

# The TCL_SHARED_LIB_SUFFIX macro below relies on the DBGX macro,
# which is set way far above here.  Don't set it to the value of
# TCL_DBGX, or you'll run into problems if you build Tcl with symbols
# and expect without (and vice versa?)

echo $ac_n "checking for type of library to build""... $ac_c" 1>&6
echo "configure:6370: checking for type of library to build" >&5
if test "$enable_shared" = "yes" && test "x${TCL_SHLIB_SUFFIX}" != "x" ; then
  EXP_SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS

  eval "EXP_SHARED_LIB_FILE=libexpect${TCL_SHARED_LIB_SUFFIX}"
  EXP_LIB_FILE=$EXP_SHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_SHARED_LIB_FILE $EXP_UNSHARED_LIB_FILE"
  echo "$ac_t""both shared and unshared" 1>&6
else
  EXP_SHLIB_CFLAGS=
  EXP_SHARED_LIB_FILE="reconfigure_Tcl_for_shared_library"
  EXP_LIB_FILE=$EXP_UNSHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_UNSHARED_LIB_FILE"
  echo "$ac_t""unshared" 1>&6
fi






# Sigh - Tcl defines SHLIB_LD_LIBS to be either empty or ${LIBS} and
# LIBS is intended to be expanded by Make.  But since we're too close
# to hitting config's max symbols, pack everything together here and
# do test ourselves.  Ugh.  
#
if test "x$TCL_SHLIB_LD_LIBS" = "x" ; then
	EXP_SHLIB_LD_LIBS="$LIBS"
else
	# seems a little strange to build in Tcl's build-lib, but
	# that's what Tk does.
	EXP_SHLIB_LD_LIBS="$TCL_BUILD_LIB_SPEC $TCL_DL_LIBS $LIBS -lc"
fi

#--------------------------------------------------------------------
5950
5951
5952
5953
5954
5955
5956

5957
5958







5959
5960
5961
5962
5963
5964
5965
5966
5967
5968

5969



5970






5971
5972
5973
5974

5975
5976
5977
5978
5979
5980
5981
#--------------------------------------------------------------------

LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}'

# If Tcl and Expect are installed in different places, adjust the library
# search path to reflect this.


if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}"







fi

if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

# The statement below is very tricky!  It actually *evaluates* the
# string in TCL_LD_SEARCH_FLAGS, which causes a substitution of the
# variable LIB_RUNTIME_DIR.


eval "EXP_CC_SEARCH_FLAGS=\"$TCL_LD_SEARCH_FLAGS\""



EXP_LD_SEARCH_FLAGS=`echo ${EXP_CC_SEARCH_FLAGS} |sed -e "s|-Wl,||g" -e "s|,| |g"`







#
# Set up makefile substitutions
#















>
|
|
>
>
>
>
>
>
>






|
|


>
|
>
>
>
|
>
>
>
>
>
>




>







6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
#--------------------------------------------------------------------

LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}'

# If Tcl and Expect are installed in different places, adjust the library
# search path to reflect this.

if test x"$no_tk" = x"true" ; then
  if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib"
  fi
else
  if test "$TK_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TK_EXEC_PREFIX}/lib"
    # no need to include TCL's search path, because TK does it already
    # (it is actually appended later, via TK_LD_SEARCH_FLAGS trick below)
  fi
fi

if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

# The eval below is tricky!  It *evaluates* the string in
# ..._CC_SEARCH_FLAGS, which causes a substitution of the
# variable LIB_RUNTIME_DIR.

if test x"$no_tk" = x"true" ; then
  eval "EXP_CC_SEARCH_FLAGS=\"$TCL_CC_SEARCH_FLAGS\""
  EXP_LD_SEARCH_FLAGS=${TCL_LD_SEARCH_FLAGS}
else
  eval "EXP_CC_SEARCH_FLAGS=\"$TK_CC_SEARCH_FLAGS\""
  EXP_LD_SEARCH_FLAGS=${TK_LD_SEARCH_FLAGS}
fi

# now broken out into EXP_AND_TCL_LIBS and EXP_AND_TK_LIBS.  Had to do this
# in order to avoid repeating lib specs to which some systems object.
EXP_AND_TCL_LIBS="$EXP_AND_TCL_LIBS $EXP_CC_SEARCH_FLAGS"
EXP_AND_TK_LIBS="$EXP_AND_TK_LIBS $EXP_CC_SEARCH_FLAGS"

#
# Set up makefile substitutions
#








6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056

6057
6058
6059
6060
6061
6062
6063
6064
6065

6066
6067
6068

6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086

6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101

6102
6103
6104

6105
6106
6107
6108
6109
6110
6111
6112

6113
6114
6115
6116
6117
6118

6119
6120
6121
6122
6123
6124
6125
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.11"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"


trap 'rm -fr `echo "Makefile pkgIndex expect_cf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF

# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
 s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub

s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g

s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g

s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@target@%$target%g
s%@target_alias@%$target_alias%g
s%@target_cpu@%$target_cpu%g
s%@target_vendor@%$target_vendor%g
s%@target_os@%$target_os%g
s%@build@%$build%g
s%@build_alias@%$build_alias%g
s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g

s%@TCL_DEFS@%$TCL_DEFS%g
s%@TCL_DELETEME@%$TCL_DELETEME%g
s%@TCL_DBGX@%$TCL_DBGX%g

s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g
s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
s%@TCL_LD_FLAGS@%$TCL_LD_FLAGS%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
s%@TCL_SHARED_LIB_SUFFIX@%$TCL_SHARED_LIB_SUFFIX%g
s%@TK_VERSION@%$TK_VERSION%g
s%@TK_DEFS@%$TK_DEFS%g

s%@TK_XINCLUDES@%$TK_XINCLUDES%g
s%@TK_XLIBSW@%$TK_XLIBSW%g
s%@TK_BUILD_LIB_SPEC@%$TK_BUILD_LIB_SPEC%g
s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g
s%@CC@%$CC%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g

s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@RANLIB@%$RANLIB%g
s%@subdirs@%$subdirs%g
s%@CPP@%$CPP%g
s%@TCLHDIR@%$TCLHDIR%g
s%@TCLHDIRDASHI@%$TCLHDIRDASHI%g
s%@TCL_LIBRARY@%$TCL_LIBRARY%g







|










>
|








>



>


















>















>



>








>




<

>







6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600

6601
6602
6603
6604
6605
6606
6607
6608
6609
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.13"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"

trap 'rm -fr `echo "Makefile \
	pkgIndex expect_cf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF

# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
 s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@found@%$found%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
s%@host_vendor@%$host_vendor%g
s%@host_os@%$host_os%g
s%@target@%$target%g
s%@target_alias@%$target_alias%g
s%@target_cpu@%$target_cpu%g
s%@target_vendor@%$target_vendor%g
s%@target_os@%$target_os%g
s%@build@%$build%g
s%@build_alias@%$build_alias%g
s%@build_cpu@%$build_cpu%g
s%@build_vendor@%$build_vendor%g
s%@build_os@%$build_os%g
s%@CC@%$CC%g
s%@TCL_DEFS@%$TCL_DEFS%g
s%@TCL_DELETEME@%$TCL_DELETEME%g
s%@TCL_DBGX@%$TCL_DBGX%g
s%@TCL_EXEC_PREFIX@%$TCL_EXEC_PREFIX%g
s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g
s%@SHLIB_SUFFIX@%$SHLIB_SUFFIX%g
s%@TCL_LD_FLAGS@%$TCL_LD_FLAGS%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
s%@TCL_SHARED_LIB_SUFFIX@%$TCL_SHARED_LIB_SUFFIX%g
s%@TK_VERSION@%$TK_VERSION%g
s%@TK_DEFS@%$TK_DEFS%g
s%@TK_DBGX@%$TK_DBGX%g
s%@TK_XINCLUDES@%$TK_XINCLUDES%g
s%@TK_XLIBSW@%$TK_XLIBSW%g
s%@TK_BUILD_LIB_SPEC@%$TK_BUILD_LIB_SPEC%g
s%@TK_LIB_SPEC@%$TK_LIB_SPEC%g

s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@RANLIB@%$RANLIB%g
s%@subdirs@%$subdirs%g
s%@CPP@%$CPP%g
s%@TCLHDIR@%$TCLHDIR%g
s%@TCLHDIRDASHI@%$TCLHDIRDASHI%g
s%@TCL_LIBRARY@%$TCL_LIBRARY%g
6136
6137
6138
6139
6140
6141
6142

6143
6144
6145
6146
6147
6148
6149
s%@EXP_LIB_FILE@%$EXP_LIB_FILE%g
s%@EXP_LIB_FILES@%$EXP_LIB_FILES%g
s%@EXP_BUILD_LIB_SPEC@%$EXP_BUILD_LIB_SPEC%g
s%@EXP_LIB_SPEC@%$EXP_LIB_SPEC%g
s%@EXP_CFLAGS@%$EXP_CFLAGS%g
s%@EXP_LDFLAGS@%$EXP_LDFLAGS%g
s%@EXP_LD_SEARCH_FLAGS@%$EXP_LD_SEARCH_FLAGS%g

s%@EXP_AND_TCL_LIBS@%$EXP_AND_TCL_LIBS%g
s%@EXP_AND_TK_LIBS@%$EXP_AND_TK_LIBS%g
s%@EXP_SHLIB_LD_LIBS@%$EXP_SHLIB_LD_LIBS%g
s%@X_PROGS@%$X_PROGS%g
s%@PTY_TYPE@%$PTY_TYPE%g
s%@EVENT_TYPE@%$EVENT_TYPE%g
s%@EVENT_ABLE@%$EVENT_ABLE%g







>







6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
s%@EXP_LIB_FILE@%$EXP_LIB_FILE%g
s%@EXP_LIB_FILES@%$EXP_LIB_FILES%g
s%@EXP_BUILD_LIB_SPEC@%$EXP_BUILD_LIB_SPEC%g
s%@EXP_LIB_SPEC@%$EXP_LIB_SPEC%g
s%@EXP_CFLAGS@%$EXP_CFLAGS%g
s%@EXP_LDFLAGS@%$EXP_LDFLAGS%g
s%@EXP_LD_SEARCH_FLAGS@%$EXP_LD_SEARCH_FLAGS%g
s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g
s%@EXP_AND_TCL_LIBS@%$EXP_AND_TCL_LIBS%g
s%@EXP_AND_TK_LIBS@%$EXP_AND_TK_LIBS%g
s%@EXP_SHLIB_LD_LIBS@%$EXP_SHLIB_LD_LIBS%g
s%@X_PROGS@%$X_PROGS%g
s%@PTY_TYPE@%$PTY_TYPE%g
s%@EVENT_TYPE@%$EVENT_TYPE%g
s%@EVENT_ABLE@%$EVENT_ABLE%g
6187
6188
6189
6190
6191
6192
6193
6194

6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
fi
EOF

cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile pkgIndex"}

EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.







|
>



|

|







6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
fi
EOF

cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile \
	pkgIndex"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
6235
6236
6237
6238
6239
6240
6241


6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac


  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" $ac_given_srcdir/$ac_file_in | eval "$ac_sed_cmds" > $ac_file
fi; done
rm -f conftest.s*

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.







>
>





|







6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac

  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
s%@INSTALL@%$INSTALL%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*

# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
# NAME is the cpp macro being defined and VALUE is the value it is being given.
#
# ac_d sets the value in "#define NAME VALUE" lines.
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287

6288
6289
6290
6291
6292
6293
6294
6295
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'

if test -z "$CONFIG_HEADERS"; then
EOF
cat >> $CONFIG_STATUS <<EOF
  CONFIG_HEADERS="expect_cf.h"
EOF
cat >> $CONFIG_STATUS <<\EOF
fi
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  echo creating $ac_file

  rm -f conftest.frag conftest.in conftest.out

  cp $ac_given_srcdir/$ac_file_in conftest.in

EOF

# Transform confdefs.h into a sed script conftest.vals that substitutes
# the proper values into config.h.in to produce config.h.  And first:
# Protect against being on the right side of a sed subst in config.status.
# Protect against being in an unquoted here document in config.status.







|







|

|







>
|







6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
ac_uD='\4%g'
# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'

if test "${CONFIG_HEADERS+set}" != set; then
EOF
cat >> $CONFIG_STATUS <<EOF
  CONFIG_HEADERS="expect_cf.h"
EOF
cat >> $CONFIG_STATUS <<\EOF
fi
for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  echo creating $ac_file

  rm -f conftest.frag conftest.in conftest.out
  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  cat $ac_file_inputs > conftest.in

EOF

# Transform confdefs.h into a sed script conftest.vals that substitutes
# the proper values into config.h.in to produce config.h.  And first:
# Protect against being on the right side of a sed subst in config.status.
# Protect against being in an unquoted here document in config.status.
6350
6351
6352
6353
6354
6355
6356
6357

6358



6359
6360
6361
6362
6363
6364
6365
      test ! -d "$ac_dir" && mkdir "$ac_dir"
    fi
    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done







exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1

if test "$no_recursion" != yes; then







|
>

>
>
>







6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
      test ! -d "$ac_dir" && mkdir "$ac_dir"
    fi
    rm -f $ac_file
    mv conftest.h $ac_file
  fi
fi; done

EOF
cat >> $CONFIG_STATUS <<EOF

EOF
cat >> $CONFIG_STATUS <<\EOF
chmod +x ${srcdir}/install-sh ${srcdir}/mkinstalldirs
exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1

if test "$no_recursion" != yes; then

Changes to configure.in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
























24
25
26
27
28
29
30
# Process this file with autoconf to produce a configure script.

# while Expect is in alpha/beta, disable caching so as not to confuse
# people trying to fix configure bugs
define([AC_CACHE_LOAD], )
define([AC_CACHE_SAVE], )

AC_INIT(expect.h)

# note when updating version numbers here, also update pkgIndex.in (see
# comments in Makefile)
EXP_MAJOR_VERSION=5
EXP_MINOR_VERSION=28
EXP_MICRO_VERSION=1
EXP_VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION
EXP_VERSION_NODOTS=$EXP_MAJOR_VERSION$EXP_MINOR_VERSION
EXP_VERSION_FULL=$EXP_VERSION.$EXP_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION

# Too many people send me configure output without identifying the version.
# This forced identification should reduce my pain significantly.
echo "configuring Expect $EXP_MAJOR_VERSION.$EXP_MINOR_VERSION.$EXP_MICRO_VERSION"

























dnl AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..)
AC_CANONICAL_SYSTEM

AC_CONFIG_HEADER(expect_cf.h)

# /bin/sh on some systems is too deficient (in particular, Ultrix 4.3












|
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Process this file with autoconf to produce a configure script.

# while Expect is in alpha/beta, disable caching so as not to confuse
# people trying to fix configure bugs
define([AC_CACHE_LOAD], )
define([AC_CACHE_SAVE], )

AC_INIT(expect.h)

# note when updating version numbers here, also update pkgIndex.in (see
# comments in Makefile)
EXP_MAJOR_VERSION=5
EXP_MINOR_VERSION=34
EXP_MICRO_VERSION=0
EXP_VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION
EXP_VERSION_NODOTS=$EXP_MAJOR_VERSION$EXP_MINOR_VERSION
EXP_VERSION_FULL=$EXP_VERSION.$EXP_MICRO_VERSION
# Tcl's handling of shared_lib_suffix requires this symbol exist
VERSION=$EXP_MAJOR_VERSION.$EXP_MINOR_VERSION

# Too many people send me configure output without identifying the version.
# This forced identification should reduce my pain significantly.
echo "configuring Expect $EXP_MAJOR_VERSION.$EXP_MINOR_VERSION.$EXP_MICRO_VERSION"

# People (when downloading Expect from CVS archive) sometimes run into
# Make thinking configure is old and needs to be rebuilt.  If they
# don't have a clue about autoconf, they get confused.  This is
# particular irritating because the problem only crops up after
# configure has successfully completed.  Help them out by checking it
# right now and giving some advice.  Alas, we cannot summarily fix the
# problem because it might conceivably be someone doing real
# development.
# Test if configure is older than configure.in and explain if no autoconf
AC_CHECK_PROG(found,autoconf,yes,no,)
AC_MSG_CHECKING([configure up to date])
for i in `ls -tr ${srcdir}/configure ${srcdir}/configure.in ${srcdir}/Makefile.in` ; do
  newest=$i
done
if test "$srcdir/configure" = "$newest" ; then
  AC_MSG_RESULT(yes)
else
  AC_MSG_RESULT(no)
fi
if test $found = "no" -a "$newest" != "$srcdir/configure" ; then
  AC_MSG_WARN([$srcdir/configure appears to be old ($srcdir/configure.in and/or $srcdir/Makefile.in are newer) and the autoconf program to fix this situation was not found.  If you've no idea what this means, enter the command \"touch $srcdir/configure\" and restart $srcdir/configure.])
  exit
fi

dnl AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..)
AC_CANONICAL_SYSTEM

AC_CONFIG_HEADER(expect_cf.h)

# /bin/sh on some systems is too deficient (in particular, Ultrix 4.3
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# If `configure' is invoked (in)directly via `make', ensure that it
# encounters no `make' conflicts.
#
dnl unset MFLAGS MAKEFLAGS
MFLAGS=
MAKEFLAGS=

CY_AC_PATH_TCLCONFIG
CY_AC_LOAD_TCLCONFIG
CC=$TCL_CC
EXP_AND_TCL_LIBS=$TCL_LIBS
CY_AC_PATH_TKCONFIG
CY_AC_LOAD_TKCONFIG
EXP_AND_TK_LIBS=$TK_LIBS

# An explanation is in order for the strange things going on with the
# various LIBS.  There are three separate definitions for LIBS.  The
# reason is that some systems require shared libraries include
# references to their dependent libraries, i.e., any additional
# libraries that must be linked to.  And some systems get upset if the
# references are repeated on the link line.  So therefore, we create
# one for Expect and Tk (EXP_AND_TK_LIBS), one for Expect and Tcl







<
<
<
<
<
<
<
<







62
63
64
65
66
67
68








69
70
71
72
73
74
75
# If `configure' is invoked (in)directly via `make', ensure that it
# encounters no `make' conflicts.
#
dnl unset MFLAGS MAKEFLAGS
MFLAGS=
MAKEFLAGS=









# An explanation is in order for the strange things going on with the
# various LIBS.  There are three separate definitions for LIBS.  The
# reason is that some systems require shared libraries include
# references to their dependent libraries, i.e., any additional
# libraries that must be linked to.  And some systems get upset if the
# references are repeated on the link line.  So therefore, we create
# one for Expect and Tk (EXP_AND_TK_LIBS), one for Expect and Tcl
72
73
74
75
76
77
78
















79
80
81
82
83
84
85

dnl AC_PROG_CC insists on sticking crap -g and -O in CFLAGS
dnl but I want to control it.  Can't just throw it out at the
dnl end alas, because the user might have defined CFLAGS.
OLD_CFLAGS=$CFLAGS
AC_PROG_CC
CFLAGS=$OLD_CFLAGS

















CY_AC_C_WORKS

# this'll use a BSD compatible install or our included install-sh
AC_PROG_INSTALL

# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

dnl AC_PROG_CC insists on sticking crap -g and -O in CFLAGS
dnl but I want to control it.  Can't just throw it out at the
dnl end alas, because the user might have defined CFLAGS.
OLD_CFLAGS=$CFLAGS
AC_PROG_CC
CFLAGS=$OLD_CFLAGS

#------------------------------------------------------------------------
# Hook for when threading is supported in Expect.  The --enable-threads
# flag currently has no effect.
#------------------------------------------------------------------------

SC_ENABLE_THREADS

CY_AC_PATH_TCLCONFIG
CY_AC_LOAD_TCLCONFIG
CC=$TCL_CC
EXP_AND_TCL_LIBS=$TCL_LIBS
CY_AC_PATH_TKCONFIG
CY_AC_LOAD_TKCONFIG
EXP_AND_TK_LIBS=$TK_LIBS


CY_AC_C_WORKS

# this'll use a BSD compatible install or our included install-sh
AC_PROG_INSTALL

# Tcl sets TCL_RANLIB appropriately for shared library if --enable-shared
99
100
101
102
103
104
105




106





107
108
109
110
111
112
113

AC_TYPE_PID_T
AC_RETSIGTYPE
dnl AC_TIME_WITH_SYS_TIME
AC_HEADER_TIME
AC_HEADER_SYS_WAIT





EXP_CFLAGS=-g





case "${host}" in
 # Use -g on all systems but Linux where it upsets the dynamic X libraries.
  i[[3456]]86-*-linux*)	EXP_CFLAGS="" ;;
esac

AC_MSG_CHECKING([if running Mach])
mach=0







>
>
>
>
|
>
>
>
>
>







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

AC_TYPE_PID_T
AC_RETSIGTYPE
dnl AC_TIME_WITH_SYS_TIME
AC_HEADER_TIME
AC_HEADER_SYS_WAIT

AC_ARG_ENABLE(symbols,
	[  --enable-symbols   allow use of symbols if available],
	[enable_symbols=$enableval], [enable_symbols=no])
if test "$enable_symbols" = "no"; then
  EXP_CFLAGS="$TCL_EXTRA_CFLAGS"
else
  EXP_CFLAGS="-g $TCL_EXTRA_CFLAGS"
  # This is always "g" for unix.
  DBGX=g
fi
case "${host}" in
 # Use -g on all systems but Linux where it upsets the dynamic X libraries.
  i[[3456]]86-*-linux*)	EXP_CFLAGS="" ;;
esac

AC_MSG_CHECKING([if running Mach])
mach=0
488
489
490
491
492
493
494













495
496
497
498
499
500
501
502
503
504
505
506
507
508
509


510
511
512
513
514
515
516
517
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# End of library/func checking
######################################################################














######################################################################
#
# Look for various header files
#
AC_CHECK_HEADER(sys/sysmacros.h, AC_DEFINE(HAVE_SYSMACROS_H))
AC_CHECK_HEADER(stdlib.h, ,AC_DEFINE(NO_STDLIB_H))
AC_CHECK_HEADER(inttypes.h, AC_DEFINE(HAVE_INTTYPES_H))

# Oddly, some systems have stdarg but don't support prototypes
# Tcl avoids the whole issue by not using stdarg on UNIX at all!
dnl AC_CHECK_HEADER(stdarg.h, AC_DEFINE(HAVE_STDARG_H))

AC_CHECK_HEADER(varargs.h, AC_DEFINE(HAVE_VARARGS_H))
AC_CHECK_HEADER(unistd.h, AC_DEFINE(HAVE_UNISTD_H))


AC_CHECK_HEADER(sys/stropts.h, AC_DEFINE(HAVE_STROPTS_H))
AC_CHECK_HEADER(sys/sysconfig.h, AC_DEFINE(HAVE_SYSCONF_H))
AC_CHECK_HEADER(sys/fcntl.h, AC_DEFINE(HAVE_SYS_FCNTL_H))
AC_CHECK_HEADER(sys/select.h, AC_DEFINE(HAVE_SYS_SELECT_H))
AC_CHECK_HEADER(sys/time.h, AC_DEFINE(HAVE_SYS_TIME_H))
AC_CHECK_HEADER(sys/ptem.h, AC_DEFINE(HAVE_SYS_PTEM_H))
AC_CHECK_HEADER(sys/strredir.h, AC_DEFINE(HAVE_STRREDIR_H))
AC_CHECK_HEADER(sys/strpty.h, AC_DEFINE(HAVE_STRPTY_H))







>
>
>
>
>
>
>
>
>
>
>
>
>















>
>
|







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
# save Tk results and reset for Expect
EXP_AND_TK_LIBS=$LIBS
LIBS=$EXP_LIBS

######################################################################
# End of library/func checking
######################################################################

# Hand patches to library/func checking.

dnl From: Michael Kuhl <[email protected]>
dnl To get expect to compile on a Sequent NUMA-Q running DYNIX/ptx v4.4.2.
AC_MSG_CHECKING([if running Sequent running SVR4])
if test "$host_alias" = "i386-sequent-sysv4" ; then
 EXP_AND_TCL_LIBS="-lnsl -lsocket -lm"
 dnl if there's something similar required for Tk, no one's told me!
 AC_MSG_RESULT(yes)
else
 AC_MSG_RESULT(no)
fi

######################################################################
#
# Look for various header files
#
AC_CHECK_HEADER(sys/sysmacros.h, AC_DEFINE(HAVE_SYSMACROS_H))
AC_CHECK_HEADER(stdlib.h, ,AC_DEFINE(NO_STDLIB_H))
AC_CHECK_HEADER(inttypes.h, AC_DEFINE(HAVE_INTTYPES_H))

# Oddly, some systems have stdarg but don't support prototypes
# Tcl avoids the whole issue by not using stdarg on UNIX at all!
dnl AC_CHECK_HEADER(stdarg.h, AC_DEFINE(HAVE_STDARG_H))

AC_CHECK_HEADER(varargs.h, AC_DEFINE(HAVE_VARARGS_H))
AC_CHECK_HEADER(unistd.h, AC_DEFINE(HAVE_UNISTD_H))
# If no stropts.h, then the svr4 implementation is broken.
# At least it is on my Debian "potato" system. - Rob Savoye
AC_CHECK_HEADER(sys/stropts.h, AC_DEFINE(HAVE_STROPTS_H), svr4_ptys_broken=1)
AC_CHECK_HEADER(sys/sysconfig.h, AC_DEFINE(HAVE_SYSCONF_H))
AC_CHECK_HEADER(sys/fcntl.h, AC_DEFINE(HAVE_SYS_FCNTL_H))
AC_CHECK_HEADER(sys/select.h, AC_DEFINE(HAVE_SYS_SELECT_H))
AC_CHECK_HEADER(sys/time.h, AC_DEFINE(HAVE_SYS_TIME_H))
AC_CHECK_HEADER(sys/ptem.h, AC_DEFINE(HAVE_SYS_PTEM_H))
AC_CHECK_HEADER(sys/strredir.h, AC_DEFINE(HAVE_STRREDIR_H))
AC_CHECK_HEADER(sys/strpty.h, AC_DEFINE(HAVE_STRPTY_H))
535
536
537
538
539
540
541

542
543
544
545
546
547
548
#
dnl AC_CHECK_FUNC(memcpy, AC_DEFINE(HAVE_MEMCPY))
AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE))
AC_CHECK_FUNC(sysconf, AC_DEFINE(HAVE_SYSCONF))
AC_CHECK_FUNC(strftime, AC_DEFINE(HAVE_STRFTIME))
AC_CHECK_FUNC(strchr, AC_DEFINE(HAVE_STRCHR))
AC_CHECK_FUNC(timezone, AC_DEFINE(HAVE_TIMEZONE))


# dnl check for memcpy by hand
# because Unixware 2.0 handles it specially and refuses to compile
# autoconf's automatic test that is a call with no arguments
AC_MSG_CHECKING([for memcpy])
AC_TRY_LINK(,[
char *s1, *s2;







>







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
#
dnl AC_CHECK_FUNC(memcpy, AC_DEFINE(HAVE_MEMCPY))
AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE))
AC_CHECK_FUNC(sysconf, AC_DEFINE(HAVE_SYSCONF))
AC_CHECK_FUNC(strftime, AC_DEFINE(HAVE_STRFTIME))
AC_CHECK_FUNC(strchr, AC_DEFINE(HAVE_STRCHR))
AC_CHECK_FUNC(timezone, AC_DEFINE(HAVE_TIMEZONE))
AC_CHECK_FUNC(siglongjmp, AC_DEFINE(HAVE_SIGLONGJMP))

# dnl check for memcpy by hand
# because Unixware 2.0 handles it specially and refuses to compile
# autoconf's automatic test that is a call with no arguments
AC_MSG_CHECKING([for memcpy])
AC_TRY_LINK(,[
char *s1, *s2;
596
597
598
599
600
601
602






















603
604
605
606
607
608
609
	rm -f wnohang
,
	AC_MSG_RESULT(no)
	AC_DEFINE(WNOHANG_BACKUP_VALUE, 1)
,
	AC_MSG_ERROR([Expect can't be cross compiled])
)























#
# check how signals work
#

# Check for the data type of the mask used in select().
# This picks up HP braindamage which defines fd_set and then 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
	rm -f wnohang
,
	AC_MSG_RESULT(no)
	AC_DEFINE(WNOHANG_BACKUP_VALUE, 1)
,
	AC_MSG_ERROR([Expect can't be cross compiled])
)

#-----Stolen from Tcl's configure file-------------------------------
#	The check below checks whether <sys/wait.h> defines the type
#	"union wait" correctly.  It's needed because of weirdness in
#	HP-UX where "union wait" is defined in both the BSD and SYS-V
#	environments.  Checking the usability of WIFEXITED seems to do
#	the trick.
#--------------------------------------------------------------------

AC_MSG_CHECKING([union wait])
AC_TRY_LINK([#include <sys/types.h> 
#include <sys/wait.h>], [
union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */
], tcl_ok=yes, tcl_ok=no)
AC_MSG_RESULT($tcl_ok)
if test $tcl_ok = no; then
    AC_DEFINE(NO_UNION_WAIT)
fi



#
# check how signals work
#

# Check for the data type of the mask used in select().
# This picks up HP braindamage which defines fd_set and then 
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
if test $convex -eq 1 ; then
  AC_MSG_RESULT(yes)
  AC_DEFINE(CONVEX)
else
  AC_MSG_RESULT(no)
fi

EXP_LDFLAGS=

AC_MSG_CHECKING([if on NeXT])
if test -r /NextApps ; then
  AC_MSG_RESULT(yes)
  # "-m" flag suppresses complaints about multiple strtod
  EXP_LDFLAGS="$EXP_LDFLAGS -m"
else







|







767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
if test $convex -eq 1 ; then
  AC_MSG_RESULT(yes)
  AC_DEFINE(CONVEX)
else
  AC_MSG_RESULT(no)
fi

EXP_LDFLAGS="$LDFLAGS"

AC_MSG_CHECKING([if on NeXT])
if test -r /NextApps ; then
  AC_MSG_RESULT(yes)
  # "-m" flag suppresses complaints about multiple strtod
  EXP_LDFLAGS="$EXP_LDFLAGS -m"
else
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800
fi

AC_MSG_CHECKING([for SVR4 style pty allocation])
if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then
  AC_MSG_RESULT(yes)
  AC_DEFINE(HAVE_PTMX)
  # aargg. Some systems need libpt.a to use /dev/ptmx

  AC_CHECK_FUNC(ptsname, , LIBS="${LIBS} -lpt")
  # I've never seen Tcl or Tk include -lpt so don't bother with explicit test
  AC_CHECK_FUNC(ptsname, , EXP_AND_TCL_LIBS="${EXP_AND_TCL_LIBS} -lpt")
  AC_CHECK_FUNC(ptsname, , EXP_AND_TK_LIBS="${EXP_AND_TK_LIBS} -lpt")
else
  AC_MSG_RESULT(no)
fi

# In OSF/1 case, SVR4 are somewhat different.
# Gregory Depp <[email protected]> 17Aug93
AC_MSG_CHECKING([for OSF/1 style pty allocation])







>
|

|
|







862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
fi

AC_MSG_CHECKING([for SVR4 style pty allocation])
if test -r /dev/ptmx -a "x$svr4_ptys_broken" = x ; then
  AC_MSG_RESULT(yes)
  AC_DEFINE(HAVE_PTMX)
  # aargg. Some systems need libpt.a to use /dev/ptmx
  AC_CHECK_LIB(pt, libpts="-lpt", libpts="")
  AC_CHECK_FUNC(ptsname, , LIBS="${LIBS} $libpts")
  # I've never seen Tcl or Tk include -lpt so don't bother with explicit test
  AC_CHECK_FUNC(ptsname, , EXP_AND_TCL_LIBS="${EXP_AND_TCL_LIBS} $libpts")
  AC_CHECK_FUNC(ptsname, , EXP_AND_TK_LIBS="${EXP_AND_TK_LIBS} $libpts")
else
  AC_MSG_RESULT(no)
fi

# In OSF/1 case, SVR4 are somewhat different.
# Gregory Depp <[email protected]> 17Aug93
AC_MSG_CHECKING([for OSF/1 style pty allocation])
968
969
970
971
972
973
974



975
976
977
978
979
980
981
  AC_MSG_RESULT(none)
  AC_DEFINE(SIMPLE_EVENT)
fi

AC_HAVE_FUNCS(_getpty)
AC_HAVE_FUNCS(getpty)




#
# check for timezones
#
AC_MSG_CHECKING([for SV-style timezone])
AC_TRY_RUN([
extern char *tzname[2];
extern int daylight;







>
>
>







1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
  AC_MSG_RESULT(none)
  AC_DEFINE(SIMPLE_EVENT)
fi

AC_HAVE_FUNCS(_getpty)
AC_HAVE_FUNCS(getpty)

# following test sets SETPGRP_VOID if setpgrp takes 0 args, else takes 2
AC_FUNC_SETPGRP

#
# check for timezones
#
AC_MSG_CHECKING([for SV-style timezone])
AC_TRY_RUN([
extern char *tzname[2];
extern int daylight;
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053





1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
# also remove dots on systems that don't support filenames > 14
# (are there systems which support shared libs and restrict filename lengths!?)
AC_SYS_LONG_FILE_NAMES
if test $ac_cv_sys_long_file_names = no; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

EXP_BUILD_LIB_SPEC="-L`pwd` -lexpect${EXP_LIB_VERSION}"
EXP_LIB_SPEC="-L\${exec_prefix}/lib -lexpect${EXP_LIB_VERSION}"
EXP_UNSHARED_LIB_FILE=libexpect${EXP_LIB_VERSION}.a






AC_MSG_CHECKING([for type of library to build])
if test "$enable_shared" = "yes" && test "x${TCL_SHLIB_SUFFIX}" != "x" ; then
  EXP_SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS
#  EXP_SHARED_LIB_FILE=libexpect$EXP_LIB_VERSION$TCL_SHLIB_SUFFIX
  eval "EXP_SHARED_LIB_FILE=libexpect${TCL_SHARED_LIB_SUFFIX}"
  EXP_LIB_FILE=$EXP_SHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_SHARED_LIB_FILE $EXP_UNSHARED_LIB_FILE"
  AC_MSG_RESULT(both shared and unshared)
else
  EXP_SHLIB_CFLAGS=
  EXP_SHARED_LIB_FILE="reconfigure_Tcl_for_shared_library"
  EXP_LIB_FILE=$EXP_UNSHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_UNSHARED_LIB_FILE"
  AC_MSG_RESULT(unshared)
fi

# now broken out into EXP_AND_TCL_LIBS and EXP_AND_TK_LIBS.  Had to do this
# in order to avoid repeating lib specs to which some systems object.
EXP_AND_TCL_LIBS="$EXP_AND_TCL_LIBS $TCL_LD_SEARCH_FLAGS"
EXP_AND_TK_LIBS="$EXP_AND_TK_LIBS $TCL_LD_SEARCH_FLAGS"

# Sigh - Tcl defines SHLIB_LD_LIBS to be either empty or ${LIBS} and
# LIBS is intended to be expanded by Make.  But since we're too close
# to hitting config's max symbols, pack everything together here and
# do test ourselves.  Ugh.  
#
if test "x$TCL_SHLIB_LD_LIBS" = "x" ; then
	EXP_SHLIB_LD_LIBS=""
else
	# seems a little strange to build in Tcl's build-lib, but
	# that's what Tk does.
	EXP_SHLIB_LD_LIBS="$TCL_BUILD_LIB_SPEC $TCL_DL_LIBS $LIBS -lc"
fi

#--------------------------------------------------------------------







|
|
|
>
>
>
>
>




<












<
<
<
<
<






|







1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157





1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# also remove dots on systems that don't support filenames > 14
# (are there systems which support shared libs and restrict filename lengths!?)
AC_SYS_LONG_FILE_NAMES
if test $ac_cv_sys_long_file_names = no; then
    EXP_LIB_VERSION=$EXP_VERSION_NODOTS
fi

EXP_BUILD_LIB_SPEC="-L`pwd` -lexpect${EXP_LIB_VERSION}${DBGX}"
EXP_LIB_SPEC="-L\${INSTALL_ROOT}\${exec_prefix}/lib -lexpect${EXP_LIB_VERSION}${DBGX}"
EXP_UNSHARED_LIB_FILE=libexpect${EXP_LIB_VERSION}${DBGX}.a

# The TCL_SHARED_LIB_SUFFIX macro below relies on the DBGX macro,
# which is set way far above here.  Don't set it to the value of
# TCL_DBGX, or you'll run into problems if you build Tcl with symbols
# and expect without (and vice versa?)

AC_MSG_CHECKING([for type of library to build])
if test "$enable_shared" = "yes" && test "x${TCL_SHLIB_SUFFIX}" != "x" ; then
  EXP_SHLIB_CFLAGS=$TCL_SHLIB_CFLAGS

  eval "EXP_SHARED_LIB_FILE=libexpect${TCL_SHARED_LIB_SUFFIX}"
  EXP_LIB_FILE=$EXP_SHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_SHARED_LIB_FILE $EXP_UNSHARED_LIB_FILE"
  AC_MSG_RESULT(both shared and unshared)
else
  EXP_SHLIB_CFLAGS=
  EXP_SHARED_LIB_FILE="reconfigure_Tcl_for_shared_library"
  EXP_LIB_FILE=$EXP_UNSHARED_LIB_FILE
  EXP_LIB_FILES="$EXP_UNSHARED_LIB_FILE"
  AC_MSG_RESULT(unshared)
fi






# Sigh - Tcl defines SHLIB_LD_LIBS to be either empty or ${LIBS} and
# LIBS is intended to be expanded by Make.  But since we're too close
# to hitting config's max symbols, pack everything together here and
# do test ourselves.  Ugh.  
#
if test "x$TCL_SHLIB_LD_LIBS" = "x" ; then
	EXP_SHLIB_LD_LIBS="$LIBS"
else
	# seems a little strange to build in Tcl's build-lib, but
	# that's what Tk does.
	EXP_SHLIB_LD_LIBS="$TCL_BUILD_LIB_SPEC $TCL_DL_LIBS $LIBS -lc"
fi

#--------------------------------------------------------------------
1100
1101
1102
1103
1104
1105
1106

1107
1108







1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

1119



1120






1121
1122
1123
1124
1125
1126
1127
#--------------------------------------------------------------------

LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}'

# If Tcl and Expect are installed in different places, adjust the library
# search path to reflect this.


if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}"







fi

if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

# The statement below is very tricky!  It actually *evaluates* the
# string in TCL_LD_SEARCH_FLAGS, which causes a substitution of the
# variable LIB_RUNTIME_DIR.


eval "EXP_CC_SEARCH_FLAGS=\"$TCL_LD_SEARCH_FLAGS\""



EXP_LD_SEARCH_FLAGS=`echo ${EXP_CC_SEARCH_FLAGS} |sed -e "s|-Wl,||g" -e "s|,| |g"`







#
# Set up makefile substitutions
#
AC_SUBST(EXP_MAJOR_VERSION)
AC_SUBST(EXP_MINOR_VERSION)
AC_SUBST(EXP_MICRO_VERSION)







>
|
|
>
>
>
>
>
>
>






|
|


>
|
>
>
>
|
>
>
>
>
>
>







1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
#--------------------------------------------------------------------

LIB_RUNTIME_DIR='${LIB_RUNTIME_DIR}'

# If Tcl and Expect are installed in different places, adjust the library
# search path to reflect this.

if test x"$no_tk" = x"true" ; then
  if test "$TCL_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TCL_EXEC_PREFIX}/lib"
  fi
else
  if test "$TK_EXEC_PREFIX" != "$exec_prefix"; then
    LIB_RUNTIME_DIR="${LIB_RUNTIME_DIR}:${TK_EXEC_PREFIX}/lib"
    # no need to include TCL's search path, because TK does it already
    # (it is actually appended later, via TK_LD_SEARCH_FLAGS trick below)
  fi
fi

if test "${TCL_LD_SEARCH_FLAGS}" = '-L${LIB_RUNTIME_DIR}'; then
    LIB_RUNTIME_DIR=`echo ${LIB_RUNTIME_DIR} |sed -e 's/:/ -L/g'`
fi

# The eval below is tricky!  It *evaluates* the string in
# ..._CC_SEARCH_FLAGS, which causes a substitution of the
# variable LIB_RUNTIME_DIR.

if test x"$no_tk" = x"true" ; then
  eval "EXP_CC_SEARCH_FLAGS=\"$TCL_CC_SEARCH_FLAGS\""
  EXP_LD_SEARCH_FLAGS=${TCL_LD_SEARCH_FLAGS}
else
  eval "EXP_CC_SEARCH_FLAGS=\"$TK_CC_SEARCH_FLAGS\""
  EXP_LD_SEARCH_FLAGS=${TK_LD_SEARCH_FLAGS}
fi

# now broken out into EXP_AND_TCL_LIBS and EXP_AND_TK_LIBS.  Had to do this
# in order to avoid repeating lib specs to which some systems object.
EXP_AND_TCL_LIBS="$EXP_AND_TCL_LIBS $EXP_CC_SEARCH_FLAGS"
EXP_AND_TK_LIBS="$EXP_AND_TK_LIBS $EXP_CC_SEARCH_FLAGS"

#
# Set up makefile substitutions
#
AC_SUBST(EXP_MAJOR_VERSION)
AC_SUBST(EXP_MINOR_VERSION)
AC_SUBST(EXP_MICRO_VERSION)
1135
1136
1137
1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152


AC_SUBST(EXP_LIB_FILE)
AC_SUBST(EXP_LIB_FILES)
AC_SUBST(EXP_BUILD_LIB_SPEC)
AC_SUBST(EXP_LIB_SPEC)
AC_SUBST(EXP_CFLAGS)
AC_SUBST(EXP_LDFLAGS)
AC_SUBST(EXP_LD_SEARCH_FLAGS)

AC_SUBST(EXP_AND_TCL_LIBS)
AC_SUBST(EXP_AND_TK_LIBS)
AC_SUBST(EXP_SHLIB_LD_LIBS)
AC_SUBST(X_PROGS)
AC_SUBST(PTY_TYPE)
AC_SUBST(EVENT_TYPE)
AC_SUBST(EVENT_ABLE)
AC_SUBST(SETUID)
AC_SUBST(UNSHARED_RANLIB)
AC_SUBST(DEFAULT_STTY_ARGS)
AC_OUTPUT(Makefile pkgIndex)









>










|
>
>
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
AC_SUBST(EXP_LIB_FILE)
AC_SUBST(EXP_LIB_FILES)
AC_SUBST(EXP_BUILD_LIB_SPEC)
AC_SUBST(EXP_LIB_SPEC)
AC_SUBST(EXP_CFLAGS)
AC_SUBST(EXP_LDFLAGS)
AC_SUBST(EXP_LD_SEARCH_FLAGS)
AC_SUBST(TCL_LD_SEARCH_FLAGS)
AC_SUBST(EXP_AND_TCL_LIBS)
AC_SUBST(EXP_AND_TK_LIBS)
AC_SUBST(EXP_SHLIB_LD_LIBS)
AC_SUBST(X_PROGS)
AC_SUBST(PTY_TYPE)
AC_SUBST(EVENT_TYPE)
AC_SUBST(EVENT_ABLE)
AC_SUBST(SETUID)
AC_SUBST(UNSHARED_RANLIB)
AC_SUBST(DEFAULT_STTY_ARGS)
AC_OUTPUT([Makefile \
	pkgIndex],
	chmod +x ${srcdir}/install-sh ${srcdir}/mkinstalldirs)

Changes to example/Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
TCLVERSION = 8.0
EXPVERSION = 5.25
TCLROOT = ../../tcl$(TCLVERSION)

# Tcl include files.  (If you haven't installed Tcl yet, read the README file).
# This must point to the directory that contains ALL of Tcl's include
# files, not just the public ones.
TCLHDIR = $(TCLROOT)/generic

# TCL library.  Very little actually comes out of it, but it is handy.
TCLLIB = $(TCLROOT)/unix/libtcl$(TCLVERSION).so
# if installed, you can use:
# TCLLIB = -ltcl

CC = gcc
CPLUSPLUS = g++
CPLUSPLUSLIBDIR = -L/depot/gnu/arch/lib
CPLUSPLUSLIB = -lg++

CFLAGS = -g -I.. -I$(TCLHDIR)
LIBEXPECT = -L.. -lexpect$(EXPVERSION)

LIBS = $(LIBEXPECT) $(TCLLIB) -lm

SCRIPTS = su2 noidle script.exp bonfield.exp

all: chesslib chesslib2 chesslib++

# this can be compiled with either cc or gcc
chesslib: chesslib.o
<
|
<
<
<
<
<
<
<
<
<
<
<






|


|








1











2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

EXPVERSION = 5.31












CC = gcc
CPLUSPLUS = g++
CPLUSPLUSLIBDIR = -L/depot/gnu/arch/lib
CPLUSPLUSLIB = -lg++

CFLAGS = -g -I..
LIBEXPECT = -L.. -lexpect$(EXPVERSION)

LIBS = $(LIBEXPECT) -lm

SCRIPTS = su2 noidle script.exp bonfield.exp

all: chesslib chesslib2 chesslib++

# this can be compiled with either cc or gcc
chesslib: chesslib.o

Changes to example/autoexpect.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
set filename "script.exp"
set verbose 1
set conservative 0
set promptmode 0
set option_keys ""

proc check_for_following {type} {
	if ![llength [uplevel set argv]] {
		puts "autoexpect: [uplevel set flag] requires following $type"
		exit 1
	}
}	

while {[llength $argv]>0} {
	set flag [lindex $argv 0]
	if 0==[regexp "^-" $flag] break
	set argv [lrange $argv 1 end]
	switch -- $flag \
	  "-c" {
		set conservative 1
	} "-C" {
		check_for_following character
		lappend option_keys [lindex $argv 0] ctoggle







|







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
set filename "script.exp"
set verbose 1
set conservative 0
set promptmode 0
set option_keys ""

proc check_for_following {type} {
	if {![llength [uplevel set argv]]} {
		puts "autoexpect: [uplevel set flag] requires following $type"
		exit 1
	}
}	

while {[llength $argv]>0} {
	set flag [lindex $argv 0]
	if {0==[regexp "^-" $flag]} break
	set argv [lrange $argv 1 end]
	switch -- $flag \
	  "-c" {
		set conservative 1
	} "-C" {
		check_for_following character
		lappend option_keys [lindex $argv 0] ctoggle
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Handle a null character from the keyboard
proc input_null {} {
	global lastkey userbuf procbuf echoing

	send -null

	if {$lastkey == ""} {
		if $echoing {
			sendcmd "$userbuf"
		}
		if {$procbuf != ""} {
			expcmd "$procbuf"
		}
	} else {
		sendcmd "$userbuf"
		if $echoing {
			expcmd "$procbuf"
			sendcmd "$lastkey"
		}			
	}
	cmd "send -null"
	set userbuf ""
	set procbuf ""
	set lastkey ""
	set echoing 0
}

# Handle a character that came from the process
proc output {s} {
	global lastkey procbuf userbuf echoing

	send_user -raw -- $s

	if {$lastkey == ""} {
		if !$echoing {
			append procbuf $s
		} else {
			sendcmd "$userbuf"
			expcmd "$procbuf"
			set echoing 0
			set userbuf ""
			set procbuf $s
		}
		return
	}

	regexp (.)(.*) $s dummy c tail
	if {$c == $lastkey} {
		if $echoing {
			append userbuf $lastkey
			set lastkey ""
		} else {
			if {$procbuf != ""} {
				expcmd "$procbuf"
				set procbuf ""
			}
			set echoing 1
		}
		append procbuf $s

		if [string length $tail] {
			sendcmd "$userbuf$lastkey"
			set userbuf ""
			set lastkey ""
			set echoing 0
		}
	} else {
		if !$echoing {
			expcmd "$procbuf"
		}
		sendcmd "$userbuf$lastkey"
		set procbuf $s
		set userbuf ""
		set lastkey ""
		set echoing 0







|







|


















|













|











|






|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Handle a null character from the keyboard
proc input_null {} {
	global lastkey userbuf procbuf echoing

	send -null

	if {$lastkey == ""} {
		if {$echoing} {
			sendcmd "$userbuf"
		}
		if {$procbuf != ""} {
			expcmd "$procbuf"
		}
	} else {
		sendcmd "$userbuf"
		if {$echoing} {
			expcmd "$procbuf"
			sendcmd "$lastkey"
		}			
	}
	cmd "send -null"
	set userbuf ""
	set procbuf ""
	set lastkey ""
	set echoing 0
}

# Handle a character that came from the process
proc output {s} {
	global lastkey procbuf userbuf echoing

	send_user -raw -- $s

	if {$lastkey == ""} {
		if {!$echoing} {
			append procbuf $s
		} else {
			sendcmd "$userbuf"
			expcmd "$procbuf"
			set echoing 0
			set userbuf ""
			set procbuf $s
		}
		return
	}

	regexp (.)(.*) $s dummy c tail
	if {$c == $lastkey} {
		if {$echoing} {
			append userbuf $lastkey
			set lastkey ""
		} else {
			if {$procbuf != ""} {
				expcmd "$procbuf"
				set procbuf ""
			}
			set echoing 1
		}
		append procbuf $s

		if {[string length $tail]} {
			sendcmd "$userbuf$lastkey"
			set userbuf ""
			set lastkey ""
			set echoing 0
		}
	} else {
		if {!$echoing} {
			expcmd "$procbuf"
		}
		sendcmd "$userbuf$lastkey"
		set procbuf $s
		set userbuf ""
		set lastkey ""
		set echoing 0
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	return $s
}

# generate an expect command
proc expcmd {s} {
	global promptmode

	if $promptmode {
		regexp ".*\[\r\n]+(.*)" $s dummy s
	}

	cmd "expect -exact \"[expand $s]\""
}

# generate a send command







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	return $s
}

# generate an expect command
proc expcmd {s} {
	global promptmode

	if {$promptmode} {
		regexp ".*\[\r\n]+(.*)" $s dummy s
	}

	cmd "expect -exact \"[expand $s]\""
}

# generate a send command
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
	global fd
	puts $fd "$s"
}

proc verbose_send_user {s} {
	global verbose

	if $verbose {
		send_user -- $s
	}
}

proc ctoggle {} {
	global conservative send_style

	if $conservative {
		cmd "# conservative mode off - adding no delays"
		verbose_send_user "conservative mode off\n"
		set conservative 0
		set send_style ""
	} else {
		cmd "# prompt mode on - adding delays"
		verbose_send_user "conservative mode on\n"
		set conservative 1
		set send_style " -s"
	}
}

proc ptoggle {} {
	global promptmode

	if $promptmode {
		cmd "# prompt mode off - now looking for complete output"
		verbose_send_user "prompt mode off\n"
		set promptmode 0
	} else {
		cmd "# prompt mode on - now looking only for prompts"
		verbose_send_user "prompt mode on\n"
		set promptmode 1
	}
}

# quote the next character from the user
proc quote {} {
	expect_user -re .
	send -- $expect_out(buffer)
}
	

if [catch {set fd [open $filename w]} msg] {
	puts $msg
	exit
}
exec chmod +x $filename
verbose_send_user "autoexpect started, file is $filename\n"

# calculate a reasonable #! line
set expectpath /usr/local/bin		;# prepare default
foreach dir [split $env(PATH) :] {	;# now look for real location
	if [file executable $dir/expect] {
		set expectpath $dir
		break
	}
}

cmd "#![set expectpath]/expect -f
#







|







|















|

















|









|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
	global fd
	puts $fd "$s"
}

proc verbose_send_user {s} {
	global verbose

	if {$verbose} {
		send_user -- $s
	}
}

proc ctoggle {} {
	global conservative send_style

	if {$conservative} {
		cmd "# conservative mode off - adding no delays"
		verbose_send_user "conservative mode off\n"
		set conservative 0
		set send_style ""
	} else {
		cmd "# prompt mode on - adding delays"
		verbose_send_user "conservative mode on\n"
		set conservative 1
		set send_style " -s"
	}
}

proc ptoggle {} {
	global promptmode

	if {$promptmode} {
		cmd "# prompt mode off - now looking for complete output"
		verbose_send_user "prompt mode off\n"
		set promptmode 0
	} else {
		cmd "# prompt mode on - now looking only for prompts"
		verbose_send_user "prompt mode on\n"
		set promptmode 1
	}
}

# quote the next character from the user
proc quote {} {
	expect_user -re .
	send -- $expect_out(buffer)
}
	

if {[catch {set fd [open $filename w]} msg]} {
	puts $msg
	exit
}
exec chmod +x $filename
verbose_send_user "autoexpect started, file is $filename\n"

# calculate a reasonable #! line
set expectpath /usr/local/bin		;# prepare default
foreach dir [split $env(PATH) :] {	;# now look for real location
	if {[file executable $dir/expect] && ![file isdirectory $dir/expect]} {
		set expectpath $dir
		break
	}
}

cmd "#![set expectpath]/expect -f
#
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# Read the man page for more info.
#
# -Don

}

cmd "set timeout -1"
if $conservative {
	set send_style " -s"
	cmd "set send_slow {1 .1}"
} else {
	set send_style ""
}

if [llength $argv]>0 {
	eval spawn -noecho $argv
	cmd "spawn $argv"
} else {
	spawn -noecho $env(SHELL)
	cmd "spawn \$env(SHELL)"
}

cmd "match_max 100000"

set lastkey ""
set procbuf ""
set userbuf ""
set echoing 0

remove_nulls 0

eval interact $option_keys {
	-re . {
		input $interact_out(0,string)
	} null {
		input_null
	} \
	-o \
	-re .+ {
		output $interact_out(0,string)
	} eof {
		cmd "expect eof"
		return
	} null {
	}
}

close $fd
verbose_send_user "autoexpect done, file is $filename\n"







|






|

















|
|
<
<
<
<
|
|
|
|
|
<
|




299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332




333
334
335
336
337

338
339
340
341
342
# Read the man page for more info.
#
# -Don

}

cmd "set timeout -1"
if {$conservative} {
	set send_style " -s"
	cmd "set send_slow {1 .1}"
} else {
	set send_style ""
}

if {[llength $argv]>0} {
	eval spawn -noecho $argv
	cmd "spawn $argv"
} else {
	spawn -noecho $env(SHELL)
	cmd "spawn \$env(SHELL)"
}

cmd "match_max 100000"

set lastkey ""
set procbuf ""
set userbuf ""
set echoing 0

remove_nulls 0

eval interact $option_keys {
    -re . {
	input $interact_out(0,string)




    } -o -re .+ {
	output $interact_out(0,string)
    } eof {
	cmd "expect eof"
	return

    }
}

close $fd
verbose_send_user "autoexpect done, file is $filename\n"

Changes to example/beer.exp.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
proc line4 {i} {
    out $i "[bottles $i] on the wall.\n\n"
}

proc out {i s} {
    foreach c [split $s ""] {
	# don't touch punctuation; just looks too strange if you do
	if [regexp "\[,. \n\]" $c] {
	    append d $c
	    continue
	}

	# keep first couple of verses straight
	if {$i > 97} {append d $c; continue}

	# +3 prevents it from degenerating too far
	# /2 makes it degenerate faster though

	set r [rand [expr $i/2+3]]
	if {$r} {append d $c; continue}

	# do something strange
	switch [rand 3] {
	    0 {
		# substitute another letter

		if [regexp \[aeiou\] $c] {
		    # if vowel, substitute another
		    append d [string index aeiou [rand 5]]
		} elseif [regexp \[0-9\] $c] {
		    # if number, substitute another
		    append d [string index 123456789 [rand 9]]
		} else {
		    # if consonant, substitute another
		    append d [string index bcdfghjklmnpqrstvwxyz [rand 21]]
		}
	    } 1 {







|


















|


|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
proc line4 {i} {
    out $i "[bottles $i] on the wall.\n\n"
}

proc out {i s} {
    foreach c [split $s ""] {
	# don't touch punctuation; just looks too strange if you do
	if {[regexp "\[,. \n\]" $c]} {
	    append d $c
	    continue
	}

	# keep first couple of verses straight
	if {$i > 97} {append d $c; continue}

	# +3 prevents it from degenerating too far
	# /2 makes it degenerate faster though

	set r [rand [expr $i/2+3]]
	if {$r} {append d $c; continue}

	# do something strange
	switch [rand 3] {
	    0 {
		# substitute another letter

		if {[regexp \[aeiou\] $c]} {
		    # if vowel, substitute another
		    append d [string index aeiou [rand 5]]
		} elseif {[regexp \[0-9\] $c]} {
		    # if number, substitute another
		    append d [string index 123456789 [rand 9]]
		} else {
		    # if consonant, substitute another
		    append d [string index bcdfghjklmnpqrstvwxyz [rand 21]]
		}
	    } 1 {

Changes to example/carpal.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Script to enforce a 10 minute break every half hour from typing - 
# Written for someone (Uwe Hollerbach) with Carpal Tunnel Syndrome.

# If you type for more than 20 minutes straight, the script rings
# the bell after every character until you take a 10 minute break.

# Author: Don Libes, NIST
# Date: Feb 26, '95

spawn $env(SHELL)
set start [timestamp]	;# when we started our current typing period
set stop [timestamp]	;# when we stopped typing

set typing 1200		;# twenty minutes, max typing time allowed
set notyping 600	;# ten minutes, min notyping time required

interact -nobuffer -re . {
	set now [timestamp]

	if {$now-$stop > $notyping} {
		set start [timestamp]
	} elseif {$now-$start > $typing} {
		send_user "\007"
	}
	set stop [timestamp]
}










|
|





|

|
|
|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Script to enforce a 10 minute break every half hour from typing - 
# Written for someone (Uwe Hollerbach) with Carpal Tunnel Syndrome.

# If you type for more than 20 minutes straight, the script rings
# the bell after every character until you take a 10 minute break.

# Author: Don Libes, NIST
# Date: Feb 26, '95

spawn $env(SHELL)
set start [clock seconds]	;# when we started our current typing period
set stop [clock seconds]	;# when we stopped typing

set typing 1200		;# twenty minutes, max typing time allowed
set notyping 600	;# ten minutes, min notyping time required

interact -nobuffer -re . {
    set now [clock seconds]

    if {$now-$stop > $notyping} {
	set start [clock seconds]
    } elseif {$now-$start > $typing} {
	send_user "\007"
    }
    set stop [clock seconds]
}

Changes to example/chess.exp.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#
# n/kn1-kb3		(echo from first player)
# 2. n/kn1-kb3		(reprint it as above, but differently - god knows why)
# 2. ... p/k4-k5	(our new countermove - written differently, of course)

set timeout -1;			# wait forever
expect_before {
	-i $any_spawn_id eof {
		send_user "player resigned!\n"
		exit
	}
}

# start things rolling
spawn chess
set id1 $spawn_id
expect "Chess\r\n"
send "first\r"
# read_first_move
expect -re "1. (.*)\n"

spawn chess
set id2 $spawn_id
expect "Chess\r\n"
send $expect_out(1,string)

for {} 1 {} {
	expect {
		-i $id2 -re "\\.\\. (.*)\n" {
			send -i $id1 $expect_out(1,string)
		}
		-i $id1 -re "\\.\\. .*\\. (.*)\n" {
			send -i $id2 $expect_out(1,string)
		}
	}
}







|
|
|
|















|
|
|
|
|
|
|
|
|

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#
# n/kn1-kb3		(echo from first player)
# 2. n/kn1-kb3		(reprint it as above, but differently - god knows why)
# 2. ... p/k4-k5	(our new countermove - written differently, of course)

set timeout -1;			# wait forever
expect_before {
    -i $any_spawn_id eof {
	send_user "player resigned!\n"
	exit
    }
}

# start things rolling
spawn chess
set id1 $spawn_id
expect "Chess\r\n"
send "first\r"
# read_first_move
expect -re "1. (.*)\n"

spawn chess
set id2 $spawn_id
expect "Chess\r\n"
send $expect_out(1,string)

while {1} {
    expect {
	-i $id2 -re "\\.\\. (.*)\n" {
	    send -i $id1 $expect_out(1,string)
	}
	-i $id1 -re "\\.\\. .*\\. (.*)\n" {
	    send -i $id2 $expect_out(1,string)
	}
    }
}

Changes to example/chesslib++.c.

58
59
60
61
62
63
64
65



66
67
68
69
70
71
72

main(){
	int fd1, fd2;

	exp_loguser = 1;
	exp_timeout = 3600;

	fd1 = exp_spawnl("chess","chess",(char *)0);




	if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit;

	if (-1 == write(fd1,"first\r",6)) exit;

	read_first_move(fd1);








|
>
>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

main(){
	int fd1, fd2;

	exp_loguser = 1;
	exp_timeout = 3600;

	if (-1 == (fd1 = exp_spawnl("chess","chess",(char *)0))) {
	  perror("chess");
	  exit(-1);
	}

	if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit;

	if (-1 == write(fd1,"first\r",6)) exit;

	read_first_move(fd1);

Changes to example/chesslib.c.

54
55
56
57
58
59
60
61



62
63
64
65
66
67
68

main(){
	int fd1, fd2;

	exp_loguser = 1;
	exp_timeout = 3600;

	fd1 = exp_spawnl("chess","chess",(char *)0);




	if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit;

	if (-1 == write(fd1,"first\r",6)) exit;

	read_first_move(fd1);








|
>
>
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

main(){
	int fd1, fd2;

	exp_loguser = 1;
	exp_timeout = 3600;

	if (-1 == (fd1 = exp_spawnl("chess","chess",(char *)0))) {
	  perror("chess");
	  exit(-1);
	}

	if (-1 == exp_expectl(fd1,exp_glob,"Chess\r\n",0,exp_end)) exit;

	if (-1 == write(fd1,"first\r",6)) exit;

	read_first_move(fd1);

Changes to example/chesslib2.c.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	int ec;

/*	exp_is_debugging = 1;*/
	exp_loguser = 1;
	exp_timeout = 3600;

	if (0 == (fp1 = exp_popen("chess"))) {
		printf("exp_popen failed\n");
		exit(-1);
	}

	if (0 > exp_fexpectl(fp1,exp_glob,"Chess\r\n",0,exp_end)) exit(-1);
	fprintf(fp1,"first\r");

	read_first_move(fp1);








|
|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	int ec;

/*	exp_is_debugging = 1;*/
	exp_loguser = 1;
	exp_timeout = 3600;

	if (0 == (fp1 = exp_popen("chess"))) {
	  perror("chess");
	  exit(-1);
	}

	if (0 > exp_fexpectl(fp1,exp_glob,"Chess\r\n",0,exp_end)) exit(-1);
	fprintf(fp1,"first\r");

	read_first_move(fp1);

Changes to example/cryptdir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!../expect --
# Name: cryptdir
# Author: Don Libes, NIST
#
# Synopsis:
#	  cryptdir [dir]
#	decryptdir [dir]
#
# Encrypt or decrypts the current directory or named directory if given.

if {[llength $argv] > 0} {
	cd $argv
}

# encrypt or decrypt?
set decrypt [regexp "decrypt" $argv0]

set timeout -1
stty -echo
send "Password:"
expect -re "(.*)\n"
send "\n"
set passwd $expect_out(1,string)

# wouldn't want to encrypt files with mistyped password!
if !$decrypt {
	send "Again:"
	expect -re "(.*)\n"
	send "\n"
	if ![string match $passwd $expect_out(1,string)] {
		send_user "mistyped password?\n"
		stty echo
		exit
	}
}
stty echo

log_user 0
foreach f [glob *] {
	# strip shell metachars from filename to avoid problems
	if [regsub -all {[]['`~<>:-]} $f "" newf] {
		exec mv $f $newf
		set f $newf
	}

	set strcmp [string compare .crypt [file extension $f]]
	if $decrypt {
		# skip files that don't end with ".crypt"
		if 0!=$strcmp continue
		spawn sh -c "exec crypt < $f > [file root $f]"
	} else {
		# skip files that already end with ".crypt"
		if 0==$strcmp continue
		spawn sh -c "exec crypt < $f > $f.crypt"
	}
	expect "key:"
	send "$passwd\r"
	expect
	wait
	exec rm -f $f
	send_tty "."
}
send_tty "\n"











|












|
<
|
|
|
|
|
|
|
<





|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!../expect --
# Name: cryptdir
# Author: Don Libes, NIST
#
# Synopsis:
#	  cryptdir [dir]
#	decryptdir [dir]
#
# Encrypt or decrypts the current directory or named directory if given.

if {[llength $argv] > 0} {
    cd $argv
}

# encrypt or decrypt?
set decrypt [regexp "decrypt" $argv0]

set timeout -1
stty -echo
send "Password:"
expect -re "(.*)\n"
send "\n"
set passwd $expect_out(1,string)

# Wouldn't want to encrypt/decrypt files with mistyped password!

send "Again:"
expect -re "(.*)\n"
send "\n"
if {![string match $passwd $expect_out(1,string)]} {
    send_user "mistyped password?\n"
    stty echo
    exit

}
stty echo

log_user 0
foreach f [glob *] {
    # strip shell metachars from filename to avoid problems
    if {[regsub -all {[]['`~<>:-]} $f "" newf]} {
	exec mv $f $newf
	set f $newf
    }

    set strcmp [string compare .crypt [file extension $f]]
    if {$decrypt} {
	# skip files that don't end with ".crypt"
	if {0!=$strcmp} continue
	spawn sh -c "exec crypt < $f > [file root $f]"
    } else {
	# skip files that already end with ".crypt"
	if {0==$strcmp} continue
	spawn sh -c "exec crypt < $f > $f.crypt"
    }
    expect "key:"
    send "$passwd\r"
    expect
    wait
    exec rm -f $f
    send_tty "."
}
send_tty "\n"

Changes to example/decryptdir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!../expect --
# Name: cryptdir
# Author: Don Libes, NIST
#
# Synopsis:
#	  cryptdir [dir]
#	decryptdir [dir]
#
# Encrypt or decrypts the current directory or named directory if given.

if {[llength $argv] > 0} {
	cd $argv
}

# encrypt or decrypt?
set decrypt [regexp "decrypt" $argv0]

set timeout -1
stty -echo
send "Password:"
expect -re "(.*)\n"
send "\n"
set passwd $expect_out(1,string)

# wouldn't want to encrypt files with mistyped password!
if !$decrypt {
	send "Again:"
	expect -re "(.*)\n"
	send "\n"
	if ![string match $passwd $expect_out(1,string)] {
		send_user "mistyped password?"
		stty echo
		exit
	}
}
stty echo

log_user 0
foreach f [glob *] {
	# strip shell metachars from filename to avoid problems
	if [regsub -all {[]['`~<>:-]} $f "" newf] {
		exec mv $f $newf
		set f $newf
	}

	set strcmp [string compare .crypt [file extension $f]]
	if $decrypt {
		# skip files that don't end with ".crypt"
		if 0!=$strcmp continue
		spawn sh -c "exec crypt < $f > [file root $f]"
	} else {
		# skip files that already end with ".crypt"
		if 0==$strcmp continue
		spawn sh -c "exec crypt < $f > $f.crypt"
	}
	expect "key:"
	send "$passwd\r"
	expect
	wait
	exec rm -f $f
	send_tty "."
}
send_tty "\n"











|












|
<
|
|
|
|
|
|
|
<





|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!../expect --
# Name: cryptdir
# Author: Don Libes, NIST
#
# Synopsis:
#	  cryptdir [dir]
#	decryptdir [dir]
#
# Encrypt or decrypts the current directory or named directory if given.

if {[llength $argv] > 0} {
    cd $argv
}

# encrypt or decrypt?
set decrypt [regexp "decrypt" $argv0]

set timeout -1
stty -echo
send "Password:"
expect -re "(.*)\n"
send "\n"
set passwd $expect_out(1,string)

# Wouldn't want to encrypt/decrypt files with mistyped password!

send "Again:"
expect -re "(.*)\n"
send "\n"
if {![string match $passwd $expect_out(1,string)]} {
    send_user "mistyped password?\n"
    stty echo
    exit

}
stty echo

log_user 0
foreach f [glob *] {
    # strip shell metachars from filename to avoid problems
    if {[regsub -all {[]['`~<>:-]} $f "" newf]} {
	exec mv $f $newf
	set f $newf
    }

    set strcmp [string compare .crypt [file extension $f]]
    if {$decrypt} {
	# skip files that don't end with ".crypt"
	if {0!=$strcmp} continue
	spawn sh -c "exec crypt < $f > [file root $f]"
    } else {
	# skip files that already end with ".crypt"
	if {0==$strcmp} continue
	spawn sh -c "exec crypt < $f > $f.crypt"
    }
    expect "key:"
    send "$passwd\r"
    expect
    wait
    exec rm -f $f
    send_tty "."
}
send_tty "\n"

Changes to example/dislocate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81








82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

194


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

273
274



275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326


327
328
329
330
331
332
333
334





335
336
337
338
339
340
341
342

#!../expect --
# dislocate - allow disconnection and reconnection to a background program
# Author: Don Libes, NIST

exp_version -exit 5.1

# The following code attempts to intuit whether cat buffers by default.
# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems.
if [file exists $exp_exec_library/cat-buffers] {
	set catflags "-u"
} else {
	set catflags ""
}
# If this fails, you can also force it by commenting in one of the following.
# Or, you can use the -catu flag to the script.
#set catflags ""
#set catflags "-u"

set escape \035			;# control-right-bracket
set escape_printable "^\]"

set pidfile "~/.dislocate"
set prefix "disc"
set timeout -1
set debug_flag 0

while {$argc} {
	set flag [lindex $argv 0]
	switch -- $flag \
	"-catu" {
		set catflags "-u"
		set argv [lrange $argv 1 end]
		incr argc -1
	} "-escape" {
		set escape [lindex $argv 1]
		set escape_printable $escape
		set argv [lrange $argv 2 end]
		incr argc -2
	} "-debug" {
		log_file [lindex $argv 1]
		set debug_flag 1
		set argv [lrange $argv 2 end]
		incr argc -2
	} default {
		break
	}
}

# These are correct from parent's point of view.
# In child, we will reset these so that they appear backwards
# thus allowing following two routines to be used by both parent and child
set  infifosuffix ".i"
set outfifosuffix ".o"

proc infifoname {pid} {
	global prefix infifosuffix

	return "/tmp/$prefix$pid$infifosuffix"
}

proc outfifoname {pid} {
	global prefix outfifosuffix

	return "/tmp/$prefix$pid$outfifosuffix"
}

proc pid_remove {pid} {
	global date proc

	say "removing $pid $proc($pid)"

	unset date($pid)
	unset proc($pid)
}

# lines in data file looks like this:
# pid#date-started#argv

# allow element lookups on empty arrays
set date(dummy) dummy;	unset date(dummy)
set proc(dummy) dummy;	unset proc(dummy)









# load pidfile into memory
proc pidfile_read {} {
	global date proc pidfile


	if [catch {open $pidfile} fp] return

	#
	# read info out of file
	#

	say "reading pidfile"
	set line 0
	while {[gets $fp buf]!=-1} {
		# while pid and date can't have # in it, proc can
		if [regexp "(\[^#]*)#(\[^#]*)#(.*)" $buf junk pid xdate xproc] {
			set date($pid) $xdate
			set proc($pid) $xproc
		} else {
			puts "warning: inconsistency in $pidfile line $line"
		}
		incr line
	}
	close $fp
	say "read $line entries"

	#
	# see if pids and fifos are still around
	#

	foreach pid [array names date] {
		if {$pid && [catch {exec /bin/kill -0 $pid}]} {
			say "$pid no longer exists, removing"
			pid_remove $pid
			continue
		}

		# pid still there, see if fifos are
		if {![file exists [infifoname $pid]] || ![file exists [outfifoname $pid]]} {
			say "$pid fifos no longer exists, removing"
			pid_remove $pid
			continue
		}
	}
}

proc pidfile_write {} {
	global pidfile date proc

	say "writing pidfile"

	set fp [open $pidfile w]
	foreach pid [array names date] {
		puts $fp "$pid#$date($pid)#$proc($pid)"
		say "wrote $pid#$date($pid)#$proc($pid)"
	}
	close $fp
}

proc fifo_pair_remove {pid} {
	global date proc prefix

	pidfile_read
	pid_remove $pid
	pidfile_write

	catch {exec rm -f [infifoname $pid] [outfifoname $pid]}
}

proc fifo_pair_create {pid argdate argv} {
	global prefix date proc

	pidfile_read
	set date($pid) $argdate
	set proc($pid) $argv
	pidfile_write

	mkfifo [infifoname $pid]
	mkfifo [outfifoname $pid]
}

proc mkfifo {f} {
	if [file exists $f] {
		say "uh, fifo already exists?"
		return
	}

	if 0==[catch {exec mkfifo $f}] return		;# POSIX
	if 0==[catch {exec mknod $f p}] return
	# some systems put mknod in wierd places
	if 0==[catch {exec /usr/etc/mknod $f p}] return	;# Sun
	if 0==[catch {exec /etc/mknod $f p}] return	;# AIX, Cray
	puts "Couldn't figure out how to make a fifo - where is mknod?"
	exit
}

proc child {argdate argv} {
	global catflags infifosuffix outfifosuffix

	disconnect

	# these are backwards from the child's point of view so that
	# we can make everything else look "right"
	set  infifosuffix ".o"
	set outfifosuffix ".i"
	set pid 0

	eval spawn $argv
	set proc_spawn_id $spawn_id

	while {1} {
		say "opening [infifoname $pid] for read"

	 	spawn -open [open "|cat $catflags < [infifoname $pid]" "r"]


		set in $spawn_id

		say "opening [outfifoname $pid] for write"
		spawn -open [open [outfifoname $pid] w]
		set out $spawn_id

		fifo_pair_remove $pid

		say "interacting"
		interact {
			-u $proc_spawn_id eof exit
			-output $out
			-input $in
		}

		# parent has closed connection
		say "parent closed connection"
		catch {close -i $in}
		catch {wait -i $in}
		catch {close -i $out}
		catch {wait -i $out}

		# switch to using real pid
		set pid [pid]
		# put entry back
		fifo_pair_create $pid $argdate $argv
	}
}

proc say {msg} {
	global debug_flag

	if !$debug_flag return

	if [catch {puts "parent: $msg"}] {
		send_log "child: $msg\n"
	}
}

proc escape {} {
	# export process handles so that user can get at them
	global in out

	puts "\nto disconnect, enter: exit (or ^D)"
	puts "to suspend, press appropriate job control sequence"
	puts "to return to process, enter: return"
	interpreter
	puts "returning ..."
}

# interactively query user to choose process, return pid
proc choose {} {
	global index date

	while 1 {
		send_user "enter # or pid: "
		expect_user -re "(.*)\n" {set buf $expect_out(1,string)}
		if [info exists index($buf)] {
			set pid $index($buf)
		} elseif [info exists date($buf)] {
			set pid $buf
		} else {
			puts "no such # or pid"
			continue
		}
		return $pid
	}
}

if {$argc} {
	# initial creation occurs before fork because if we do it after
	# then either the child or the parent may have to spin retrying
	# the fifo open.  Unfortunately, we cannot know the pid ahead of
	# time so use "0".  This will be set to the real pid when the
	# parent does its initial disconnect.  There is no collision
	# problem because the fifos are deleted immediately anyway.

	set datearg [exec date]

	fifo_pair_create 0 $datearg $argv




	set pid [fork]
	say "after fork, pid = $pid"
	if $pid==0 {
		child $datearg $argv
	}

	# parent thinks of child as pid==0 for reason given earlier
	set pid 0
}

say "examining pid"

if ![info exists pid] {
	global fifos date proc

	say "pid does not exist"

	pidfile_read

	set count 0
	foreach pid [array names date] {
		incr count
	}

	if $count==0 {
		puts "no connectable processes"
		exit
	} elseif $count==1 {
		puts "one connectable process: $proc($pid)"
		puts "pid $pid, started $date($pid)"
		send_user "connect? \[y] "
		expect_user -re "(.*)\n" {set buf $expect_out(1,string)}
		if {$buf!="y" && $buf!=""} exit
	} else {
		puts "connectable processes:"
		set count 1
		puts " #   pid      date started      process"
		foreach pid [array names date] {
			puts [format "%2d %6d  %.19s  %s" \
				$count $pid $date($pid) $proc($pid)]
			set index($count) $pid
			incr count
		}
		set pid [choose]
	}
}

say "opening [outfifoname $pid] for write"
spawn -noecho -open [open [outfifoname $pid] w]
set out $spawn_id

say "opening [infifoname $pid] for read"
spawn -noecho -open [open "|cat $catflags < [infifoname $pid]" "r"]


set in $spawn_id

puts "Escape sequence is $escape_printable"

proc prompt1 {} {
	global argv0

	return "$argv0[history nextid]> "





}

interact {
	-reset $escape escape
	-output $out
	-input $in
}










|
|

|















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|









<
<
|



|
<
<



<
<
|

|
|


|





>
>
>
>
>
>
>
>



|

>
|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|



|

|

|
|
|
|
|
|



|

|
|
|

|



|

|
|
|
|

|
|



|
|
|
|

|
|
|
|
|
|
|



|

|
<
|
|
|
|
|

|
|

|
|
>
|
>
>
|

|
|
|

|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
<
<
<
<
<
<
<
<
<
<



|
|

|
|
|
|
|




<
<
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|

|
>
|

>
>
>
|
|
|
|
|
>
|
|




|
|

|

|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







|
>
>





|
|
|
>
>
>
>
>



|
|
|


>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55


56
57
58
59
60


61
62
63


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226










227
228
229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#!../expect --
# dislocate - allow disconnection and reconnection to a background program
# Author: Don Libes, NIST

exp_version -exit 5.1

# The following code attempts to intuit whether cat buffers by default.
# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems.
if {[file exists $exp_exec_library/cat-buffers]} {
    set catflags "-u"
} else {
    set catflags ""
}
# If this fails, you can also force it by commenting in one of the following.
# Or, you can use the -catu flag to the script.
#set catflags ""
#set catflags "-u"

set escape \035			;# control-right-bracket
set escape_printable "^\]"

set pidfile "~/.dislocate"
set prefix "disc"
set timeout -1
set debug_flag 0

while {$argc} {
    set flag [lindex $argv 0]
    switch -- $flag \
	    "-catu" {
	set catflags "-u"
	set argv [lrange $argv 1 end]
	incr argc -1
    } "-escape" {
	set escape [lindex $argv 1]
	set escape_printable $escape
	set argv [lrange $argv 2 end]
	incr argc -2
    } "-debug" {
	log_file [lindex $argv 1]
	set debug_flag 1
	set argv [lrange $argv 2 end]
	incr argc -2
    } default {
	break
    }
}

# These are correct from parent's point of view.
# In child, we will reset these so that they appear backwards
# thus allowing following two routines to be used by both parent and child
set  infifosuffix ".i"
set outfifosuffix ".o"

proc infifoname {pid} {


    return "/tmp/$::prefix$pid$::infifosuffix"
}

proc outfifoname {pid} {
    return "/tmp/$::prefix$pid$::outfifosuffix"


}

proc pid_remove {pid} {


    say "removing $pid $::proc($pid)"

    unset ::date($pid)
    unset ::proc($pid)
}

# lines in data file look like this:
# pid#date-started#argv

# allow element lookups on empty arrays
set date(dummy) dummy;	unset date(dummy)
set proc(dummy) dummy;	unset proc(dummy)

proc say {msg} {
    if {!$::debug_flag} return

    if {[catch {puts "parent: $msg"}]} {
	send_log "child: $msg\n"
    }
}

# load pidfile into memory
proc pidfile_read {} {
    global date proc pidfile

    say "opening $pidfile"
    if {[catch {open $pidfile} fp]} return

    #
    # read info from file
    #

    say "reading pidfile"
    set line 0
    while {[gets $fp buf]!=-1} {
	# while pid and date can't have # in it, proc can
	if {[regexp "(\[^#]*)#(\[^#]*)#(.*)" $buf junk pid xdate xproc]} {
	    set date($pid) $xdate
	    set proc($pid) $xproc
	} else {
	    puts "warning: inconsistency in $pidfile line $line"
	}
	incr line
    }
    close $fp
    say "read $line entries"

    #
    # see if pids and fifos are still around
    #

    foreach pid [array names date] {
	if {$pid && [catch {exec /bin/kill -0 $pid}]} {
	    say "$pid no longer exists, removing"
	    pid_remove $pid
	    continue
	}

	# pid still there, see if fifos are
	if {![file exists [infifoname $pid]] || ![file exists [outfifoname $pid]]} {
	    say "$pid fifos no longer exists, removing"
	    pid_remove $pid
	    continue
	}
    }
}

proc pidfile_write {} {
    global pidfile date proc

    say "writing pidfile"

    set fp [open $pidfile w]
    foreach pid [array names date] {
	puts $fp "$pid#$date($pid)#$proc($pid)"
	say "wrote $pid#$date($pid)#$proc($pid)"
    }
    close $fp
}

proc fifo_pair_remove {pid} {
    global date proc prefix

    pidfile_read
    pid_remove $pid
    pidfile_write

    file delete -force [infifoname $pid] [outfifoname $pid]
}

proc fifo_pair_create {pid argdate argv} {
    global prefix date proc

    pidfile_read
    set date($pid) $argdate
    set proc($pid) $argv
    pidfile_write

    mkfifo [infifoname $pid]
    mkfifo [outfifoname $pid]
}

proc mkfifo {f} {
    if {[file exists $f]} {
	say "uh, fifo already exists?"
	return
    }

    if {0==[catch {exec mkfifo $f}]} return		;# POSIX
    if {0==[catch {exec mknod $f p}]} return
    # some systems put mknod in wierd places
    if {0==[catch {exec /usr/etc/mknod $f p}]} return	;# Sun
    if {0==[catch {exec /etc/mknod $f p}]} return	;# AIX, Cray
    puts "Couldn't figure out how to make a fifo - where is mknod?"
    exit
}

proc child {argdate argv} {
    global infifosuffix outfifosuffix

    disconnect

    # these are backwards from the child's point of view so that
    # we can make everything else look "right"
    set  infifosuffix ".o"
    set outfifosuffix ".i"
    set pid 0

    eval spawn $argv
    set proc_spawn_id $spawn_id

    while {1} {
	say "opening [infifoname $pid] for read"
	
	set catfid [open "|cat $::catflags < [infifoname $pid]" "r"]
	set ::catpid $catfid
	spawn -open $catfid
	set in $spawn_id

	say "opening [outfifoname $pid] for write"
	spawn -open [open [outfifoname $pid] w]
	set out $spawn_id

	fifo_pair_remove $pid

	say "interacting"
	interact {
	    -u $proc_spawn_id eof exit
	    -output $out
	    -input $in
	}

	# parent has closed connection
	say "parent closed connection"
	catch {close -i $in}
	catch {wait -i $in}
	catch {close -i $out}
	catch {wait -i $out}

	# switch to using real pid
	set pid [pid]
	# put entry back
	fifo_pair_create $pid $argdate $argv
    }










}

proc escape {} {
    # export process handles so that user can get at them
    global in out

    puts "\nto disconnect, enter: exit (or ^D)"
    puts "to suspend, press appropriate job control sequence"
    puts "to return to process, enter: return"
    interpreter -eof exit
    puts "returning ..."
}

# interactively query user to choose process, return pid
proc choose {} {


    while {1} {
	send_user "enter # or pid: "
	expect_user -re "(.*)\n" {set buf $expect_out(1,string)}
	if {[info exists ::index($buf)]} {
	    set pid $::index($buf)
	} elseif {[info exists ::date($buf)]} {
	    set pid $buf
	} else {
	    puts "no such # or pid"
	    continue
	}
	return $pid
    }
}

if {$argc} {
    # initial creation occurs before fork because if we do it after
    # then either the child or the parent may have to spin retrying
    # the fifo open.  Unfortunately, we cannot know the pid ahead of
    # time so use "0".  This will be set to the real pid when the
    # parent does its initial disconnect.  There is no collision
    # problem because the fifos are deleted immediately anyway.

    set datearg [clock format [clock seconds]]

    fifo_pair_create 0 $datearg $argv

    # to debug by faking child, comment out fork and set pid to a
    # non-zero int, then you can read/write to pipes manually

    set pid [fork]
    say "after fork, pid = $pid"
    if {$pid==0} {
	child $datearg $argv
    }

    # parent thinks of child as pid==0 for reason given earlier
    set pid 0
}

say "examining pid"

if {![info exists pid]} {
    global fifos date proc

    say "pid does not exist"

    pidfile_read

    set count 0
    foreach pid [array names date] {
	incr count
    }

    if {$count==0} {
	puts "no connectable processes"
	exit
    } elseif {$count==1} {
	puts "one connectable process: $proc($pid)"
	puts "pid $pid, started $date($pid)"
	send_user "connect? \[y] "
	expect_user -re "(.*)\n" {set buf $expect_out(1,string)}
	if {$buf!="y" && $buf!=""} exit
    } else {
	puts "connectable processes:"
	set count 1
	puts " #   pid      date started      process"
	foreach pid [array names date] {
	    puts [format "%2d %6d  %.19s  %s" \
		    $count $pid $date($pid) $proc($pid)]
	    set index($count) $pid
	    incr count
	}
	set pid [choose]
    }
}

say "opening [outfifoname $pid] for write"
spawn -noecho -open [open [outfifoname $pid] w]
set out $spawn_id

say "opening [infifoname $pid] for read"
set catfid [open "|cat $catflags < [infifoname $pid]" "r"]
set catpid [pid $catfid]
spawn -noecho -open $catfid
set in $spawn_id

puts "Escape sequence is $escape_printable"

proc prompt1 {} {
    return "$::argv0[history nextid]> "
}

rename exit exitReal

proc exit {} {
    exec /bin/kill $::catpid
    exitReal
}

interact {
    -reset $escape escape
    -output $out
    -input $in
}


Changes to example/dvorak.

22
23
24
25
26
27
28
29
log_user 0
spawn $env(SHELL)
log_user 1
send_user "~d for dvorak input\n"
send_user "~q for qwerty input (default)\n"
send_user "~e for expect interpreter\n"
send_user "Enter ~ sequences using qwerty keys\n"
interact ~d rot ~q {} ~e







|
22
23
24
25
26
27
28
29
log_user 0
spawn $env(SHELL)
log_user 1
send_user "~d for dvorak input\n"
send_user "~q for qwerty input (default)\n"
send_user "~e for expect interpreter\n"
send_user "Enter ~ sequences using qwerty keys\n"
interact ~d rot ~q {} ~e {interpreter -eof exit}

Changes to example/ftp-inband.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

set timeout -1
set verbose_flag 0

proc send_verbose {msg} {
	global verbose_flag

	if $verbose_flag {
		send_user $msg
	}
}

proc get {infile outfile} {
	global prompt verbose_flag

	if (!$verbose_flag) {
		log_user 0
	}

	send_verbose "disabling echo: "
	send "stty -echo\r"
	expect -re $prompt








|







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

set timeout -1
set verbose_flag 0

proc send_verbose {msg} {
	global verbose_flag

	if {$verbose_flag} {
		send_user $msg
	}
}

proc get {infile outfile} {
	global prompt verbose_flag

	if {!$verbose_flag} {
		log_user 0
	}

	send_verbose "disabling echo: "
	send "stty -echo\r"
	expect -re $prompt

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
		} -re "^(\[^\r]*)\r\n" {
			puts $out $expect_out(1,string)
			send_verbose "."
			exp_continue
		}
	}

	if ($verbose_flag) {
		send_user "\n"		;# after last "."
		log_user 1
	}

	expect -re $prompt			;# wait for prompt from cat

	send_verbose "deleting temporary files\n"
	send "rm -f $infile_compressed $infile_encoded\r"
	expect -re $prompt

	send_verbose "switching attention to local system\nuudecoding\n"
	exec uudecode $outfile_encoded

	send_verbose "uncompressing\n"
	exec uncompress -f $outfile_compressed

	send_verbose "renaming\n"
	if [catch "exec cp $outfile_plain $outfile" msg] {
		send_user "could not move file in place, reason: $msg\n"
		send_user "left as $outfile_plain\n"
		exec rm -f $outfile_encoded
	} else {
		exec rm -f $outfile_plain $outfile_encoded
	}

	# restore echo and serendipitously reprompt
	send "stty echo\r"

	log_user 1
}	

proc put {infile outfile} {
	global prompt verbose_flag

	if (!$verbose_flag) {
		log_user 0
	}

	send_verbose "disabling echo: "
	send "stty -echo\r"
	expect -re $prompt








|

















|
















|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
		} -re "^(\[^\r]*)\r\n" {
			puts $out $expect_out(1,string)
			send_verbose "."
			exp_continue
		}
	}

	if {$verbose_flag} {
		send_user "\n"		;# after last "."
		log_user 1
	}

	expect -re $prompt			;# wait for prompt from cat

	send_verbose "deleting temporary files\n"
	send "rm -f $infile_compressed $infile_encoded\r"
	expect -re $prompt

	send_verbose "switching attention to local system\nuudecoding\n"
	exec uudecode $outfile_encoded

	send_verbose "uncompressing\n"
	exec uncompress -f $outfile_compressed

	send_verbose "renaming\n"
	if {[catch "exec cp $outfile_plain $outfile" msg]} {
		send_user "could not move file in place, reason: $msg\n"
		send_user "left as $outfile_plain\n"
		exec rm -f $outfile_encoded
	} else {
		exec rm -f $outfile_plain $outfile_encoded
	}

	# restore echo and serendipitously reprompt
	send "stty echo\r"

	log_user 1
}	

proc put {infile outfile} {
	global prompt verbose_flag

	if {!$verbose_flag} {
		log_user 0
	}

	send_verbose "disabling echo: "
	send "stty -echo\r"
	expect -re $prompt

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

	send_verbose "copying\n"
	send "cat > $outfile_encoded\r"

	log_user 0

	set fp [open $infile_encoded r]
	while 1 {
		if {-1 == [gets $fp buf]} break
		send_verbose "."
		send "$buf\r"
	}

	if ($verbose_flag) {
		send_user "\n"			;# after last "."
		log_user 1
	}

	send "\004"				;# eof
	close $fp








|


|


|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

	send_verbose "copying\n"
	send "cat > $outfile_encoded\r"

	log_user 0

	set fp [open $infile_encoded r]
	while {1} {
		if {-1 == [gets $fp buf]} break
		send_verbose "."
		send -- "$buf\r"
	}

	if {$verbose_flag} {
		send_user "\n"			;# after last "."
		log_user 1
	}

	send "\004"				;# eof
	close $fp

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
	set verbose_flag [expr !$verbose_flag]
	send_user "verbose [verbose_status]\r\n"
}

proc verbose_status {} {
	global verbose_flag

	if $verbose_flag {
		return "on"
	} else {
		return "off"
	}
}

proc cmd {} {







|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
	set verbose_flag [expr !$verbose_flag]
	send_user "verbose [verbose_status]\r\n"
}

proc verbose_status {} {
	global verbose_flag

	if {$verbose_flag} {
		return "on"
	} else {
		return "off"
	}
}

proc cmd {} {

Changes to example/ftp-rfc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!../expect --

# ftp-rfc <rfc-number>
# ftp-rfc -index

# retrieves an rfc (or the index) from uunet

exp_version -exit 5.0

if $argc!=1 {
	send_user "usage: ftp-rfc \[#] \[-index]\n"
	exit
}

set file "rfc$argv.Z"

set timeout 60









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!../expect --

# ftp-rfc <rfc-number>
# ftp-rfc -index

# retrieves an rfc (or the index) from uunet

exp_version -exit 5.0

if {$argc!=1} {
	send_user "usage: ftp-rfc \[#] \[-index]\n"
	exit
}

set file "rfc$argv.Z"

set timeout 60

Changes to example/gethostbyaddr.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	send_user "  -r    reverse back to IP addr for verification  true\n"
	send_user "  -n    query nic                                 true\n"
	send_user "  -d    produce debugging output                  false\n"
	send_user "options must be separate.\n"
	exit
}

if [file readable ~/.gethostbyaddr] {source ~/.gethostbyaddr}

while {[llength $argv]>0} {
	set flag [lindex $argv 0]
	switch -- $flag \
	"-v" {
		set verbose [expr !$verbose]
		set argv [lrange $argv 1 end]







|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	send_user "  -r    reverse back to IP addr for verification  true\n"
	send_user "  -n    query nic                                 true\n"
	send_user "  -d    produce debugging output                  false\n"
	send_user "options must be separate.\n"
	exit
}

if {[file readable ~/.gethostbyaddr]} {source ~/.gethostbyaddr}

while {[llength $argv]>0} {
	set flag [lindex $argv 0]
	switch -- $flag \
	"-v" {
		set verbose [expr !$verbose]
		set argv [lrange $argv 1 end]
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	} default {
		break
	}
}

set IPaddress $argv

if [llength $argv]!=1 usage
if 4!=[scan $IPaddress "%d.%d.%d.%d" a b c d] usage

proc vprint {s} {
	global verbose

	if !$verbose return
	send_user $s\n
}

# dn==1 if domain name, 0 if text (from nic)
proc printhost {name how dn} {
	global reverse tag IPaddress

	if {$dn && $reverse} {
		set verified [verify $name $IPaddress]
	} else {set verified 0}

	if {$verified || !$reverse || !$dn} {
		if $tag {
			send_user "$name ($how)\n"
		} else {
			send_user "$name\n"
		}
		
		if {$verified || !$reverse} {
			close







|
|




|












|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
	} default {
		break
	}
}

set IPaddress $argv

if {[llength $argv]!=1} usage
if {4!=[scan $IPaddress "%d.%d.%d.%d" a b c d]} usage

proc vprint {s} {
	global verbose

	if {!$verbose} return
	send_user $s\n
}

# dn==1 if domain name, 0 if text (from nic)
proc printhost {name how dn} {
	global reverse tag IPaddress

	if {$dn && $reverse} {
		set verified [verify $name $IPaddress]
	} else {set verified 0}

	if {$verified || !$reverse || !$dn} {
		if {$tag} {
			send_user "$name ($how)\n"
		} else {
			send_user "$name\n"
		}
		
		if {$verified || !$reverse} {
			close
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	expect {
	 	-re "\\*\\*\\* (\[^\r]*)\r" {
			vprint $expect_out(1,string)
		} timeout {
			vprint "timed out"
		} -re "Address:.*Address:  (\[^\r]*)\r" {
			set addr2 $expect_out(1,string)
			if [string match $IPaddress $addr2] {
				vprint "verified"
				set rc 1
			} else {
				vprint "not verified - $name is $addr2"
			}
		}
	}







|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	expect {
	 	-re "\\*\\*\\* (\[^\r]*)\r" {
			vprint $expect_out(1,string)
		} timeout {
			vprint "timed out"
		} -re "Address:.*Address:  (\[^\r]*)\r" {
			set addr2 $expect_out(1,string)
			if {[string match $IPaddress $addr2]} {
				vprint "verified"
				set rc 1
			} else {
				vprint "not verified - $name is $addr2"
			}
		}
	}
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
proc telnet_error {s} {
	regexp ": (.*)\r" $s dontcare msg
	vprint $msg
}

proc guessHost {guess} {
	global guessHost
	if [info exists guessHost] return
	set guessHost $guess
}

proc guessDomain {guess} {
	global guessDomain
	if [info exists guessDomain] return
	set guessDomain $guess
}

proc guessFQDN {} {
	global guessHost guessDomain
	return $guessHost.$guessDomain
}







|





|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
proc telnet_error {s} {
	regexp ": (.*)\r" $s dontcare msg
	vprint $msg
}

proc guessHost {guess} {
	global guessHost
	if {[info exists guessHost]} return
	set guessHost $guess
}

proc guessDomain {guess} {
	global guessDomain
	if {[info exists guessDomain]} return
	set guessDomain $guess
}

proc guessFQDN {} {
	global guessHost guessDomain
	return $guessHost.$guessDomain
}
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		vprint "timed out"
	} -re "\n220 (\[^\\. ]*).?(\[^ ]*)" {
		set host $expect_out(1,string)
		set domain $expect_out(2,string)
		printhost $host.$domain smtp 1

		# if not valid FQDN, it's likely either host or domain
		if [string length $domain] {
		    guessDomain $host.$domain
		} else {
		    guessHost $host
		}
	}
}
catch close







|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		vprint "timed out"
	} -re "\n220 (\[^\\. ]*).?(\[^ ]*)" {
		set host $expect_out(1,string)
		set domain $expect_out(2,string)
		printhost $host.$domain smtp 1

		# if not valid FQDN, it's likely either host or domain
		if {[string length $domain]} {
		    guessDomain $host.$domain
		} else {
		    guessHost $host
		}
	}
}
catch close
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
			set host $expect_out(1,string)
			set domain $expect_out(2,string)
			printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1

			# if not valid FQDN, it's likely either host or domain
			# don't bother recording host since it can't be for
			# original addr.
			if [string length $domain] {
			    guessDomain $host.$domain
			}
		}
	}
	catch close
	wait
}







|







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
			set host $expect_out(1,string)
			set domain $expect_out(2,string)
			printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1

			# if not valid FQDN, it's likely either host or domain
			# don't bother recording host since it can't be for
			# original addr.
			if {[string length $domain]} {
			    guessDomain $host.$domain
			}
		}
	}
	catch close
	wait
}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
			set host $expect_out(1,string)
			set domain $expect_out(2,string)
			printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1

			# if not valid FQDN, it's likely either host or domain
			# don't bother recording host since it can't be for
			# original addr.
			if [string length $domain] {
			    guessDomain $host.$domain
			}
		}
	}
	catch close
	wait
}







|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
			set host $expect_out(1,string)
			set domain $expect_out(2,string)
			printhost $guessHost.$domain "smtp - $a.$b.$c.$i is $host.$domain" 1

			# if not valid FQDN, it's likely either host or domain
			# don't bother recording host since it can't be for
			# original addr.
			if {[string length $domain]} {
			    guessDomain $host.$domain
			}
		}
	}
	catch close
	wait
}

Changes to example/kibitz.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
				;# this must end in "kibitz", but can have
				;# things in front (like directory names).
#set proxy "kibitz"		;# uncomment and set if you want kibitz to use
				;# some other account on remote systems

# The following code attempts to intuit whether cat buffers by default.
# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems.
if [file exists $exp_exec_library/cat-buffers] {
	set catflags "-u"
} else {
	set catflags ""
}
# If this fails, you can also force it by commenting in one of the following.
# Or, you can use the -catu flag to the script.
#set catflags ""
#set catflags "-u"

# Some flags must be passed onto the remote kibitz process.  They are stored







|
|

|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
				;# this must end in "kibitz", but can have
				;# things in front (like directory names).
#set proxy "kibitz"		;# uncomment and set if you want kibitz to use
				;# some other account on remote systems

# The following code attempts to intuit whether cat buffers by default.
# The -u flag is required on HPUX (8 and 9) and IBM AIX (3.2) systems.
if {[file exists $exp_exec_library/cat-buffers]} {
    set catflags "-u"
} else {
    set catflags ""
}
# If this fails, you can also force it by commenting in one of the following.
# Or, you can use the -catu flag to the script.
#set catflags ""
#set catflags "-u"

# Some flags must be passed onto the remote kibitz process.  They are stored
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	exit
}

log_user 0
set timeout -1

set user [lindex $argv 0]
if [string match -r $user] {
	send_user "KRUN"	;# this tells user_number 1 that we're running
				;# and to prepare for possible error messages
	set user_number 3
	# need to check that it exists first!
	set user [lindex $argv 1]
} else {
	set user_number [expr 1+(0==[string first - $user])]







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
	exit
}

log_user 0
set timeout -1

set user [lindex $argv 0]
if {[string match -r $user]} {
	send_user "KRUN"	;# this tells user_number 1 that we're running
				;# and to prepare for possible error messages
	set user_number 3
	# need to check that it exists first!
	set user [lindex $argv 1]
} else {
	set user_number [expr 1+(0==[string first - $user])]
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# return true if x is a prefix of xjunk, given that prefixes are only
# valid at . delimiters
# if !do_if0, skip the whole thing - this is here just to make caller simpler
proc is_prefix {do_if0 x xjunk} {
	if 0!=$do_if0 {return 0}
	set split [split $xjunk .]
	for {set i [expr [llength $split]-1]} {$i>=0} {incr i -1} {
		if [string match $x [join [lrange $split 0 $i] .]] {return 1}
	}
	return 0
}

# get domainname.  Unfortunately, on some systems, domainname(1)
# returns NIS domainname which is not the internet domainname.
proc domainname {} {
	# open pops stack upon failure
	set rc [catch {open /etc/resolv.conf r} file]
	if {$rc==0} {
		while {-1!=[gets $file buf]} {
			if 1==[scan $buf "domain %s" name] {
				close $file
				return $name
			}
		}
		close $file
	}

	# fall back to using domainname
	if {0==[catch {exec domainname} name]} {return $name}

	error "could not figure out domainname"
}

if $user_number==1 {
	if $noproc==0 {
		if [llength $argv]>1 {
			set pid [eval spawn [lrange $argv 1 end]]
		} else {
			# if running as CGI, shell may not be set!
			set shell /bin/sh
			catch {set shell $env(SHELL)}
			set pid [spawn $shell]
		}
		set shell $spawn_id
	}

	# is user2 remote?
	regexp (\[^@\]*)@*(.*) $user ignore tmp host
	set user $tmp
	if ![string match $host ""] {
		set h_rc [catch {exec hostname}	hostname]
		set d_rc [catch domainname 	domainname]

		if {![is_prefix $h_rc $host $hostname]
		 && ![is_prefix $d_rc $host $hostname.$domainname]} {
			set user2_islocal 0
		}
	}

	if !$user2_islocal {
		if $verbose {send_user "connecting to $host\n"}

		if ![info exists proxy] {
			proc whoami {} {
				global env
				if [info exists env(USER)] {return $env(USER)}
				if [info exists env(LOGNAME)] {return $env(LOGNAME)}
				if ![catch {exec whoami} user] {return $user}
				if ![catch {exec logname} user] {return $user}
				# error "can't figure out who you are!"
			}
			set proxy [whoami]
		}
		spawn rlogin $host -l $proxy -8
		set userin $spawn_id
		set userout $spawn_id

		catch {set prompt $env(EXPECT_PROMPT)}

		set timeout 120
		expect {
			assword: {
				stty -echo
				send_user "password (for $proxy) on $host: "
				set old_timeout $timeout; set timeout -1
				expect_user -re "(.*)\n"
				send_user "\n"
				set timeout $old_timeout
				send "$expect_out(1,string)\r"
				# bother resetting echo?
				exp_continue
			} incorrect* {
				send_user "invalid password or account\n"
				exit
			} "TERM = *) " {
				send "\r"
				exp_continue
			} timeout {
				send_user "connection to $host timed out\n"
				exit
			} eof {
				send_user "connection to host failed: $expect_out(buffer)"
				exit
			} -re $prompt
		}
		if $verbose {send_user "starting kibitz on $host\n"}
		# the kill protects user1 from receiving user3's
		# prompt if user2 exits via expect's exit.
		send "$kibitz $kibitz_flags -r $user;kill -9 $$\r"

		expect {
			-re "kibitz $kibitz_flags -r $user.*KRUN" {}
			-re "kibitz $kibitz_flags -r $user.*(kibitz\[^\r\]*)\r" {
				send_user "unable to start kibitz on $host: \"$expect_out(1,string)\"\n"
				send_user "try rlogin by hand followed by \"kibitz $user\"\n"
				exit
			}
			timeout {
				send_user "unable to start kibitz on $host: "
				set expect_out(buffer) "timed out"
				set timeout 0; expect -re .+
				send_user $expect_out(buffer)
				exit
			}
		}
		expect {
			-re ".*\n" {
				# pass back diagnostics
				# should really strip out extra cr
				send_user $expect_out(buffer)
				exp_continue
			}
			KABORT exit
			default exit
			KDATA
		}
	}
}

if $user_number==2 {
	set pid [string trimleft $user -]
}

set local_io [expr ($user_number==3)||$user2_islocal]
if $local_io||($user_number==2) {
	if 0==[info exists pid] {set pid [pid]}

	set userinfile /tmp/exp0.$pid
	set useroutfile /tmp/exp1.$pid
}

proc prompt1 {} {
	return "kibitz[info level].[history nextid]> "
}

set esc_match {}
if {$allow_escape} {
   set esc_match {
      $escape_char {
	send_user "\nto exit kibitz, enter: exit\n"
	send_user "to suspend kibitz, press appropriate job control sequence\n"
	send_user "to return to kibitzing, enter: return\n"
	interpreter
	send_user "returning to kibitz\n"
      }
   }
}

proc prompt1 {} {
	return "kibitz[info level].[history nextid]> "
}

set timeout -1

# kibitzer executes following code
if $user_number==2 {
	# for readability, swap variables
	set tmp $userinfile
	set userinfile $useroutfile
	set useroutfile $tmp

	if ![file readable $userinfile] {
		send_user "Eh?  No one is asking you to kibitz.\n"
		exit -1
	}
 	spawn -open [open "|cat $catflags < $userinfile" "r"]
	set userin $spawn_id

	spawn -open [open $useroutfile w]
	set userout $spawn_id
	# open will hang until other user's cat starts

	stty -echo raw
	if $allow_escape {send_user "Escape sequence is $escape_printable\r\n"}

	# While user is reading message, try to delete other fifo
	catch {exec rm -f $userinfile}

	eval interact $esc_match \
		-output $userout \
		-input $userin

	exit
}

# only user_numbers 1 and 3 execute remaining code

proc abort {} {
	global user_number

	# KABORT tells user_number 1 that user_number 3 has run into problems
	# and is exiting, and diagnostics have been returned already
	if $user_number==3 {send_user KABORT}
	exit
}

if $local_io {
    proc mkfifo {f} {
	if 0==[catch {exec mkfifo $f}] return		;# POSIX
	if 0==[catch {exec mknod $f p}] return
	# some systems put mknod in wierd places
	if 0==[catch {exec /usr/etc/mknod $f p}] return	;# Sun
	if 0==[catch {exec /etc/mknod $f p}] return	;# AIX, Cray
	puts "Couldn't figure out how to make a fifo - where is mknod?"







|







|
|
|
|
|
|
|
|
|
|
|

|
|

|



|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|



|
|

|
|



|
















|





|
|
|
|
|

|
|
|
|
|
|

|
|
|

|
|

|
|

|
|
|

|





<
<
|
|
|
|


|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319


320
321
322
323
324
325
326
327
328
329
330
331
332
333
# return true if x is a prefix of xjunk, given that prefixes are only
# valid at . delimiters
# if !do_if0, skip the whole thing - this is here just to make caller simpler
proc is_prefix {do_if0 x xjunk} {
	if 0!=$do_if0 {return 0}
	set split [split $xjunk .]
	for {set i [expr [llength $split]-1]} {$i>=0} {incr i -1} {
		if {[string match $x [join [lrange $split 0 $i] .]]} {return 1}
	}
	return 0
}

# get domainname.  Unfortunately, on some systems, domainname(1)
# returns NIS domainname which is not the internet domainname.
proc domainname {} {
    # open pops stack upon failure
    set rc [catch {open /etc/resolv.conf r} file]
    if {$rc==0} {
	while {-1!=[gets $file buf]} {
	    if 1==[scan $buf "domain %s" name] {
		close $file
		return $name
	    }
	}
	close $file
    }

    # fall back to using domainname
    if {0==[catch {exec domainname} name]} {return $name}

    error "could not figure out domainname"
}

if $user_number==1 {
    if $noproc==0 {
	if {[llength $argv]>1} {
	    set pid [eval spawn [lrange $argv 1 end]]
	} else {
	    # if running as CGI, shell may not be set!
	    set shell /bin/sh
	    catch {set shell $env(SHELL)}
	    set pid [spawn $shell]
	}
	set shell $spawn_id
    }

    # is user2 remote?
    regexp (\[^@\]*)@*(.*) $user ignore tmp host
    set user $tmp
    if ![string match $host ""] {
	set h_rc [catch {exec hostname}	hostname]
	set d_rc [catch domainname 	domainname]

	if {![is_prefix $h_rc $host $hostname]
	&& ![is_prefix $d_rc $host $hostname.$domainname]} {
	    set user2_islocal 0
	}
    }

    if !$user2_islocal {
	if $verbose {send_user "connecting to $host\n"}

	if ![info exists proxy] {
	    proc whoami {} {
		global env
		if {[info exists env(USER)]} {return $env(USER)}
		if {[info exists env(LOGNAME)]} {return $env(LOGNAME)}
		if {![catch {exec whoami} user]} {return $user}
		if {![catch {exec logname} user]} {return $user}
		# error "can't figure out who you are!"
	    }
	    set proxy [whoami]
	}
	spawn rlogin $host -l $proxy -8
	set userin $spawn_id
	set userout $spawn_id

	catch {set prompt $env(EXPECT_PROMPT)}

	set timeout 120
	expect {
	    assword: {
		stty -echo
		send_user "password (for $proxy) on $host: "
		set old_timeout $timeout; set timeout -1
		expect_user -re "(.*)\n"
		send_user "\n"
		set timeout $old_timeout
		send "$expect_out(1,string)\r"
		# bother resetting echo?
		exp_continue
	    } incorrect* {
		send_user "invalid password or account\n"
		exit
	    } "TERM = *) " {
		send "\r"
		exp_continue
	    } timeout {
		send_user "connection to $host timed out\n"
		exit
	    } eof {
		send_user "connection to host failed: $expect_out(buffer)"
		exit
	    } -re $prompt
	}
	if {$verbose} {send_user "starting kibitz on $host\n"}
	# the kill protects user1 from receiving user3's
	# prompt if user2 exits via expect's exit.
	send "$kibitz $kibitz_flags -r $user;kill -9 $$\r"

	expect {
	    -re "kibitz $kibitz_flags -r $user.*KRUN" {}
	    -re "kibitz $kibitz_flags -r $user.*(kibitz\[^\r\]*)\r" {
		send_user "unable to start kibitz on $host: \"$expect_out(1,string)\"\n"
		send_user "try rlogin by hand followed by \"kibitz $user\"\n"
		exit
	    }
	    timeout {
		send_user "unable to start kibitz on $host: "
		set expect_out(buffer) "timed out"
		set timeout 0; expect -re .+
		send_user $expect_out(buffer)
		exit
	    }
	}
	expect {
	    -re ".*\n" {
		# pass back diagnostics
		# should really strip out extra cr
		send_user $expect_out(buffer)
		exp_continue
	    }
	    KABORT exit
	    default exit
	    KDATA
	}
    }
}

if {$user_number==2} {
    set pid [string trimleft $user -]
}

set local_io [expr ($user_number==3)||$user2_islocal]
if {$local_io||($user_number==2)} {
    if {0==[info exists pid]} {set pid [pid]}

    set userinfile /tmp/exp0.$pid
    set useroutfile /tmp/exp1.$pid
}

proc prompt1 {} {
    return "kibitz[info level].[history nextid]> "
}

set esc_match {}
if {$allow_escape} {
   set esc_match {
      $escape_char {
	send_user "\nto exit kibitz, enter: exit\n"
	send_user "to suspend kibitz, press appropriate job control sequence\n"
	send_user "to return to kibitzing, enter: return\n"
	interpreter
	send_user "returning to kibitz\n"
      }
   }
}

proc prompt1 {} {
    return "kibitz[info level].[history nextid]> "
}

set timeout -1

# kibitzer executes following code
if {$user_number==2} {
    # for readability, swap variables
    set tmp $userinfile
    set userinfile $useroutfile
    set useroutfile $tmp

    if ![file readable $userinfile] {
	send_user "Eh?  No one is asking you to kibitz.\n"
	exit -1
    }
    spawn -open [open "|cat $catflags < $userinfile" "r"]
    set userin $spawn_id

    spawn -open [open $useroutfile w]
    set userout $spawn_id
    # open will hang until other user's cat starts

    stty -echo raw
    if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"}

    # While user is reading message, try to delete other fifo
    catch {exec rm -f $userinfile}

    eval interact $esc_match \
	    -output $userout \
	    -input $userin

    exit
}

# only user_numbers 1 and 3 execute remaining code

proc abort {} {


    # KABORT tells user_number 1 that user_number 3 has run into problems
    # and is exiting, and diagnostics have been returned already
    if {$::user_number==3} {send_user KABORT}
    exit
}

if {$local_io} {
    proc mkfifo {f} {
	if 0==[catch {exec mkfifo $f}] return		;# POSIX
	if 0==[catch {exec mknod $f p}] return
	# some systems put mknod in wierd places
	if 0==[catch {exec /usr/etc/mknod $f p}] return	;# Sun
	if 0==[catch {exec /etc/mknod $f p}] return	;# AIX, Cray
	puts "Couldn't figure out how to make a fifo - where is mknod?"
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399




400
401
402
403
404
405
406

    # create 2 fifos to communicate with other user
    mkfifo $userinfile
    mkfifo $useroutfile
    # make sure other user can access despite umask
    exec chmod 666 $userinfile $useroutfile

    if $verbose {send_user "asking $user to type:  kibitz -$pid\n"}

    # can't use exec since write insists on being run from a tty!
    set rc [catch {
		   system echo "Can we talk?  Run: \"kibitz -$pid\"" | \
			/bin/write $user $tty
		}
	]
    if $rc {rmfifos;abort}

    spawn -open [open $useroutfile w]
    set userout $spawn_id
    # open will hang until other user's cat starts

    spawn -open [open "|cat $catflags < $userinfile" "r"]
    set userin $spawn_id
    catch {exec rm $userinfile}
}

stty -echo raw

if $user_number==3 {
	send_user "KDATA"	;# this tells user_number 1 to send data

	interact {
		-output $userout
		-input $userin eof {
			wait -i $userin
			return -tcl
		} -output $user_spawn_id 
	}
} else {
	if $allow_escape {send_user "Escape sequence is $escape_printable\r\n"}

	if $noproc {
		interact {
			-output $userout
			-input $userin eof {wait -i $userin; return}
			-output $user_spawn_id
		}
	} else {
		eval interact $esc_match {
			-output $shell \
			-input $userin eof {
				wait -i $userin
				close -i $shell
				return
			} -output $shell \




			-input $shell -output "$user_spawn_id $userout"
		}
		wait -i $shell
	}
}

if $local_io rmfifos







|







|












|
|

|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|


|
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

    # create 2 fifos to communicate with other user
    mkfifo $userinfile
    mkfifo $useroutfile
    # make sure other user can access despite umask
    exec chmod 666 $userinfile $useroutfile

    if {$verbose} {send_user "asking $user to type:  kibitz -$pid\n"}

    # can't use exec since write insists on being run from a tty!
    set rc [catch {
		   system echo "Can we talk?  Run: \"kibitz -$pid\"" | \
			/bin/write $user $tty
		}
	]
    if {$rc} {rmfifos;abort}

    spawn -open [open $useroutfile w]
    set userout $spawn_id
    # open will hang until other user's cat starts

    spawn -open [open "|cat $catflags < $userinfile" "r"]
    set userin $spawn_id
    catch {exec rm $userinfile}
}

stty -echo raw

if {$user_number==3} {
    send_user "KDATA"	;# this tells user_number 1 to send data

    interact {
	-output $userout
	-input $userin eof {
	    wait -i $userin
	    return -tcl
	} -output $user_spawn_id 
    }
} else {
    if {$allow_escape} {send_user "Escape sequence is $escape_printable\r\n"}

    if {$noproc} {
	interact {
	    -output $userout
	    -input $userin eof {wait -i $userin; return}
	    -output $user_spawn_id
	}
    } else {
	eval interact $esc_match {
	    -output $shell \
		    -input $userin eof {
		wait -i $userin
		close -i $shell
		return
	    } -output $shell \
		    -input $shell eof {
		close -i $userout
		wait -i $userout
		return
	    } -output "$user_spawn_id $userout"
	}
	wait -i $shell
    }
}

if {$local_io} rmfifos

Changes to example/lpunlock.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

proc usage {} {
	send_user "usage: lpunlock <printer> \[<server>\]\n"
	send_user "example: lpunlock lw-isg durer\n"
	exit
}

if $argc==0 usage
set printer [lindex $argv 0]

set client [exec hostname]

if {$argc == 1} {
	# if no arg2, look in local printcap for info
	spawn ed /etc/printcap
	expect "\n"			;# discard character count
	send "/$printer/\r"
	for {} 1 {} {
		expect -re ".*:rm=(\[^:]*):.*\r\n" {
			set server $expect_out(1,string)
			break
		} "\r\n*\\\r\n" {	;# look at next line of entry
			send "\r"
		} "\r\n*\n" {		;# no more lines of entry - give up
			set server $client







|









|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

proc usage {} {
	send_user "usage: lpunlock <printer> \[<server>\]\n"
	send_user "example: lpunlock lw-isg durer\n"
	exit
}

if {$argc==0} usage
set printer [lindex $argv 0]

set client [exec hostname]

if {$argc == 1} {
	# if no arg2, look in local printcap for info
	spawn ed /etc/printcap
	expect "\n"			;# discard character count
	send "/$printer/\r"
	for {} {1} {} {
		expect -re ".*:rm=(\[^:]*):.*\r\n" {
			set server $expect_out(1,string)
			break
		} "\r\n*\\\r\n" {	;# look at next line of entry
			send "\r"
		} "\r\n*\n" {		;# no more lines of entry - give up
			set server $client

Changes to example/mkpasswd.

1
2
3
4
5
6
7
8
9

10
11
12


13
14
15
16
17
18
19
20
21
22
#!/depot/path/expect --
# mkpasswd - make a password, if username given, set it.
# Author: Don Libes, NIST

# defaults
set length 9
set minnum 2
set minlower 2
set minupper 2

set verbose 0
set distribute 0



if [file executable /bin/yppasswd] {
	set defaultprog /bin/yppasswd
} elseif [file executable /bin/passwd] {
	set defaultprog /bin/passwd
} else {
	set defaultprog passwd
}
set prog $defaultprog

while {[llength $argv]>0} {









>



>
>
|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/depot/path/expect --
# mkpasswd - make a password, if username given, set it.
# Author: Don Libes, NIST

# defaults
set length 9
set minnum 2
set minlower 2
set minupper 2
set minspecial 1
set verbose 0
set distribute 0

if {[file executable /bin/nispasswd]} {
	set defaultprog /bin/nispasswd
} elseif {[file executable /bin/yppasswd]} {
	set defaultprog /bin/yppasswd
} elseif {[file executable /bin/passwd]} {
	set defaultprog /bin/passwd
} else {
	set defaultprog passwd
}
set prog $defaultprog

while {[llength $argv]>0} {
30
31
32
33
34
35
36



37
38
39
40
41
42
43
		set argv [lrange $argv 2 end]
	} "-c" {
		set minlower [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-C" {
		set minupper [lindex $argv 1]
		set argv [lrange $argv 2 end]



	} "-v" {
		set verbose 1
		set argv [lrange $argv 1 end]
	} "-p" {
		set prog [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-2" {







>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
		set argv [lrange $argv 2 end]
	} "-c" {
		set minlower [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-C" {
		set minupper [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-s" {
		set minspecial [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-v" {
		set verbose 1
		set argv [lrange $argv 1 end]
	} "-p" {
		set prog [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} "-2" {
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
if {[llength $argv]} {
	puts "usage: mkpasswd \[args] \[user]"
	puts "  where arguments are:"
	puts "    -l #      (length of password, default = $length)"
	puts "    -d #      (min # of digits, default = $minnum)"
	puts "    -c #      (min # of lowercase chars, default = $minlower)"
	puts "    -C #      (min # of uppercase chars, default = $minupper)"

	puts "    -v        (verbose, show passwd interaction)"
	puts "    -p prog   (program to set password, default = $defaultprog)"
	exit 1
}

if {$minnum + $minlower + $minupper > $length} {
	puts "impossible to generate $length-character password\
		with $minnum numbers, $minlower lowercase letters,\
		and $minupper uppercase letters"

	exit 1
}

# if there is any underspecification, use additional lowercase letters
set minlower [expr $length - ($minnum + $minupper)]

set lpass ""		;# password chars typed by left hand
set rpass ""		;# password chars typed by right hand

# insert char into password at a random position

proc insert {pvar char} {
	upvar $pvar p

	set p [linsert $p [rand [expr 1+[llength $p]]] $char]
}

set _ran [pid]

proc rand {m} {
	global _ran

	set period 259200
	set _ran [expr ($_ran*7141 + 54773) % $period]
	expr int($m*($_ran/double($period)))
}

# choose left or right starting hand
set initially_left [set isleft [rand 2]]

# given a size, distribute between left and right hands
# taking into account where we left off







>





|


|
>




|




|
>

|

|


<
<

<
|
<
<
<







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93


94

95



96
97
98
99
100
101
102
if {[llength $argv]} {
	puts "usage: mkpasswd \[args] \[user]"
	puts "  where arguments are:"
	puts "    -l #      (length of password, default = $length)"
	puts "    -d #      (min # of digits, default = $minnum)"
	puts "    -c #      (min # of lowercase chars, default = $minlower)"
	puts "    -C #      (min # of uppercase chars, default = $minupper)"
	puts "    -s #      (min # of special chars, default = $minspecial)"
	puts "    -v        (verbose, show passwd interaction)"
	puts "    -p prog   (program to set password, default = $defaultprog)"
	exit 1
}

if {$minnum + $minlower + $minupper + $minspecial > $length} {
	puts "impossible to generate $length-character password\
		with $minnum numbers, $minlower lowercase letters,\
		$minupper uppercase letters and\
		$minspecial special characters."
	exit 1
}

# if there is any underspecification, use additional lowercase letters
set minlower [expr {$length - ($minnum + $minupper + $minspecial)}]

set lpass ""		;# password chars typed by left hand
set rpass ""		;# password chars typed by right hand

# insert char into password at a random position, thereby spreading
# the different kinds of characters throughout the password
proc insert {pvar char} {
    upvar $pvar p

    set p [linsert $p [rand [expr {(1+[llength $p])}]] $char]
}



proc rand {m} {

    expr {int($m*rand())}



}

# choose left or right starting hand
set initially_left [set isleft [rand 2]]

# given a size, distribute between left and right hands
# taking into account where we left off
113
114
115
116
117
118
119


120
121
122
123
124


125
126
127
128
129
130


131
132
133
134
135
136
137
}

if {$distribute} {
	set lkeys {q w e r t a s d f g z x c v b}
	set rkeys {y u i o p h j k l n m}
	set lnums {1 2 3 4 5 6}
	set rnums {7 8 9 0}


} else {
	set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set lnums {0 1 2 3 4 5 6 7 8 9}
	set rnums {0 1 2 3 4 5 6 7 8 9}


}

set lkeys_length [llength $lkeys]
set rkeys_length [llength $rkeys]
set lnums_length [llength $lnums]
set rnums_length [llength $rnums]



psplit $minnum left right
for {set i 0} {$i<$left} {incr i} {
	insert lpass [lindex $lnums [rand $lnums_length]]
}
for {set i 0} {$i<$right} {incr i} {
	insert rpass [lindex $rnums [rand $rnums_length]]







>
>





>
>






>
>







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
}

if {$distribute} {
	set lkeys {q w e r t a s d f g z x c v b}
	set rkeys {y u i o p h j k l n m}
	set lnums {1 2 3 4 5 6}
	set rnums {7 8 9 0}
	set lspec {! @ # \$ %}
	set rspec {^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /}
} else {
	set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set lnums {0 1 2 3 4 5 6 7 8 9}
	set rnums {0 1 2 3 4 5 6 7 8 9}
	set lspec {! @ # \$ % ~ ^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /}
	set rspec {! @ # \$ % ~ ^ & * ( ) - = _ + [ ] "{" "}" \\ | ; : ' \" < > , . ? /}
}

set lkeys_length [llength $lkeys]
set rkeys_length [llength $rkeys]
set lnums_length [llength $lnums]
set rnums_length [llength $rnums]
set lspec_length [llength $lspec]
set rspec_length [llength $rspec]

psplit $minnum left right
for {set i 0} {$i<$left} {incr i} {
	insert lpass [lindex $lnums [rand $lnums_length]]
}
for {set i 0} {$i<$right} {incr i} {
	insert rpass [lindex $rnums [rand $rnums_length]]
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

172

173


174
175
176
177
178
179
180
181
psplit $minupper left right
for {set i 0} {$i<$left} {incr i} {
	insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
}
for {set i 0} {$i<$right} {incr i} {
	insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
}

# merge results together
if {$initially_left} {
	regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass
	while {[llength $lpass]} {
		regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
		regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
	}
	if {[llength $rpass]} {
		append password $rpass
	}		
} else {
	regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass
	while {[llength $rpass]} {
		regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
		regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
	}

	if {[llength $lpass]} {

		append password $lpass


	}		
}

if {[info exists user]} {
	if {!$verbose} {
		log_user 0
	}









|
|
<
|
<
<
|
|
|
|
<
<
<
<
<
|
>
|
>
|
>
>
|







157
158
159
160
161
162
163
164
165
166

167


168
169
170
171





172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
psplit $minupper left right
for {set i 0} {$i<$left} {incr i} {
	insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
}
for {set i 0} {$i<$right} {incr i} {
	insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
}

psplit $minspecial left right
for {set i 0} {$i<$left} {incr i} {

	insert lpass [lindex $lspec [rand $lspec_length]]


}
for {set i 0} {$i<$right} {incr i} {
	insert rpass [lindex $rspec [rand $rspec_length]]
}






# merge results together
foreach l $lpass r $rpass {
    if {$initially_left} {
	append password $l $r
    } else {
	append password $r $l
    }
}

if {[info exists user]} {
	if {!$verbose} {
		log_user 0
	}

Changes to example/mkpasswd.man.

52
53
54
55
56
57
58





59
60
61
62
63
64
65
The default is 2.

The
.B \-C
flag defines the minimum number of uppercase alphabetic characters that must be in the password.
The default is 2.






The
.B \-p
flag names a program to set the password.
By default, /etc/yppasswd is used if present, otherwise /bin/passwd is used.

The
.B \-2







>
>
>
>
>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
The default is 2.

The
.B \-C
flag defines the minimum number of uppercase alphabetic characters that must be in the password.
The default is 2.

The
.B \-s
flag defines the minimum number of special characters that must be in the password.
The default is 1.

The
.B \-p
flag names a program to set the password.
By default, /etc/yppasswd is used if present, otherwise /bin/passwd is used.

The
.B \-2

Changes to example/passmass.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59


60
61
62
63

64
65
66
67
68
69
70
71



















72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120




121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172







173


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197

#!../expect --
# passmass: change password on many machines
# Synopsis: passmass host1 host2 host3 ....
# Don Libes - March 11, 1991

# Description: Change passwords on the named machines.
#
# You are prompted for old/new passwords.  (If you are changing root
# passwords and have equivalencing, the old password is not used and may be
# omitted.)
# 
# Additional arguments may be used for fine tuning.  They affect all hosts
# which follow until another argument overrides.
#
#   -user	User whose password will be changed.  By default, the current
#		user is used.
#   -rlogin	Use rlogin to access host.  (default)
#   -slogin	Use slogin to access host.
#   -telnet	Use telnet to access host.
#   -program	Next argument is taken as program to run to set password.
#		Default is "passwd".  Other common choices are "yppasswd" and
#		"set passwd" (e.g., VMS hosts).
#   -prompt	Next argument is taken as a prompt suffix pattern.  This allows
#		the script to know when the shell is prompting.  The default is
#		"# " for root and "% " for non-root accounts.
#   -timeout	Next argument is number of seconds to wait for responses.
#		Default is 30 but some systems can be much slower logging in.

# The best way to run this is to put the command in a one-line shell script
# or alias. (Presumably, the set of hosts and parameters will rarely change.)
# Then run it whenever you want to change your passwords on all the hosts.

exp_version -exit 5.0

if $argc==0 {
	send_user "usage: $argv0 host1 host2 host3 . . .\n"
	exit
}

expect_before -i $user_spawn_id \003 exit

proc badhost {host emsg} {
	global badhosts

	send_user "\r\n\007password not changed on $host - $emsg\n\n"
	if 0==[llength $badhosts] {
		set badhosts $host
	} else {
		set badhosts [concat $badhosts $host]
	}
}

# set defaults
set login "rlogin"
set program "passwd"
set user [exec whoami]


set timeout 1000000
stty -echo


send_user "old password: "
expect_user -re "(.*)\n"
send_user "\n"
set password(old) $expect_out(1,string)

send_user "new password: "
expect_user -re "(.*)\n"
send_user "\n"
set password(new) $expect_out(1,string)
send_user "retype new password: "
expect_user -re "(.*)\n"
set password(newcheck) $expect_out(1,string)
send_user "\n"



















stty echo
trap exit SIGINT

if ![string match $password(new) $password(newcheck)] {
	send_user "mismatch - password unchanged\n"
	exit
}


#send_user "want to see new password you just typed? (y|n) "
#expect_user "*\n"
#
#if [string match "y" [lindex $expect_match 0 c]] {
#	send_user "password is <$password(new)>\nproceed? (y|n) "
#	expect_user "*\n"
#	if ![string match "y" [lindex $expect_match 0 c]] exit
#}

set timeout 30
set badhosts {}
for {set i 0} {$i<$argc} {incr i} {

	set arg [lindex $argv $i]
	switch -- $arg \
		"-user" {
			incr i
			set user [lindex $argv $i]
			continue
		} "-prompt" {
			incr i
			set prompt [lindex $argv $i]
			continue
		} "-rlogin" {
			set login "rlogin"
			continue
		} "-slogin" {
			set login "slogin"
			continue
		} "-telnet" {
			set login "telnet"
			continue
		} "-program" {
			incr i
			set program [lindex $argv $i]
			continue
		} "-timeout" {
			incr i
			set timeout [lindex $argv $i]
			continue




		}

	set host $arg
	if [string match $login "rlogin"] {
		set pid [spawn rlogin $host -l $user]
	} elseif [string match $login "slogin"] {
		set pid [spawn slogin $host -l $user]
	} elseif [string match $login "ssh"] {
		set pid [spawn ssh $host -l $user]
	} else {
		set pid [spawn telnet $host]
		expect -re "(login|Username):.*" {
			send "$user\r"
		}
	}

	if ![info exists prompt] {
		if [string match $user "root"] {
			set prompt "# "
		} else {
			set prompt "(%|\\\$) "
		}
	}

	set logged_in 0
	for {} 1 {} {
		expect "Password*" {
			send "$password(old)\r"
		} eof {
			badhost $host "spawn failed"
			break
		} timeout {
			badhost $host "could not log in (or unrecognized prompt)"
			exec kill $pid
			expect eof
			break
		} -re "incorrect|invalid" {
			badhost $host "bad password or login"
			exec kill $pid
			expect eof
			break
		} -re $prompt {
			set logged_in 1
			break
		}
	}

	if (!$logged_in) {
		wait
		continue
	}








	send "$program\r"


	expect "Old password*" {
		send "$password(old)\r"
		expect "Sorry*" {
			badhost $host "old password is bad?"
			continue
		} "password:"
	} -re "(n|N)ew password:"
	send "$password(new)\r"
	expect -re "not changed|unchanged" {
		badhost $host "new password is bad?"
		continue
	} -re "(password|Verification|Verify|again):.*"
	send "$password(new)\r"
	expect -re "(not changed|incorrect|choose new).*" {
		badhost $host "password is bad?"
		continue
	} -re "$prompt"
	send_user "\n"

	close
	wait
}


if [llength $badhosts] {send_user "\nfailed to set password on $badhosts\n"}








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<



|
|
|





|

|
|
|
|
|
|






>

|

>
>
|
|
|
|
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
|






|








<
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

>
>
>
>
>
>
>

>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|


>
|
>
1
2
3
4
5
6
7




















8



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!../expect --
# passmass: change password on many machines
# Synopsis: passmass host1 host2 host3 ....
# Don Libes - March 11, 1991

# Description: Change passwords on the named machines.
#




















# See passmass.man for further info.




exp_version -exit 5.0

if {$argc==0} {
    send_user "usage: $argv0 host1 host2 host3 . . .\n"
    exit
}

expect_before -i $user_spawn_id \003 exit

proc badhost {host emsg} {
    global badhosts

    send_user "\r\n\007password not changed on $host - $emsg\n\n"
    if {0==[llength $badhosts]} {
	set badhosts $host
    } else {
	set badhosts [concat $badhosts $host]
    }
}

# set defaults
set login "rlogin"
set program "passwd"
set user [exec whoami]
set su 0

set timeout -1
stty -echo

if {!$su} {
    send_user "old password: "
    expect_user -re "(.*)\n"
    send_user "\n"
    set password(old) $expect_out(1,string)
    set password(login) $expect_out(1,string)
    send_user "new password: "
    expect_user -re "(.*)\n"
    send_user "\n"
    set password(new) $expect_out(1,string)
    send_user "retype new password: "
    expect_user -re "(.*)\n"
    set password(newcheck) $expect_out(1,string)
    send_user "\n"
} else {
    send_user "login password: "
    expect_user -re "(.*)\n"
    send_user "\n"
    set password(login) $expect_out(1,string)
    send_user "root password: "
    expect_user -re "(.*)\n"
    send_user "\n"
    set password(old) $expect_out(1,string)
    send_user "new password: "
    expect_user -re "(.*)\n"
    send_user "\n"
    set password(new) $expect_out(1,string)
    send_user "retype new password: "
    expect_user -re "(.*)\n"
    set password(newcheck) $expect_out(1,string)
    send_user "\n"
}

stty echo
trap exit SIGINT

if ![string match $password(new) $password(newcheck)] {
    send_user "mismatch - password unchanged\n"
    exit
}


#send_user "want to see new password you just typed? (y|n) "
#expect_user "*\n"
#
#if {[string match "y" [lindex $expect_match 0 c]]} {
#	send_user "password is <$password(new)>\nproceed? (y|n) "
#	expect_user "*\n"
#	if ![string match "y" [lindex $expect_match 0 c]] exit
#}

set timeout 30
set badhosts {}
for {set i 0} {$i<$argc} {incr i} {

    set arg [lindex $argv $i]
    switch -- $arg "-user" {

	incr i
	set user [lindex $argv $i]
	continue
    } "-prompt" {
	incr i
	set prompt [lindex $argv $i]
	continue
    } "-rlogin" {
	set login "rlogin"
	continue
    } "-slogin" {
	set login "slogin"
	continue
    } "-telnet" {
	set login "telnet"
	continue
    } "-program" {
	incr i
	set program [lindex $argv $i]
	continue
    } "-timeout" {
	incr i
	set timeout [lindex $argv $i]
	continue
    } "-su" {
	incr i
	set su [lindex $argv $i]
	continue
    }

    set host $arg
    if {[string match $login "rlogin"]} {
	set pid [spawn rlogin $host -l $user]
    } elseif {[string match $login "slogin"]} {
	set pid [spawn slogin $host -l $user]
    } elseif {[string match $login "ssh"]} {
	set pid [spawn ssh $host -l $user]
    } else {
	set pid [spawn telnet $host]
	expect -re "(login|Username):.*" {
	    send "$user\r"
	}
    }

    if ![info exists prompt] {
	if {[string match $user "root"]} {
	    set prompt "# "
	} else {
	    set prompt "(%|\\\$|#) "
	}
    }

    set logged_in 0
    while {1} {
	expect "Password*" {
	    send "$password(login)\r"
	} eof {
	    badhost $host "spawn failed"
	    break
	} timeout {
	    badhost $host "could not log in (or unrecognized prompt)"
	    exec kill $pid
	    expect eof
	    break
	} -re "incorrect|invalid" {
	    badhost $host "bad password or login"
	    exec kill $pid
	    expect eof
	    break
	} -re $prompt {
	    set logged_in 1
	    break
	}
    }

    if (!$logged_in) {
	wait
	continue
    }

    if ($su) {
	send "su -\r"
	expect "Password:"
	send "$password(old)\r"
	expect "# "
	send "$program root\r"
    } else {
	send "$program\r"
    }

    expect "Old password*" {
	send "$password(old)\r"
	expect "Sorry*" {
	    badhost $host "old password is bad?"
	    continue
	} "password:"
    } -re "(n|N)ew password:"
    send "$password(new)\r"
    expect -re "not changed|unchanged" {
	badhost $host "new password is bad?"
	continue
    } -re "(password|Verification|Verify|again):.*"
    send "$password(new)\r"
    expect -re "(not changed|incorrect|choose new).*" {
	badhost $host "password is bad?"
	continue
    } -re "$prompt"
    send_user "\n"

    close
    wait
}

if {[llength $badhosts]} {
    send_user "\nfailed to set password on $badhosts\n"
}

Changes to example/passmass.man.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63








64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
.TP 4
-telnet
Use telnet to access host.

.TP 4
-program

Next argument is taken as program to run to set password.  Default is
"passwd".  Other common choices are "yppasswd" and "set passwd" (e.g.,
VMS hosts).  A program name such as "password fred" can be used to
create entries for new accounts (when run as root).

.TP 4
-prompt
Next argument is taken as a prompt suffix pattern.  This allows
the script to know when the shell is prompting.  The default is
"# " for root and "% " for non-root accounts.

.TP 4
-timeout
Next argument is number of seconds to wait for responses.
Default is 30 but some systems can be much slower logging in.









.SH HOW TO USE
The best way to run Passmass is to put the command in a one-line shell
script or alias.  Whenever you get a new account on a new machine, add
the appropriate arguments to the command.  Then run it whenever you
want to change your passwords on all the hosts.

.SH CAVEATS

It should be obvious that using the same password on multiple hosts
carries risks.  In particular, if the password can be stolen, then all
of your accounts are at risk.  Thus, you should not use Passmass in
situations where your password is visible, such as across a network
where hackers are known to eavesdrop.

On the other hand, if you have enough accounts with different
passwords, you may end up writing them down somewhere - and
.I that
can be a security problem.  Funny story: my college roommate had an
11"x13" piece of paper on which he had listed accounts and passwords
all across the Internet.  This was several years worth of careful work







|






|





|


>
>
>
>
>
>
>
>








|
|
|
|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
.TP 4
-telnet
Use telnet to access host.

.TP 4
-program

Next argument is a program to run to set the password.  Default is
"passwd".  Other common choices are "yppasswd" and "set passwd" (e.g.,
VMS hosts).  A program name such as "password fred" can be used to
create entries for new accounts (when run as root).

.TP 4
-prompt
Next argument is a prompt suffix pattern.  This allows
the script to know when the shell is prompting.  The default is
"# " for root and "% " for non-root accounts.

.TP 4
-timeout
Next argument is the number of seconds to wait for responses.
Default is 30 but some systems can be much slower logging in.

.TP 4
-su

Next argument is 1 or 0.  If 1, you are additionally prompted for a
root password which is used to su after logging in.  root's password
is changed rather than the user's.  This is useful for hosts which
do not allow root to log in.

.SH HOW TO USE
The best way to run Passmass is to put the command in a one-line shell
script or alias.  Whenever you get a new account on a new machine, add
the appropriate arguments to the command.  Then run it whenever you
want to change your passwords on all the hosts.

.SH CAVEATS

Using the same password on multiple hosts carries risks.  In
particular, if the password can be stolen, then all of your accounts
are at risk.  Thus, you should not use Passmass in situations where
your password is visible, such as across a network which hackers are
known to eavesdrop.

On the other hand, if you have enough accounts with different
passwords, you may end up writing them down somewhere - and
.I that
can be a security problem.  Funny story: my college roommate had an
11"x13" piece of paper on which he had listed accounts and passwords
all across the Internet.  This was several years worth of careful work

Changes to example/passwd.cgi.

95
96
97
98
99
100
101
102
103
104
105
106
send "$var(new2)\r"
expect -re (.*)\r\n {
	set error $expect_out(1,string)
}
close
wait

if [info exists error] {
	errormsg "$error"
} else {
	successmsg "Password changed successfully."
}







|




95
96
97
98
99
100
101
102
103
104
105
106
send "$var(new2)\r"
expect -re (.*)\r\n {
	set error $expect_out(1,string)
}
close
wait

if {[info exists error]} {
	errormsg "$error"
} else {
	successmsg "Password changed successfully."
}

Changes to example/reprompt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/depot/path/expect --

# Name: reprompt
# Description: reprompt every so often until user enters something
# Usage: reprompt timeout prompt
# Author: Don Libes, NIST

foreach {timeout prompt} $argv {}

send_error $prompt
expect {
	timeout {
		send_error "\nwake up!!\a"
		send_error \n$prompt
		exp_continue
	}
	-re .+ {
		send_user $expect_out(buffer)
	}
}











|
|
|
|
|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/depot/path/expect --

# Name: reprompt
# Description: reprompt every so often until user enters something
# Usage: reprompt timeout prompt
# Author: Don Libes, NIST

foreach {timeout prompt} $argv {}

send_error $prompt
expect {
    timeout {
	send_error "\nwake up!!\a"
	send_error \n$prompt
	exp_continue
    }
    -re .+ {
	send_user $expect_out(buffer)
    }
}

Changes to example/rftp.

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

####################end of documentation###############################

match_max -d 100000		;# max size of a directory listing

# return name of file from one line of directory listing
proc getname {line} {
	# if it's a symbolic link, return local name
	set i [lsearch $line "->"]
	if {-1==$i} {
	     # not a sym link, return last token of line as name
	     return [lindex $line [expr [llength $line]-1]]
	} else {
	     # sym link, return "a" of "a -> b"
	     return [lindex $line [expr $i-1]]
	}
}

proc putfile {name} {
	global current_type default_type
	global binary ascii tenex
	global file_timeout

	switch -- $name	$binary	{set new_type binary} \
			$ascii	{set new_type ascii} \
			$tenex	{set new_type tenex} \
			default	{set new_type $default_type}

	if {$current_type != $new_type} {
		settype $new_type
	}

	set timeout $file_timeout
	send "put $name\r"
	expect timeout {
		send_user "ftp timed out in response to \"put $name\"\n"
		exit
	} "ftp>*"
}

proc getfile {name} {
	global current_type default_type
	global binary ascii tenex
	global file_timeout

	switch -- $name	$binary	{set new_type binary} \
			$ascii	{set new_type ascii} \
			$tenex	{set new_type tenex} \
			default	{set new_type $default_type}

	if {$current_type != $new_type} {
		settype $new_type
	}

	set timeout $file_timeout
	send "get $name\r"
	expect timeout {
		send_user "ftp timed out in response to \"get $name\"\n"
		exit
	} "ftp>*"
}

# returns 1 if successful, 0 otherwise
proc putdirectory {name} {
	send "mkdir $name\r"
	expect "550*denied*ftp>*" {
		send_user "failed to make remote directory $name\n"
		return 0
	} timeout {
		send_user "timed out on make remote directory $name\n"
		return 0
	} -re "(257|550.*exists).*ftp>.*"
	# 550 is returned if directory already exists

	send "cd $name\r"
	expect "550*ftp>*" {
		send_user "failed to cd to remote directory $name\n"
		return 0
	} timeout {
		send_user "timed out on cd to remote directory $name\n"
		return 0
	} -re "2(5|0)0.*ftp>.*"
	# some ftp's return 200, some return 250

	send "lcd $name\r"
	# hard to know what to look for, since my ftp doesn't return status
	# codes.  It is evidentally very locale-dependent.
	# So, assume success.
	expect "ftp>*"
	putcurdirectory
	send "lcd ..\r"
	expect "ftp>*"
	send "cd ..\r"
	expect timeout {
		send_user "failed to cd to remote directory ..\n"
		return 0
	} -re "2(5|0)0.*ftp>.*"

	return 1
}

# returns 1 if successful, 0 otherwise
proc getdirectory {name transfer} {
	send "cd $name\r"
	# this can fail normally if it's a symbolic link, and we are just
	# experimenting
	expect "550*ftp>*" {
		send_user "failed to cd to remote directory $name\n"
		return 0
	} timeout {
		send_user "timed out on cd to remote directory $name\n"
		return 0
	} -re "2(5|0)0.*ftp>.*"
	# some ftp's return 200, some return 250

	if $transfer {
		send "!mkdir $name\r"
		expect "denied*" return timeout return "ftp>"
		send "lcd $name\r"
		# hard to know what to look for, since my ftp doesn't return
		# status codes.  It is evidentally very locale-dependent.
		# So, assume success.
		expect "ftp>*"
	}
	getcurdirectory $transfer
	if $transfer {
		send "lcd ..\r"
		expect "ftp>*"
	}
	send "cd ..\r"
	expect timeout {
		send_user "failed to cd to remote directory ..\n"
		return 0
	} -re "2(5|0)0.*ftp>.*"

	return 1
}

proc putentry {name type} {
	switch -- $type \
	d {
		# directory
		if {$name=="." || $name==".."} return
		putdirectory $name
	} - {
		# file
		putfile $name
	} l {
		# symlink, could be either file or directory
		# first assume it's a directory
		if [putdirectory $name] return
		putfile $name
	} default {
		send_user "can't figure out what $name is, skipping\n"
	}
}

proc getentry {name type transfer} {
	switch -- $type \
	d {
		# directory

		getdirectory $name $transfer
	} - {
		# file
		if !$transfer return
		getfile $name
	} l {
		# symlink, could be either file or directory
		# first assume it's a directory
		if [getdirectory $name $transfer] return
		if !$transfer return
		getfile $name
	} default {
		send_user "can't figure out what $name is, skipping\n"
	}
}

proc putcurdirectory {} {
	send "!/bin/ls -alg\r"
	expect timeout {
		send_user "failed to get directory listing\n"
		return
	} "ftp>*"

	set buf $expect_out(buffer)

	for {} 1 {} {
		# if end of listing, succeeded!
		if 0==[regexp "(\[^\n]*)\n(.*)" $buf dummy line buf] return

		set token [lindex $line 0]
		switch -- $token \
		!/bin/ls {
			# original command
		} total {
			# directory header
		} . {
			# unreadable
		} default {
			# either file or directory
			set name [getname $line]
			set type [string index $line 0]
			putentry $name $type
		}
	}
}


# look at result of "dir".  If transfer==1, get all files and directories
proc getcurdirectory {transfer} {
	send "dir\r"
	expect timeout {
		send_user "failed to get directory listing\n"
		return
	} "ftp>*"

	set buf $expect_out(buffer)

	for {} 1 {} {
		regexp "(\[^\n]*)\n(.*)" $buf dummy line buf

		set token [lindex $line 0]
		switch -- $token \
		dir {
			# original command
		} 200 {
			# command successful
		} 150 {
			# opening data connection
		} total {
			# directory header
		} 226 {
			# transfer complete, succeeded!
			return
		} ftp>* {
			# next prompt, failed!
			return
		} . {
			# unreadable
		} default {
			# either file or directory
			set name [getname $line]
			set type [string index $line 0]
			getentry $name $type $transfer
		}
	}
}

proc settype {t} {
	global current_type

	send "type $t\r"
	set current_type $t
	expect "200*ftp>*"
}

proc final_msg {} {
	# write over the previous prompt with our message
	send_user "\rQuit ftp or cd to another directory and press ~g, ~p, or ~l\n"
	# and then reprompt
	send_user "ftp> "
}

if [file readable ~/.rftprc] {source ~/.rftprc}
set first_time 1

if $argc>1 {
	send_user "usage: rftp [host]
	exit
}

send_user "Once logged in, cd to the directory to be transferred and press:\n"
send_user "~p to put the current directory from the local to the remote host\n"
send_user "~g to get the current directory from the remote host to the local host\n"
send_user "~l to list the current directory from the remote host\n"

if $argc==0 {spawn ftp} else {spawn ftp $argv}
interact -echo ~g {
		if $first_time {
			set first_time 0
			settype $default_type
		}
		getcurdirectory 1
		final_msg
} -echo ~p {
		if $first_time {
			set first_time 0
			settype $default_type
		}
		putcurdirectory
		final_msg
} -echo ~l {
		getcurdirectory 0
		final_msg
}







|
|
|
|
|
|
|
|
|



|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|



|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|




|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|




|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|





|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
<
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|

|

|
|
|

|
|
<
|
|
|
|
|
|
|
|
|
|
|
|

<



|
|
|
|
|

|

|
|

|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|

|
|
|



|
|
|
|


|


|
|
|







|

|
|
|
|
|
|

|
|
|
|
|
|

|
|

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

####################end of documentation###############################

match_max -d 100000		;# max size of a directory listing

# return name of file from one line of directory listing
proc getname {line} {
    # if it's a symbolic link, return local name
    set i [lsearch $line "->"]
    if {-1==$i} {
	# not a sym link, return last token of line as name
	return [lindex $line [expr [llength $line]-1]]
    } else {
	# sym link, return "a" of "a -> b"
	return [lindex $line [expr $i-1]]
    }
}

proc putfile {name} {
    global current_type default_type
    global binary ascii tenex
    global file_timeout

    switch -- $name	$binary	{set new_type binary} \
	      $ascii	{set new_type ascii} \
	      $tenex	{set new_type tenex} \
	      default	{set new_type $default_type}

    if {$current_type != $new_type} {
	settype $new_type
    }

    set timeout $file_timeout
    send "put $name\r"
    expect timeout {
	send_user "ftp timed out in response to \"put $name\"\n"
	exit
    } "ftp>*"
}

proc getfile {name} {
    global current_type default_type
    global binary ascii tenex
    global file_timeout

    switch -- $name	$binary	{set new_type binary} \
	      $ascii	{set new_type ascii} \
	      $tenex	{set new_type tenex} \
	      default	{set new_type $default_type}

    if {$current_type != $new_type} {
	settype $new_type
    }

    set timeout $file_timeout
    send "get $name\r"
    expect timeout {
	send_user "ftp timed out in response to \"get $name\"\n"
	exit
    } "ftp>*"
}

# returns 1 if successful, 0 otherwise
proc putdirectory {name} {
    send "mkdir $name\r"
    expect "550*denied*ftp>*" {
	send_user "failed to make remote directory $name\n"
	return 0
    } timeout {
	send_user "timed out on make remote directory $name\n"
	return 0
    } -re "(257|550.*exists).*ftp>.*"
    # 550 is returned if directory already exists

    send "cd $name\r"
    expect "550*ftp>*" {
	send_user "failed to cd to remote directory $name\n"
	return 0
    } timeout {
	send_user "timed out on cd to remote directory $name\n"
	return 0
    } -re "2(5|0)0.*ftp>.*"
    # some ftp's return 200, some return 250

    send "lcd $name\r"
    # hard to know what to look for, since my ftp doesn't return status
    # codes.  It is evidentally very locale-dependent.
    # So, assume success.
    expect "ftp>*"
    putcurdirectory
    send "lcd ..\r"
    expect "ftp>*"
    send "cd ..\r"
    expect timeout {
	send_user "failed to cd to remote directory ..\n"
	return 0
    } -re "2(5|0)0.*ftp>.*"

    return 1
}

# returns 1 if successful, 0 otherwise
proc getdirectory {name transfer} {
    send "cd $name\r"
    # this can fail normally if it's a symbolic link, and we are just
    # experimenting
    expect "550*ftp>*" {
	send_user "failed to cd to remote directory $name\n"
	return 0
    } timeout {
	send_user "timed out on cd to remote directory $name\n"
	return 0
    } -re "2(5|0)0.*ftp>.*"
    # some ftp's return 200, some return 250

    if {$transfer} {
	send "!mkdir $name\r"
	expect "denied*" return timeout return "ftp>"
	send "lcd $name\r"
	# hard to know what to look for, since my ftp doesn't return
	# status codes.  It is evidentally very locale-dependent.
	# So, assume success.
	expect "ftp>*"
    }
    getcurdirectory $transfer
    if {$transfer} {
	send "lcd ..\r"
	expect "ftp>*"
    }
    send "cd ..\r"
    expect timeout {
	send_user "failed to cd to remote directory ..\n"
	return 0
    } -re "2(5|0)0.*ftp>.*"

	return 1
}

proc putentry {name type} {
    switch -- $type d {

	# directory
	if {$name=="." || $name==".."} return
	putdirectory $name
    } - {
	# file
	putfile $name
    } l {
	# symlink, could be either file or directory
	# first assume it's a directory
	if {[putdirectory $name]} return
	putfile $name
    } default {
	send_user "can't figure out what $name is, skipping\n"
    }
}

proc getentry {name type transfer} {
    switch -- $type d {

	# directory
	if {$name=="." || $name==".."} return
	getdirectory $name $transfer
    } - {
	# file
	if {!$transfer} return
	getfile $name
    } l {
	# symlink, could be either file or directory
	# first assume it's a directory
	if {[getdirectory $name $transfer]} return
	if {!$transfer} return
	getfile $name
    } default {
	send_user "can't figure out what $name is, skipping\n"
    }
}

proc putcurdirectory {} {
    send "!/bin/ls -alg\r"
    expect timeout {
	send_user "failed to get directory listing\n"
	return
    } "ftp>*"

    set buf $expect_out(buffer)

    while {1} {
	# if end of listing, succeeded!
	if 0==[regexp "(\[^\n]*)\n(.*)" $buf dummy line buf] return

	set token [lindex $line 0]
	switch -- $token !/bin/ls {

	    # original command
	} total {
	    # directory header
	} . {
	    # unreadable
	} default {
	    # either file or directory
	    set name [getname $line]
	    set type [string index $line 0]
	    putentry $name $type
	}
    }
}


# look at result of "dir".  If transfer==1, get all files and directories
proc getcurdirectory {transfer} {
    send "dir\r"
    expect timeout {
	send_user "failed to get directory listing\n"
	return
    } "ftp>*"

    set buf $expect_out(buffer)

    while {1} {
	regexp "(\[^\n]*)\n(.*)" $buf dummy line buf

	set token [lindex $line 0]
	switch -- $token dir {

	    # original command
	} 200 {
	    # command successful
	} 150 {
	    # opening data connection
	} total {
	    # directory header
	} 226 {
	    # transfer complete, succeeded!
	    return
	} ftp>* {
	    # next prompt, failed!
	    return
	} . {
	    # unreadable
	} default {
	    # either file or directory
	    set name [getname $line]
	    set type [string index $line 0]
	    getentry $name $type $transfer
	}
    }
}

proc settype {t} {
    global current_type

    send "type $t\r"
    set current_type $t
    expect "200*ftp>*"
}

proc final_msg {} {
    # write over the previous prompt with our message
    send_user "\rQuit ftp or cd to another directory and press ~g, ~p, or ~l\n"
    # and then reprompt
    send_user "ftp> "
}

if {[file readable ~/.rftprc]} {source ~/.rftprc}
set first_time 1

if {$argc>1} {
    send_user "usage: rftp [host]"
    exit
}

send_user "Once logged in, cd to the directory to be transferred and press:\n"
send_user "~p to put the current directory from the local to the remote host\n"
send_user "~g to get the current directory from the remote host to the local host\n"
send_user "~l to list the current directory from the remote host\n"

if {$argc==0} {spawn ftp} else {spawn ftp $argv}
interact -echo ~g {
    if {$first_time} {
	set first_time 0
	settype $default_type
    }
    getcurdirectory 1
    final_msg
} -echo ~p {
    if {$first_time} {
	set first_time 0
	settype $default_type
    }
    putcurdirectory
    final_msg
} -echo ~l {
    getcurdirectory 0
    final_msg
}

Changes to example/robohunt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!../expect -f
# Synopsis
#    robohunt player-name [-nodisplay]

# Plays hunt automatically.  Optional "-nodisplay" argument disables output.

# by Don Libes

expect_version -exit 5.0

set timeout 1

proc random {} {
	global ia ic im jran

	set jran [expr ($jran*$ia + $ic) % $im]
	return $jran
}

set ia 7141
set ic 54773
set im 259200
set jran [pid]

# given a direction and number, moves that many spaces in that direction
proc mv {dir num} {
	# first try firing a bullet (what the hell...open some walls to move!)
	send "f"
	for {set i 0} {$i<$num} {incr i} {
		send $dir
	}
}

# move a random distance/direction

# 31 is arbitrarily used as a max distance to move in any one direction
# this is a compromise between long horizontal and vertical moves
# but since excess movement is good for stabbing, this is reasonable
proc move {} {
	set num [random]
	set mask [expr $num&3]
	set num [expr $num&31]
	if $mask==0 {send "H"; mv "h" $num; return}
	if $mask==1 {send "L"; mv "l" $num; return}
	if $mask==2 {send "K"; mv "k" $num; return}
		     send "J"; mv "j" $num; return
}

if 2==$argc { set output 0 } {set output 1}
if 1>$argc  { send_user "usage: robohunt name \[-nodisplay\]\n"; exit}
spawn hunt -b -c -n [lindex $argv 0]
expect "team"
send "\r"

set several_moves 5

expect "Monitor:"
sleep 1
expect ;# flush output
log_user 0
# output is turned off so that we can first strip out ^Gs before they
# are sent to the tty.  It seems to drive xterms crazy - because our
# rather stupid algorithm off not checking after every move can cause
# the game to send a lot of them.

for {} 1 {} {
	# make several moves at a time, before checking to see if we are dead
	# this is a compromise between just ignoring our status after each move
	# and looking at our status after each move
	for {set j $several_moves} {$j} {incr j -1} {
		move
	}

	expect {
		-re ^\007+ {exp_continue}
		-re "\\? " {send y}
		-re .+
	}	
	if $output {send_user -raw $expect_out(buffer)}
}













|
|
|
|









|
|
|
|
|








|
|
|
|
|
|
|


|
|







|







|
|
|
|
|
|
|

|
|
|
|
|
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!../expect -f
# Synopsis
#    robohunt player-name [-nodisplay]

# Plays hunt automatically.  Optional "-nodisplay" argument disables output.

# by Don Libes

expect_version -exit 5.0

set timeout 1

proc random {} {
    global ia ic im jran
    
    set jran [expr ($jran*$ia + $ic) % $im]
    return $jran
}

set ia 7141
set ic 54773
set im 259200
set jran [pid]

# given a direction and number, moves that many spaces in that direction
proc mv {dir num} {
    # first try firing a bullet (what the hell...open some walls to move!)
    send "f"
    for {set i 0} {$i<$num} {incr i} {
	send $dir
    }
}

# move a random distance/direction

# 31 is arbitrarily used as a max distance to move in any one direction
# this is a compromise between long horizontal and vertical moves
# but since excess movement is good for stabbing, this is reasonable
proc move {} {
    set num [random]
    set mask [expr $num&3]
    set num [expr $num&31]
    if $mask==0 {send "H"; mv "h" $num; return}
    if $mask==1 {send "L"; mv "l" $num; return}
    if $mask==2 {send "K"; mv "k" $num; return}
                 send "J"; mv "j" $num; return
}

if {2==$argc} { set output 0 } {set output 1}
if {1>$argc}  { send_user "usage: robohunt name \[-nodisplay\]\n"; exit}
spawn hunt -b -c -n [lindex $argv 0]
expect "team"
send "\r"

set several_moves 5

expect "Monitor:"
after 1000
expect ;# flush output
log_user 0
# output is turned off so that we can first strip out ^Gs before they
# are sent to the tty.  It seems to drive xterms crazy - because our
# rather stupid algorithm off not checking after every move can cause
# the game to send a lot of them.

for {} {1} {} {
    # make several moves at a time, before checking to see if we are dead
    # this is a compromise between just ignoring our status after each move
    # and looking at our status after each move
    for {set j $several_moves} {$j} {incr j -1} {
	move
    }

    expect {
	-re ^\007+ {exp_continue}
	-re "\\? " {send y}
	-re .+
    }	
    if $output {send_user -raw $expect_out(buffer)}
}

Changes to example/rogue.exp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!../expect -f
# Look for a GREAT game of rogue.
# Idea is that any game with a Strength of 18 is unusually good.
# Written by Don Libes - March, 1990

set timeout -1
while {1} {
	spawn rogue
	expect	"Str: 18" break \
		"Str: 16"
	send "Q"
	expect "quit?"
	send "y"
	close
	wait
}
interact







|
|
|
|
|
|
|
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!../expect -f
# Look for a GREAT game of rogue.
# Idea is that any game with a Strength of 18 is unusually good.
# Written by Don Libes - March, 1990

set timeout -1
while {1} {
    spawn rogue
    expect  "Str: 18" break \
	    "Str: 16"
    send "Q"
    expect "quit?"
    send "y"
    close
    wait
}
interact

Changes to example/telnet-in-bg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Start telnet and when you press ^Z, put telnet in background and save any
# remaining output in "telnet.log".  You can actually apply this technique
# to any interactive program - I just chose telnet here.

# Author: Don Libes, NIST, 1/5/95

spawn -ignore HUP telnet $argv		;# start telnet
interact \032 return			;# interact until ^Z

if [fork] exit				;# disconnect from terminal
disconnect

set log [open logfile w]		;# open logfile
expect -re .+ {				;# and record everything to it
	puts -nonewline $log $expect_out(buffer)
	exp_continue
}









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Start telnet and when you press ^Z, put telnet in background and save any
# remaining output in "telnet.log".  You can actually apply this technique
# to any interactive program - I just chose telnet here.

# Author: Don Libes, NIST, 1/5/95

spawn -ignore HUP telnet $argv		;# start telnet
interact \032 return			;# interact until ^Z

if {[fork]} exit				;# disconnect from terminal
disconnect

set log [open logfile w]		;# open logfile
expect -re .+ {				;# and record everything to it
	puts -nonewline $log $expect_out(buffer)
	exp_continue
}

Changes to example/term_expect.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122


unset env(DISPLAY)
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if $termcap {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:nd=\E[C:
	:cl=\E[H\E[J:
	:ce=\E[K:
	:do=^J:







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122


unset env(DISPLAY)
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if {$termcap} {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:nd=\E[C:
	:cl=\E[H\E[J:
	:ce=\E[K:
	:do=^J:
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
	:k6=\EOU:
	:k7=\EOV:
	:k8=\EOW:
	:k9=\EOX:
    }
}

if $terminfo {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
	:k6=\EOU:
	:k7=\EOV:
	:k8=\EOW:
	:k9=\EOX:
    }
}

if {$terminfo} {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if $newline {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {







|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if {$newline} {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {

Changes to example/tknewsbiff.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# make sure that when we map it, it will be open (i.e., "normal")
set _window_open 1

# PUBLIC
proc mapwindow {} {
	global _window_open

	if $_window_open {
		wm deiconify .
	} else {
		wm iconify .
	}
}

proc _abort {msg} {
	global argv0

	puts "$argv0: $msg"
	exit 1
}

if [info exists env(DOTDIR)] {
	set home $env(DOTDIR)
} else {
	set home [glob ~]
}

set delay		  60
set width		  27







|













|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# make sure that when we map it, it will be open (i.e., "normal")
set _window_open 1

# PUBLIC
proc mapwindow {} {
	global _window_open

	if {$_window_open} {
		wm deiconify .
	} else {
		wm iconify .
	}
}

proc _abort {msg} {
	global argv0

	puts "$argv0: $msg"
	exit 1
}

if {[info exists env(DOTDIR)]} {
	set home $env(DOTDIR)
} else {
	set home [glob ~]
}

set delay		  60
set width		  27
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
.scrollbar config -highlightthickness 0
pack .scrollbar -side left -fill y
pack .list -side left -fill both -expand 1

while {[llength $argv]>0} {
	set arg [lindex $argv 0]

	if [file readable $arg] {
		if 0==[string compare active [file tail $arg]] {
			set active_file $arg
			set argv [lrange $argv 1 end]
		} else {
			# must be a config file
			set _config_file $arg
			set argv [lrange $argv 1 end]
		}







|
|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
.scrollbar config -highlightthickness 0
pack .scrollbar -side left -fill y
pack .list -side left -fill both -expand 1

while {[llength $argv]>0} {
	set arg [lindex $argv 0]

	if {[file readable $arg]} {
		if {0==[string compare active [file tail $arg]]} {
			set active_file $arg
			set argv [lrange $argv 1 end]
		} else {
			# must be a config file
			set _config_file $arg
			set argv [lrange $argv 1 end]
		}
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
	# remove previous user-provided proc in case user simply
	# deleted it from config file
	proc user {} {}

	set watch_list {}
	set ignore_list {}

	if [file exists $_config_file] {
		# uplevel allows user to set global variables
		if [catch {uplevel source $_config_file} msg] {
			_abort "error reading $_config_file\n$msg"
		}
	}

	if [llength $watch_list]==0 {
		watch *
	}
}

# PUBLIC
proc watch {args} {
	global watch_list







|

|




|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
	# remove previous user-provided proc in case user simply
	# deleted it from config file
	proc user {} {}

	set watch_list {}
	set ignore_list {}

	if {[file exists $_config_file]} {
		# uplevel allows user to set global variables
		if {[catch {uplevel source $_config_file} msg]} {
			_abort "error reading $_config_file\n$msg"
		}
	}

	if {[llength $watch_list]==0} {
		watch *
	}
}

# PUBLIC
proc watch {args} {
	global watch_list
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}

# get time and server
_read_config_file

# if user didn't set newsrc, try ~/.newsrc-server convention.
# if that fails, fall back to just plain ~/.newsrc
if ![info exists newsrc] {
	set newsrc $home/.newsrc-$server
	if ![file readable $newsrc] {
		set newsrc $home/.newsrc
		if ![file readable $newsrc] {
			_abort "cannot tell what newgroups you read
found neither $home/.newsrc-$server nor $home/.newsrc"
		}
	}
}

# PRIVATE
proc _read_newsrc {} {
	global db newsrc

	if [catch {set file [open $newsrc]} msg] {
		_abort $msg
	}
	while {-1 != [gets $file buf]} {
		if [regexp "!" $buf] continue
		if [regexp "(\[^:]*):.*\[-, ](\[0-9]+)" $buf dummy ng seen] {
			set db($ng,seen) $seen
		}
		# only way 2nd regexp can fail is on lines
		# that have a : but no number
	}
	close $file
}

proc _unknown_host {} {
	global server _default_server

	if 0==[string compare $_default_server $server] {
		puts "tknewsbiff: default server <$server> is not known"
	} else {
		puts "tknewsbiff: server <$server> is not known"
	}

	puts "Give tknewsbiff an argument - either the name of your news server
or active file.  I.e.,







|

|

|










|



|
|











|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
}

# get time and server
_read_config_file

# if user didn't set newsrc, try ~/.newsrc-server convention.
# if that fails, fall back to just plain ~/.newsrc
if {![info exists newsrc]} {
	set newsrc $home/.newsrc-$server
	if {![file readable $newsrc]} {
		set newsrc $home/.newsrc
		if {![file readable $newsrc]} {
			_abort "cannot tell what newgroups you read
found neither $home/.newsrc-$server nor $home/.newsrc"
		}
	}
}

# PRIVATE
proc _read_newsrc {} {
	global db newsrc

	if {[catch {set file [open $newsrc]} msg]} {
		_abort $msg
	}
	while {-1 != [gets $file buf]} {
		if {[regexp "!" $buf]} continue
		if {[regexp "(\[^:]*):.*\[-, ](\[0-9]+)" $buf dummy ng seen]} {
			set db($ng,seen) $seen
		}
		# only way 2nd regexp can fail is on lines
		# that have a : but no number
	}
	close $file
}

proc _unknown_host {} {
	global server _default_server

	if {0==[string compare $_default_server $server]} {
		puts "tknewsbiff: default server <$server> is not known"
	} else {
		puts "tknewsbiff: server <$server> is not known"
	}

	puts "Give tknewsbiff an argument - either the name of your news server
or active file.  I.e.,
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# PRIVATE
proc _read_active {} {
	global db server active_list active_file
	upvar #0 server_timeout timeout

	set active_list {}

	if [info exists active_file] {
		spawn -open [open $active_file]
	} else {
		spawn telnet $server nntp
		expect {
			"20*\n" {
				# should get 200 or 201
			} "NNTP server*\n" {







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# PRIVATE
proc _read_active {} {
	global db server active_list active_file
	upvar #0 server_timeout timeout

	set active_list {}

	if {[info exists active_file]} {
		spawn -open [open $active_file]
	} else {
		spawn telnet $server nntp
		expect {
			"20*\n" {
				# should get 200 or 201
			} "NNTP server*\n" {
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# test in various ways for good newsgroups
# return 1 if good, 0 if not good
# PRIVATE
proc _isgood {ng threshold} {
	global db seen_list ignore_list

	# skip if we don't subscribe to it
	if ![info exists db($ng,seen)] {return 0}

	# skip if the threshold isn't exceeded
	if {$db($ng,hi) - $db($ng,seen) < $threshold} {return 0}

	# skip if it matches an ignore command
	foreach igpat $ignore_list {
		if [string match $igpat $ng] {return 0}
	}

	# skip if we've seen it before
	if [lsearch -exact $seen_list $ng]!=-1 {return 0}

	# passed all tests, so remember that we've seen it
	lappend seen_list $ng
	return 1
}

# return 1 if not seen on previous turn
# PRIVATE
proc _isnew {ng} {
	global previous_seen_list

	if [lsearch -exact $previous_seen_list $ng]==-1 {
		return 1
	} else {
		return 0
	}
}

# schedule display of newsgroup in global variable "newsgroup"







|






|



|











|







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# test in various ways for good newsgroups
# return 1 if good, 0 if not good
# PRIVATE
proc _isgood {ng threshold} {
	global db seen_list ignore_list

	# skip if we don't subscribe to it
	if {![info exists db($ng,seen)]} {return 0}

	# skip if the threshold isn't exceeded
	if {$db($ng,hi) - $db($ng,seen) < $threshold} {return 0}

	# skip if it matches an ignore command
	foreach igpat $ignore_list {
		if {[string match $igpat $ng]} {return 0}
	}

	# skip if we've seen it before
	if {[lsearch -exact $seen_list $ng]!=-1} {return 0}

	# passed all tests, so remember that we've seen it
	lappend seen_list $ng
	return 1
}

# return 1 if not seen on previous turn
# PRIVATE
proc _isnew {ng} {
	global previous_seen_list

	if {[lsearch -exact $previous_seen_list $ng]==-1} {
		return 1
	} else {
		return 0
	}
}

# schedule display of newsgroup in global variable "newsgroup"
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
				set watch [lrange $watch 2 end]
			} default {
				_abort "watch: expecting -threshold -display or -new but found: [lindex $watch 0]"
			}
		}

		foreach ng $active_list {
			if [string match $ngpat $ng] {
				if [_isgood $ng $threshold] {
					if [llength $display] {
						set newsgroup $ng
						uplevel $display
					}
					if [_isnew $ng] {
						if [llength $new] {
							set newsgroup $ng
							uplevel $new
						}
					}
				}
			}
		}







|
|
|



|
|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
				set watch [lrange $watch 2 end]
			} default {
				_abort "watch: expecting -threshold -display or -new but found: [lindex $watch 0]"
			}
		}

		foreach ng $active_list {
			if {[string match $ngpat $ng]} {
				if {[_isgood $ng $threshold]} {
					if {[llength $display]} {
						set newsgroup $ng
						uplevel $display
					}
					if {[_isnew $ng]} {
						if {[llength $new]} {
							set newsgroup $ng
							uplevel $new
						}
					}
				}
			}
		}
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
	}

	wm geometry . ${width}x$current_height
	wm maxsize . 999 [llength $display_list]

	_display_ngs $width

	if [string compare [wm state .] withdrawn]==0 {
		mapwindow
	}
}

# actually write all newsgroups to the window
# PRIVATE
proc _display_ngs {width} {







|







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
	}

	wm geometry . ${width}x$current_height
	wm maxsize . 999 [llength $display_list]

	_display_ngs $width

	if {[string compare [wm state .] withdrawn]==0} {
		mapwindow
	}
}

# actually write all newsgroups to the window
# PRIVATE
proc _display_ngs {width} {
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
spawn cat -u; set _cat_spawn_id $spawn_id
set _update_flag 0

# PUBLIC
proc update-now {} {
	global _update_flag _cat_spawn_id

	if $_update_flag return	;# already set, do nothing
	set _update_flag 1

	exp_send -i $_cat_spawn_id "\r"
}

bind .list <1> help
bind .list <2> update-now







|







452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
spawn cat -u; set _cat_spawn_id $spawn_id
set _update_flag 0

# PUBLIC
proc update-now {} {
	global _update_flag _cat_spawn_id

	if {$_update_flag} return	;# already set, do nothing
	set _update_flag 1

	exp_send -i $_cat_spawn_id "\r"
}

bind .list <1> help
bind .list <2> update-now
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515

	set display_list {}
	set seen_list {}

	catch {unset db}
}

for {} 1 {_sleep $delay} {
	_init_ngs

	_read_newsrc
	if [_read_active] continue
	_read_config_file

	_update_ngs
	user
	_update_window
}







|



|






498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515

	set display_list {}
	set seen_list {}

	catch {unset db}
}

for {} {1} {_sleep $delay} {
	_init_ngs

	_read_newsrc
	if {[_read_active]} continue
	_read_config_file

	_update_ngs
	user
	_update_window
}

Changes to example/tkpasswd.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/depot/path/expectk -f
# tkpasswd - Change passwords using Expectk
# Author: Don Libes, NIST, October 1, 1993
# Version: 1.8 - Added support for Tk 4.1

# There is no man page.  However, there is some on-line help when you run
# the program.  Technical details and insights are described in the
# O'Reilly book "Exploring Expect".

proc prog_exists {prog} {
	global env

	foreach dir [split $env(PATH) :] {
		if [file executable $dir/$prog] {
			return 1
		}
	}
	return 0
}

frame .type -relief raised -bd 1

radiobutton .passwd -text passwd -variable passwd_cmd \
		-value {passwd {cat /etc/passwd}} \
		-anchor w -command get_users -relief flat
pack .passwd -in .type -fill x

if [prog_exists yppasswd] {
    radiobutton .yppasswd -text yppasswd -variable passwd_cmd \
		-value {yppasswd {ypcat passwd}} \
		-anchor w -command get_users -relief flat
    pack .yppasswd -in .type -fill x
}

if [prog_exists nispasswd] {
    radiobutton .nispasswd -text nispasswd -variable passwd_cmd \
		-value {nispasswd {niscat passwd}} \
		-anchor w -command get_users -relief flat
    pack .nispasswd -in .type -fill x 
}
pack .type -fill x

frame .sort -relief raised -bd 1
radiobutton .unsorted -text unsorted -variable sort_cmd -value " " \
		-anchor w -relief flat -command get_users
radiobutton .name -text name -variable sort_cmd -value "| sort" \
		-anchor w -relief flat -command get_users
radiobutton .uid -text uid -variable sort_cmd -value "| sort -t: -n +2" \
		 -anchor w -relief flat -command get_users
pack .unsorted .name .uid -in .sort -fill x
pack .sort -fill x

frame .users -relief raised -bd 1
# has to be wide enough for 8+1+5=14
text .names -yscrollcommand ".scroll set" -width 14 -height 1 \
		-font "*-bold-o-normal-*-120-*-m-*" -setgrid 1
.names tag configure nopassword -relief raised
.names tag configure selection -relief raised

set iscolor 0
if {[winfo depth .] > 1} {
	set iscolor 1
}

if {$iscolor} {
	.names tag configure nopassword -background red
	.names tag configure selection -background green
} else {
	.names tag configure nopassword -background  black -foreground white
	.names tag configure selection -background white -foreground black
}
scrollbar .scroll -command ".names yview" -relief raised
pack .scroll -in .users -side left -fill y
pack .names  -in .users -side left -fill y
pack .users -expand 1 -fill y

wm minsize . 14 1










|

|
|
|
|
|
|





|
|


|

|
|



|

|
|






|

|

|






|





|



|
|

|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/depot/path/expectk -f
# tkpasswd - Change passwords using Expectk
# Author: Don Libes, NIST, October 1, 1993
# Version: 1.8 - Added support for Tk 4.1

# There is no man page.  However, there is some on-line help when you run
# the program.  Technical details and insights are described in the
# O'Reilly book "Exploring Expect".

proc prog_exists {prog} {
    global env

    foreach dir [split $env(PATH) :] {
	if {[file executable $dir/$prog]} {
	    return 1
	}
    }
    return 0
}

frame .type -relief raised -bd 1

radiobutton .passwd -text passwd -variable passwd_cmd \
	-value {passwd {cat /etc/passwd}} \
	-anchor w -command get_users -relief flat
pack .passwd -in .type -fill x

if {[prog_exists yppasswd]} {
    radiobutton .yppasswd -text yppasswd -variable passwd_cmd \
	    -value {yppasswd {ypcat passwd}} \
	    -anchor w -command get_users -relief flat
    pack .yppasswd -in .type -fill x
}

if {[prog_exists nispasswd]} {
    radiobutton .nispasswd -text nispasswd -variable passwd_cmd \
	    -value {nispasswd {niscat passwd}} \
	    -anchor w -command get_users -relief flat
    pack .nispasswd -in .type -fill x 
}
pack .type -fill x

frame .sort -relief raised -bd 1
radiobutton .unsorted -text unsorted -variable sort_cmd -value " " \
	-anchor w -relief flat -command get_users
radiobutton .name -text name -variable sort_cmd -value "| sort" \
	-anchor w -relief flat -command get_users
radiobutton .uid -text uid -variable sort_cmd -value "| sort -t: -n +2" \
	-anchor w -relief flat -command get_users
pack .unsorted .name .uid -in .sort -fill x
pack .sort -fill x

frame .users -relief raised -bd 1
# has to be wide enough for 8+1+5=14
text .names -yscrollcommand ".scroll set" -width 14 -height 1 \
	-font "*-bold-o-normal-*-120-*-m-*" -setgrid 1
.names tag configure nopassword -relief raised
.names tag configure selection -relief raised

set iscolor 0
if {[winfo depth .] > 1} {
    set iscolor 1
}

if {$iscolor} {
    .names tag configure nopassword -background red
    .names tag configure selection -background green
} else {
    .names tag configure nopassword -background  black -foreground white
    .names tag configure selection -background white -foreground black
}
scrollbar .scroll -command ".names yview" -relief raised
pack .scroll -in .users -side left -fill y
pack .names  -in .users -side left -fill y
pack .users -expand 1 -fill y

wm minsize . 14 1
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
button .generate_button -text "generate" -command password_generate
pack .prompt .password -in .password_frame -fill x -padx 2 -pady 2
pack .password_set .generate_button -in .password_frame -side left -expand 1 -fill x -padx 2 -pady 2
pack .password_frame -fill x

set dict_loaded 0
checkbutton .dict -text "test dictionary" -variable dict_check \
		-command {if !$dict_loaded load_dict} \
		-anchor w
pack .dict -fill x -padx 2 -pady 2


button .quit -text quit -command exit
button .help_button -text help -command help
pack .quit .help_button -side left -expand 1 -fill x -padx 2 -pady 2

proc help {} {
	if [catch {toplevel .help}] return
	message .help.text -text \
"tkpasswd - written by Don Libes, NIST, 10/1/93.

Click on passwd (local users) or yppasswd (NIS users).\
Select user using mouse (or keys - see below).\
Enter password or press ^G to generate a random password.\
(Press ^A to adjust the generation parameters.)\
Press return to set the password.\
If the dictionary is enabled and the password is in it,\
the password is rejected.

You must be root to set local passwords besides your own.\
If you are not root, you must also enter an old password\
when requested.

You do not have to move mouse into password field(s) to enter password.\
^U clears password field.\
^N and ^P select next/previous user.\
M-n and M-p select next/previous user with no password.\
(Users with no passwords are highlighted.)"

	button .help.ok -text "ok" -command {destroy .help}
	pack .help.text
	pack .help.ok -fill x -padx 2 -pady 2
}

# get list of local users
proc get_users {} {
	global sort_cmd passwd_cmd
	global nopasswords	;# line numbers of entries with no passwords
	global last_line	;# last line of text box
	global selection_line

	.names delete 1.0 end

	set file [open "|[lindex $passwd_cmd 1] $sort_cmd"]
	set last_line 1
	set nopasswords {}
	while {[gets $file buf] != -1} {
		set buf [split $buf :]
		if [llength $buf]>2 {
			# normal password entry
			.names insert end "[format "%-8.8s %5d" [lindex $buf 0] [lindex $buf 2]]\n"
			if 0==[string compare [lindex $buf 1] ""] {
				.names tag add nopassword \
						{end - 2 line linestart} \
						{end - 2 line lineend}
				lappend nopasswords $last_line
			}
		} else {
			# +name style entry
			.names insert end "$buf\n"
		}
		incr last_line
	}
	incr last_line -1
	close $file
	set selection_line 0
}

proc feedback {msg} {
	global password

	set password $msg
	.password select from 0
	.password select to end
	update
}

proc load_dict {} {
	global dict dict_loaded

	feedback "loading dictionary..."

	if 0==[catch {open /usr/dict/words} file] {
		rename set s
		foreach w [split [read $file] "\n"] {s dict($w) ""}
		close $file
		rename s set
		set dict_loaded 1
		feedback "dictionary loaded"
	} else {
		feedback "dictionary missing"
		.dict deselect
	}
}

# put whatever security checks you like in here
proc weak_password {password} {
	global dict dict_check

	if $dict_check {
		feedback "checking password"

		if [info exists dict($password)] {
			feedback "sorry - in dictionary"
			return 1
		}
	}
	return 0
}

proc password_set {} {
	global password passwd_cmd selection_line

	set new_password $password

	if {$selection_line==0} {
		feedback "select a user first"
		return
	}
	set user [lindex [.names get selection.first selection.last] 0]

	if [weak_password $password] return

	feedback "setting password . . ."

	set cmd [lindex $passwd_cmd 0]
	spawn -noecho $cmd $user
	log_user 0
	set last_msg "error in $cmd"
	while 1 {
		expect {
			-nocase "old password:" {
				exp_send "[get_old_password]\r"
			} "assword*:" {
				exp_send "$new_password\r"
			} -re "(.*)\r\n" {
				set last_msg $expect_out(1,string)
			} eof break
		}
	}
	set status [wait]
	if [lindex $status 3]==0 {
		feedback "set successfully"
	} else {
		feedback $last_msg
	}
}

# defaults for generating passwords
set length 9
set minnum 2
set minlower 5
set minupper 2
set distribute 0

proc parameter_filename {} {
	set file .tkpasswd.rc
	if [info exists env(DOTDIR)] {
		set file "$env(DOTDIR)/$file"
	}
	return ~/$file
}

catch {source [parameter_filename]}

# save parameters in a file
proc save_parameters {} {
	global minnum minlower minupper length

	if [catch {open [parameter_filename] w} f] {
		# should never happen, so don't bother with window code
		puts "tkpasswd: could not write [parameter_filename]"
		return
	}
	puts $f "# This is the .tkpasswd.rc file.  Do not edit it by hand as"
	puts $f "# it is automatically maintained by tkpasswd.  Any manual"
	puts $f "# modifications will be lost."
	puts $f ""
	puts $f "set length $length"
	puts $f "set minnum $minnum"
	puts $f "set minupper $minupper"
	puts $f "set minlower $minlower"
	close $f
}

# insert char into password at a random position
proc insert {pvar char} {
	upvar $pvar p

	set p [linsert $p [rand [expr 1+[llength $p]]] $char]
}

# given a size, distribute between left and right hands
# taking into account where we left off
proc psplit {max lvar rvar} {
	upvar $lvar left $rvar right
	global isleft

	if {$isleft} {
		set right [expr $max/2]
		set left [expr $max-$right]
		set isleft [expr !($max%2)]
	} else {
		set left [expr $max/2]
		set right [expr $max-$left]
		set isleft [expr $max%2]
	}
}

proc password_generate {} {
	global password length minnum minlower minupper
	global lpass rpass initially_left isleft
	global distribute

	if {$distribute} {
	   set lkeys {q w e r t a s d f g z x c v b}
	   set rkeys {y u i o p h j k l n m}
	   set lnums {1 2 3 4 5 6}
	   set rnums {7 8 9 0}
	} else {
	   set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	   set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	   set lnums {0 1 2 3 4 5 6 7 8 9}
	   set rnums {0 1 2 3 4 5 6 7 8 9}
	}
	set lkeys_length [llength $lkeys]
	set rkeys_length [llength $rkeys]
	set lnums_length [llength $lnums]
	set rnums_length [llength $rnums]

	# if there is any underspecification, use additional lowercase letters
	set minlower [expr $length - ($minnum + $minupper)]


	set lpass ""		;# password chars typed by left hand
	set rpass ""		;# password chars typed by right hand
	set password ""		;# merged password

	# choose left or right starting hand
	set initially_left [set isleft [rand 2]]

	psplit $minnum left right
	for {set i 0} {$i<$left} {incr i} {
		insert lpass [lindex $lnums [rand $lnums_length]]
	}
	for {set i 0} {$i<$right} {incr i} {
		insert rpass [lindex $rnums [rand $rnums_length]]
	}

	psplit $minlower left right
	for {set i 0} {$i<$left} {incr i} {
		insert lpass [lindex $lkeys [rand $lkeys_length]]
	}
	for {set i 0} {$i<$right} {incr i} {
		insert rpass [lindex $rkeys [rand $rkeys_length]]
	}

	psplit $minupper left right
	for {set i 0} {$i<$left} {incr i} {
		insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
	}
	for {set i 0} {$i<$right} {incr i} {
		insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
	}

	# merge results together
	if {$initially_left} {
		regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass
		while {[llength $lpass]} {
			regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
			regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
		}
		if {[llength $rpass]} {
			append password $rpass
		}		
	} else {
		regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass
		while {[llength $rpass]} {
			regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
			regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
		}
		if {[llength $lpass]} {
			append password $lpass
		}		
	}
}

set _ran [pid]
proc rand {m} {
	global _ran

	set period 259200
	set _ran [expr ($_ran*7141 + 54773) % $period]
	expr int($m*($_ran/double($period)))
}

proc gen_bad_args {msg} {
	if ![llength [info commands .parameters.errmsg]] {
		message .parameters.errmsg -aspect 300
		pack .parameters.errmsg
	}
	.parameters.errmsg configure -text "$msg\
Please adjust the password generation arguments."
}


# tell tab what window to move between
set parm_tabList {}

# The procedure below is invoked in response to tabs in the entry







|
|








|
|




















|
|
|




|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|

|
|
|
|



|

|

|
<
|
|
<
|
|
|
|
|
|




|

|
|

|
|
|
|
|
|



|

|

|
|
|
|
|

|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|










|
|
|
|
|






|

|
|
|
|
|
|
|
|
|
|
|
|
|
|




|

|





|
|

|
|
|
|
|
|
|
|
|



|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|


|
|
|

|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


<

<
|
<
<
<



|
|
|
|
|
|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

382

383



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
button .generate_button -text "generate" -command password_generate
pack .prompt .password -in .password_frame -fill x -padx 2 -pady 2
pack .password_set .generate_button -in .password_frame -side left -expand 1 -fill x -padx 2 -pady 2
pack .password_frame -fill x

set dict_loaded 0
checkbutton .dict -text "test dictionary" -variable dict_check \
	-command {if {!$dict_loaded} load_dict} \
	-anchor w
pack .dict -fill x -padx 2 -pady 2


button .quit -text quit -command exit
button .help_button -text help -command help
pack .quit .help_button -side left -expand 1 -fill x -padx 2 -pady 2

proc help {} {
    if {[catch {toplevel .help}]} return
    message .help.text -text \
"tkpasswd - written by Don Libes, NIST, 10/1/93.

Click on passwd (local users) or yppasswd (NIS users).\
Select user using mouse (or keys - see below).\
Enter password or press ^G to generate a random password.\
(Press ^A to adjust the generation parameters.)\
Press return to set the password.\
If the dictionary is enabled and the password is in it,\
the password is rejected.

You must be root to set local passwords besides your own.\
If you are not root, you must also enter an old password\
when requested.

You do not have to move mouse into password field(s) to enter password.\
^U clears password field.\
^N and ^P select next/previous user.\
M-n and M-p select next/previous user with no password.\
(Users with no passwords are highlighted.)"

    button .help.ok -text "ok" -command {destroy .help}
    pack .help.text
    pack .help.ok -fill x -padx 2 -pady 2
}

# get list of local users
proc get_users {} {
    global sort_cmd passwd_cmd
    global nopasswords	;# line numbers of entries with no passwords
    global last_line	;# last line of text box
    global selection_line

    .names delete 1.0 end

    set file [open "|[lindex $passwd_cmd 1] $sort_cmd"]
    set last_line 1
    set nopasswords {}
    while {[gets $file buf] != -1} {
	set buf [split $buf :]
	if {[llength $buf]>2} {
	    # normal password entry
	    .names insert end "[format "%-8.8s %5d" [lindex $buf 0] [lindex $buf 2]]\n"
	    if {0==[string compare [lindex $buf 1] ""]} {
		.names tag add nopassword \
			{end - 2 line linestart} \
			{end - 2 line lineend}
		lappend nopasswords $last_line
	    }
	} else {
	    # +name style entry
	    .names insert end "$buf\n"
	}
	incr last_line
    }
    incr last_line -1
    close $file
    set selection_line 0
}

proc feedback {msg} {
    global password

    set password $msg
    .password select from 0
    .password select to end
    update
}

proc load_dict {} {
    global dict dict_loaded

    feedback "loading dictionary..."

    if {0==[catch {open /usr/dict/words} file]} {

	foreach w [split [read $file] "\n"] {set dict($w) ""}
	close $file

	set dict_loaded 1
	feedback "dictionary loaded"
    } else {
	feedback "dictionary missing"
	.dict deselect
    }
}

# put whatever security checks you like in here
proc weak_password {password} {
    global dict dict_check

    if {$dict_check} {
	feedback "checking password"

	if {[info exists dict($password)]} {
	    feedback "sorry - in dictionary"
	    return 1
	}
    }
    return 0
}

proc password_set {} {
    global password passwd_cmd selection_line

    set new_password $password

    if {$selection_line==0} {
	feedback "select a user first"
	return
    }
    set user [lindex [.names get selection.first selection.last] 0]

    if {[weak_password $password]} return

    feedback "setting password . . ."

    set cmd [lindex $passwd_cmd 0]
    spawn -noecho $cmd $user
    log_user 0
    set last_msg "error in $cmd"
    while {1} {
	expect {
	    -nocase "old password:" {
		exp_send "[get_old_password]\r"
	    } "assword*:" {
		exp_send "$new_password\r"
	    } -re "(.*)\r\n" {
		set last_msg $expect_out(1,string)
	    } eof break
	}
    }
    set status [wait]
    if {[lindex $status 3]==0} {
	feedback "set successfully"
    } else {
	feedback $last_msg
    }
}

# defaults for generating passwords
set length 9
set minnum 2
set minlower 5
set minupper 2
set distribute 0

proc parameter_filename {} {
    set file .tkpasswd.rc
    if {[info exists env(DOTDIR)]} {
	set file "$env(DOTDIR)/$file"
    }
    return ~/$file
}

catch {source [parameter_filename]}

# save parameters in a file
proc save_parameters {} {
    global minnum minlower minupper length

    if {[catch {open [parameter_filename] w} f]} {
	# should never happen, so don't bother with window code
	puts "tkpasswd: could not write [parameter_filename]"
	return
    }
    puts $f "# This is the .tkpasswd.rc file.  Do not edit it by hand as"
    puts $f "# it is automatically maintained by tkpasswd.  Any manual"
    puts $f "# modifications will be lost."
    puts $f ""
    puts $f "set length $length"
    puts $f "set minnum $minnum"
    puts $f "set minupper $minupper"
    puts $f "set minlower $minlower"
    close $f
}

# insert char into password at a random position
proc insert {pvar char} {
    upvar $pvar p

    set p [linsert $p [rand [expr 1+[llength $p]]] $char]
}

# given a size, distribute between left and right hands
# taking into account where we left off
proc psplit {max lvar rvar} {
    upvar $lvar left $rvar right
    global isleft

    if {$isleft} {
	set right [expr $max/2]
	set left [expr $max-$right]
	set isleft [expr !($max%2)]
    } else {
	set left [expr $max/2]
	set right [expr $max-$left]
	set isleft [expr $max%2]
    }
}

proc password_generate {} {
    global password length minnum minlower minupper
    global lpass rpass initially_left isleft
    global distribute

    if {$distribute} {
	set lkeys {q w e r t a s d f g z x c v b}
	set rkeys {y u i o p h j k l n m}
	set lnums {1 2 3 4 5 6}
	set rnums {7 8 9 0}
    } else {
	set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
	set lnums {0 1 2 3 4 5 6 7 8 9}
	set rnums {0 1 2 3 4 5 6 7 8 9}
    }
    set lkeys_length [llength $lkeys]
    set rkeys_length [llength $rkeys]
    set lnums_length [llength $lnums]
    set rnums_length [llength $rnums]

    # if there is any underspecification, use additional lowercase letters
    set minlower [expr $length - ($minnum + $minupper)]


    set lpass ""		;# password chars typed by left hand
    set rpass ""		;# password chars typed by right hand
    set password ""		;# merged password

    # choose left or right starting hand
    set initially_left [set isleft [rand 2]]

    psplit $minnum left right
    for {set i 0} {$i<$left} {incr i} {
	insert lpass [lindex $lnums [rand $lnums_length]]
    }
    for {set i 0} {$i<$right} {incr i} {
	insert rpass [lindex $rnums [rand $rnums_length]]
    }

    psplit $minlower left right
    for {set i 0} {$i<$left} {incr i} {
	insert lpass [lindex $lkeys [rand $lkeys_length]]
    }
    for {set i 0} {$i<$right} {incr i} {
	insert rpass [lindex $rkeys [rand $rkeys_length]]
    }

    psplit $minupper left right
    for {set i 0} {$i<$left} {incr i} {
	insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
    }
    for {set i 0} {$i<$right} {incr i} {
	insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
    }

    # merge results together
    if {$initially_left} {
	regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass
	while {[llength $lpass]} {
	    regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
	    regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
	}
	if {[llength $rpass]} {
	    append password $rpass
	}		
    } else {
	regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass
	while {[llength $rpass]} {
	    regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
	    regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
	}
	if {[llength $lpass]} {
	    append password $lpass
	}		
    }
}


proc rand {m} {

    expr {int($m*rand())}



}

proc gen_bad_args {msg} {
    if {![llength [info commands .parameters.errmsg]]} {
	message .parameters.errmsg -aspect 300
	pack .parameters.errmsg
    }
    .parameters.errmsg configure -text "$msg\
	    Please adjust the password generation arguments."
}


# tell tab what window to move between
set parm_tabList {}

# The procedure below is invoked in response to tabs in the entry
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
	}
    }
    focus [lindex $list $i]
}

# adjust args used in password generation
proc adjust_parameters {} {
	global parm_tabList
	set parm_tabList {}

	toplevel [set w .parameters]

#    wm title $w ""
#    wm iconname $w ""

	message $w.text -aspect 300 -text \
"These parameters control generation of random passwords.

It is not necessary to move the mouse into this window to operate it.\
Press <tab> to move to the next entry.\
Press <return> or click the <ok> button when you are done."

	foreach desc {
	  {length {total length}}
	  {minnum {minimum number of digits}}
	  {minupper {minimum number of uppercase letters}}
	  {minlower {minimum number of lowercase letters}}} {
		set name [lindex $desc 0]
		set text [lindex $desc 1]
		frame $w.$name -bd 1
		entry $w.$name.entry -relief sunken -width 2 -textvar $name
		bind $w.$name.entry <Tab> "Tab \$parm_tabList"
		bind $w.$name.entry <Return> "destroy_parm_window"
		label $w.$name.text -text $text
		pack $w.$name.entry -side left
		pack $w.$name.text -side left
		lappend parm_tabList $w.$name.entry
	}
	frame $w.2 -bd 1
	checkbutton $w.2.cb -text "alternate characters across hands" \
		-relief flat -variable distribute
	pack $w.2.cb -side left

	button $w.ok -text "ok" -command "destroy_parm_window"
	pack $w.text -expand 1 -fill x
	pack $w.length $w.minnum $w.minupper $w.minlower $w.2 -expand 1 -fill x
	pack $w.ok -side left -fill x -expand 1 -padx 2 -pady 2

#strace 10
	set oldfocus [focus]
#	$w.length.entry icursor end
	tkwait visibility $w.length.entry
	focus $w.length.entry
#	grab $w
	tkwait window $w
#	grab release $w
	focus $oldfocus

#strace 0

	save_parameters	
}

proc isnumber {n} {
	regexp "^\[0-9\]+$" $n
}

# destroy parm window IF all values are legal
proc destroy_parm_window {} {
	global minnum minlower minupper length

	set mustbe "must be a number greater than or equal to zero."

	# check all variables
	if {![isnumber $length]} {
		gen_bad_args "The total length $mustbe"
		return
	}
	if {![isnumber $minlower]} {
		gen_bad_args "The minimum number of lowercase characters $mustbe"
		return
	}
	if {![isnumber $minupper]} {
		gen_bad_args "The minimum number of uppercase characters $mustbe"
		return
	}
	if {![isnumber $minnum]} {
		gen_bad_args "The minimum number of digits $mustbe"
		return
	}

	# check constraints
	if {$minnum + $minlower + $minupper > $length} {
		gen_bad_args \
"It is impossible to generate a $length-character password with\
$minnum number[pluralize $minnum],\
$minlower lowercase letter[pluralize $minlower], and\
$minupper uppercase letter[pluralize $minupper]."
		return
	}

	destroy .parameters
}

# return appropriate ending for a count of "n" nouns
proc pluralize {n} {
	expr $n!=1?"s":""
}


proc get_old_password {} {
	global old

	toplevel .old
	label .old.label -text "Old password:"
	catch {unset old}
	entry .old.entry -textvar old -relief sunken -width 1

	pack .old.label
	pack .old.entry -fill x -padx 2 -pady 2

	bind .old.entry <Return> {destroy .old}
	set oldfocus [focus]
	focus .old.entry
	tkwait visibility .old
	grab .old
	tkwait window .old
	focus $oldfocus
	return $old
}

.unsorted select
.passwd invoke

proc make_selection {} {
	global selection_line last_line

	.names tag remove selection 0.0 end

	# don't let selection go off top of screen
	if {$selection_line < 1} {
		set selection_line $last_line
	} elseif {$selection_line > $last_line} {
		set selection_line 1
	}
	.names yview -pickplace [expr $selection_line-1]
	.names tag add selection $selection_line.0 [expr 1+$selection_line].0
}

proc select_next_nopassword {direction} {
	global selection_line last_line
	global nopasswords
	
	if 0==[llength $nopasswords] {
		feedback "no null passwords"
		return
	}

	if $direction==1 {
		# is there a better way to get last element of list?
		if $selection_line>=[lindex $nopasswords [expr [llength $nopasswords]-1]] {
			set selection_line 0
		}
		foreach i $nopasswords {
			if $selection_line<$i break
		}
	} else {
		if $selection_line<=[lindex $nopasswords 0] {
			set selection_line $last_line
		}
		set j [expr [llength $nopasswords]-1]
		for {} {$j>=0} {incr j -1} {
			set i [lindex $nopasswords $j]
			if $selection_line>$i break
		}
	}
	set selection_line $i
	make_selection
}

proc select {w coords} {
	global selection_line

	$w mark set insert "@$coords linestart"
	$w mark set anchor insert
	set first [$w index "anchor linestart"]
	set last [$w index "insert lineend + 1c"]
	scan $first %d selection_line

	$w tag remove selection 0.0 end
	$w tag add selection $first $last
}

bind Text <1> {select %W %x,%y}
bind Text <Double-1> {select %W %x,%y}
bind Text <Triple-1> {select %W %x,%y}
bind Text <2> {select %W %x,%y}
bind Text <3> {select %W %x,%y}







|
|

|

<
<
<
|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

<
|
<
|
|
<
|
<
|
<
<
<
|



|




|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|




|




|

|
|
|
|

|
|

|
|
|
|
|
|
|
|






|

|

|
|
|
|
|
|
|
|



|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|

|
|
|
|
|

|
|







413
414
415
416
417
418
419
420
421
422
423
424



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

458

459
460

461

462



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
	}
    }
    focus [lindex $list $i]
}

# adjust args used in password generation
proc adjust_parameters {} {
    global parm_tabList
    set parm_tabList {}

    toplevel [set w .parameters]




    message $w.text -aspect 300 -text \
"These parameters control generation of random passwords.

It is not necessary to move the mouse into this window to operate it.\
Press <tab> to move to the next entry.\
Press <return> or click the <ok> button when you are done."

    foreach desc {
	{length {total length}}
	{minnum {minimum number of digits}}
	{minupper {minimum number of uppercase letters}}
	{minlower {minimum number of lowercase letters}}} {
	    set name [lindex $desc 0]
	    set text [lindex $desc 1]
	    frame $w.$name -bd 1
	    entry $w.$name.entry -relief sunken -width 2 -textvar $name
	    bind $w.$name.entry <Tab> "Tab \$parm_tabList"
	    bind $w.$name.entry <Return> "destroy_parm_window"
	    label $w.$name.text -text $text
	    pack $w.$name.entry -side left
	    pack $w.$name.text -side left
	    lappend parm_tabList $w.$name.entry
    }
    frame $w.2 -bd 1
    checkbutton $w.2.cb -text "alternate characters across hands" \
	    -relief flat -variable distribute
    pack $w.2.cb -side left

    button $w.ok -text "ok" -command "destroy_parm_window"
    pack $w.text -expand 1 -fill x
    pack $w.length $w.minnum $w.minupper $w.minlower $w.2 -expand 1 -fill x
    pack $w.ok -side left -fill x -expand 1 -padx 2 -pady 2


    set oldfocus [focus]

    tkwait visibility $w.length.entry
    focus $w.length.entry

    tkwait window $w

    focus $oldfocus



    save_parameters	
}

proc isnumber {n} {
    regexp "^\[0-9\]+$" $n
}

# destroy parm window IF all values are legal
proc destroy_parm_window {} {
    global minnum minlower minupper length

    set mustbe "must be a number greater than or equal to zero."

    # check all variables
    if {![isnumber $length]} {
	gen_bad_args "The total length $mustbe"
	return
    }
    if {![isnumber $minlower]} {
	gen_bad_args "The minimum number of lowercase characters $mustbe"
	return
    }
    if {![isnumber $minupper]} {
	gen_bad_args "The minimum number of uppercase characters $mustbe"
	return
    }
    if {![isnumber $minnum]} {
	gen_bad_args "The minimum number of digits $mustbe"
	return
    }

    # check constraints
    if {$minnum + $minlower + $minupper > $length} {
	gen_bad_args \
		"It is impossible to generate a $length-character password with\
		$minnum number[pluralize $minnum],\
		$minlower lowercase letter[pluralize $minlower], and\
		$minupper uppercase letter[pluralize $minupper]."
	return
    }

    destroy .parameters
}

# return appropriate ending for a count of "n" nouns
proc pluralize {n} {
    expr $n!=1?"s":""
}


proc get_old_password {} {
    global old

    toplevel .old
    label .old.label -text "Old password:"
    catch {unset old}
    entry .old.entry -textvar old -relief sunken -width 1

    pack .old.label
    pack .old.entry -fill x -padx 2 -pady 2

    bind .old.entry <Return> {destroy .old}
    set oldfocus [focus]
    focus .old.entry
    tkwait visibility .old
    grab .old
    tkwait window .old
    focus $oldfocus
    return $old
}

.unsorted select
.passwd invoke

proc make_selection {} {
    global selection_line last_line

    .names tag remove selection 0.0 end

    # don't let selection go off top of screen
    if {$selection_line < 1} {
	set selection_line $last_line
    } elseif {$selection_line > $last_line} {
	set selection_line 1
    }
    .names yview -pickplace [expr $selection_line-1]
    .names tag add selection $selection_line.0 [expr 1+$selection_line].0
}

proc select_next_nopassword {direction} {
    global selection_line last_line
    global nopasswords
    
    if {0==[llength $nopasswords]} {
	feedback "no null passwords"
	return
    }

    if {$direction==1} {
	# is there a better way to get last element of list?
	if {$selection_line>=[lindex $nopasswords [expr [llength $nopasswords]-1]]} {
	    set selection_line 0
	}
	foreach i $nopasswords {
	    if {$selection_line<$i} break
	}
    } else {
	if {$selection_line<=[lindex $nopasswords 0]} {
	    set selection_line $last_line
	}
	set j [expr [llength $nopasswords]-1]
	for {} {$j>=0} {incr j -1} {
	    set i [lindex $nopasswords $j]
	    if {$selection_line>$i} break
	}
    }
    set selection_line $i
    make_selection
}

proc select {w coords} {
    global selection_line

    $w mark set insert "@$coords linestart"
    $w mark set anchor insert
    set first [$w index "anchor linestart"]
    set last [$w index "insert lineend + 1c"]
    scan $first %d selection_line

    $w tag remove selection 0.0 end
    $w tag add selection $first $last
}

bind Text <1> {select %W %x,%y}
bind Text <Double-1> {select %W %x,%y}
bind Text <Triple-1> {select %W %x,%y}
bind Text <2> {select %W %x,%y}
bind Text <3> {select %W %x,%y}

Changes to example/tkterm.

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


unset env(DISPLAY)
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if $termcap {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:nd=\E[C:
	:cl=\E[H\E[J:
	:do=^J:
	:so=\E[7m:
	:se=\E[m:
	:k1=\EOP:
	:k2=\EOQ:
	:k3=\EOR:
	:k4=\EOS:
	:k5=\EOT:
	:k6=\EOU:
	:k7=\EOV:
	:k8=\EOW:
	:k9=\EOX:
    }
}

if $terminfo {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,







|




















|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148


unset env(DISPLAY)
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if {$termcap} {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:nd=\E[C:
	:cl=\E[H\E[J:
	:do=^J:
	:so=\E[7m:
	:se=\E[m:
	:k1=\EOP:
	:k2=\EOQ:
	:k3=\EOR:
	:k4=\EOS:
	:k5=\EOT:
	:k6=\EOU:
	:k7=\EOV:
	:k8=\EOW:
	:k9=\EOX:
    }
}

if {$terminfo} {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	kf7=\EOV,
	kf8=\EOW,
	kf9=\EOX,
    }
    close $file

    set oldpath $env(PATH)
    set env(PATH) "/usr/5bin:/usr/lib/terminfo"
    if 1==[catch {exec tic $ttsrc} msg] {
	puts "WARNING: tic failed - if you don't have terminfo support on"
	puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"."
	puts "Here is the original error from running tic:"
	puts $msg
    }
    set env(PATH) $oldpath







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	kf7=\EOV,
	kf8=\EOW,
	kf9=\EOX,
    }
    close $file

    set oldpath $env(PATH)
    set env(PATH) "$env(PATH):/usr/5bin:/usr/lib/terminfo"
    if 1==[catch {exec tic $ttsrc} msg] {
	puts "WARNING: tic failed - if you don't have terminfo support on"
	puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"."
	puts "Here is the original error from running tic:"
	puts $msg
    }
    set env(PATH) $oldpath
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if $newline {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {







|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if {$newline} {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {

Changes to example/unbuffer.man.

23
24
25
26
27
28
29







30
31
32
33
34
35
36

You can disable this automatic buffering as follows:

.nf

	unbuffer od -c /tmp/fifo | more








.fi
.SH BUGS

The man page is longer than the program.

.SH SEE ALSO
.I







>
>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

You can disable this automatic buffering as follows:

.nf

	unbuffer od -c /tmp/fifo | more

.fi
When you have a pipeline, unbuffer must be applied to each element
except the last (since that doesn't have its output redirected).
Example:
.nf

        unbuffer p1 | unbuffer p2 | unbuffer p3 | p4
.fi
.SH BUGS

The man page is longer than the program.

.SH SEE ALSO
.I

Changes to example/virterm.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#############################################

set blankline ""
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if $termcap {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:cl=\E[H\E[J:
	:do=^J:
	:so=\E[7m:
	:se=\E[m:
	:nd=\E[C:
    }
}

if $terminfo {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,
	cuf1=\E[C,
	clear=\E[H\E[J,
	ind=\n,
	cr=\r,
	smso=\E[7m,
	rmso=\E[m,
    }
    close $file

    set oldpath $env(PATH)
    set env(PATH) "/usr/5bin:/usr/lib/terminfo"
    if 1==[catch {exec tic $ttsrc} msg] {
	puts "WARNING: tic failed - if you don't have terminfo support on"
	puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"."
	puts "Here is the original error from running tic:"
	puts $msg
    }
    set env(PATH) $oldpath








|











|


















|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#############################################

set blankline ""
set env(LINES) $rows
set env(COLUMNS) $cols

set env(TERM) "tt"
if {$termcap} {
    set env(TERMCAP) {tt:
	:cm=\E[%d;%dH:
	:up=\E[A:
	:cl=\E[H\E[J:
	:do=^J:
	:so=\E[7m:
	:se=\E[m:
	:nd=\E[C:
    }
}

if {$terminfo} {
    set env(TERMINFO) /tmp
    set ttsrc "/tmp/tt.src"
    set file [open $ttsrc w]

    puts $file {tt|textterm|Don Libes' tk text widget terminal emulator,
	cup=\E[%p1%d;%p2%dH,
	cuu1=\E[A,
	cuf1=\E[C,
	clear=\E[H\E[J,
	ind=\n,
	cr=\r,
	smso=\E[7m,
	rmso=\E[m,
    }
    close $file

    set oldpath $env(PATH)
    set env(PATH) "/usr/5bin:/usr/lib/terminfo"
    if {1==[catch {exec tic $ttsrc} msg]} {
	puts "WARNING: tic failed - if you don't have terminfo support on"
	puts "your system, change \"set terminfo 1\" to \"set terminfo 0\"."
	puts "Here is the original error from running tic:"
	puts $msg
    }
    set env(PATH) $oldpath

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if $newline {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
	# discard first line already written
	incr chars_rem_to_write -$chars_to_write
	set s [string range $s $chars_to_write end]
	
	# update cur_col
	incr cur_col $chars_to_write
	# update cur_row
	if {$newline} {
		term_down
	}

	##################
	# write full lines
	##################
	while {$chars_rem_to_write >= $cols} {
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335


proc term_expect {args} {
        global cur_row cur_col  # used by expect_background actions

	set desired_timeout [
	    uplevel {
		if [info exists timeout] {
			set timeout
		} else {
			uplevel #0 {
				if {[info exists timeout]} {
					set timeout
				} else {
					expr 10







|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335


proc term_expect {args} {
        global cur_row cur_col  # used by expect_background actions

	set desired_timeout [
	    uplevel {
		if {[info exists timeout]} {
			set timeout
		} else {
			uplevel #0 {
				if {[info exists timeout]} {
					set timeout
				} else {
					expr 10
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  exp_send_error "connected.\n\n"
}


proc dosearch {search} {
  global term
  exp_send_error "Searching for '$search'..."
  if [string match ?=* "$search"] {set typ ""} else {set typ "k="}
  sendcommand "$typ$search\r"
  waitfornext
  set countstr [$term get 2.17 2.35]
  if {![regsub { Entries Found *} $countstr "" number]} {
    set number 1
    exp_send_error "one entry found.\n\n"
    return 1







|







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  exp_send_error "connected.\n\n"
}


proc dosearch {search} {
  global term
  exp_send_error "Searching for '$search'..."
  if {[string match ?=* "$search"]} {set typ ""} else {set typ "k="}
  sendcommand "$typ$search\r"
  waitfornext
  set countstr [$term get 2.17 2.35]
  if {![regsub { Entries Found *} $countstr "" number]} {
    set number 1
    exp_send_error "one entry found.\n\n"
    return 1

Changes to example/weather.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!../expect -f

# weather - Expect script to get the weather (courtesy University of Michigan)
# Don Libes
# Version 1.9

# local weather is retrieved if no argument
# argument is the National Weather Service designation for an area
# I.e., WBC = Washington DC (oh yeah, that's obvious)

exp_version -exit 5.0

if $argc>0 {set code $argv} else {set code "WBC"}

proc timedout {} {
	send_user "Weather server timed out.  Try again later when weather server is not so busy.\n"
	exit 1
}

# delete special weather statement question
proc delete_special {s} {
	set x [string first "     ******" $s]
	return [join [lrange [split $s ""] 0 $x] ""]
}

set timeout 60
log_user 0

set env(TERM) vt100	;# actual value doesn't matter, just has to be set

spawn telnet downwind.sprl.umich.edu 3000
match_max 100000
for {} 1 {} {
	expect timeout {
		send_user "failed to contact weather server\n"
		exit
	} "Press Return to continue*" {
               # this prompt used sometimes, eg, upon opening connection
               send "\r"
	} "Press Return for menu*" {












|













|



|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!../expect -f

# weather - Expect script to get the weather (courtesy University of Michigan)
# Don Libes
# Version 1.9

# local weather is retrieved if no argument
# argument is the National Weather Service designation for an area
# I.e., WBC = Washington DC (oh yeah, that's obvious)

exp_version -exit 5.0

if {$argc>0} {set code $argv} else {set code "WBC"}

proc timedout {} {
	send_user "Weather server timed out.  Try again later when weather server is not so busy.\n"
	exit 1
}

# delete special weather statement question
proc delete_special {s} {
	set x [string first "     ******" $s]
	return [join [lrange [split $s ""] 0 $x] ""]
}

set timeout 60
#log_user 0

set env(TERM) vt100	;# actual value doesn't matter, just has to be set

spawn telnet cirrus.sprl.umich.edu 3000
match_max 100000
while {1} {
	expect timeout {
		send_user "failed to contact weather server\n"
		exit
	} "Press Return to continue*" {
               # this prompt used sometimes, eg, upon opening connection
               send "\r"
	} "Press Return for menu*" {
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
send "1\r"
expect timeout timedout "Selection:"
send "1\r"
expect timeout timedout "city code:"
send "$code\r"
expect $code		;# discard this

for {} 1 {} {
	expect timeout {
		timedout
	} "Press Return to continue*:*" {
		send_user "\n[delete_special $expect_out(buffer)]\n"
		send "\r"
	} "Press Return to display statement, M for menu:*" {
		send_user "\n[delete_special $expect_out(buffer)]\n"







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
send "1\r"
expect timeout timedout "Selection:"
send "1\r"
expect timeout timedout "city code:"
send "$code\r"
expect $code		;# discard this

while {1} {
	expect timeout {
		timedout
	} "Press Return to continue*:*" {
		send_user "\n[delete_special $expect_out(buffer)]\n"
		send "\r"
	} "Press Return to display statement, M for menu:*" {
		send_user "\n[delete_special $expect_out(buffer)]\n"

Changes to example/xkibitz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151


152


153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!../expect --

# share an xterm with other users
# See xkibitz(1) man page for complete info.
# Compare with kibitz.
# Author: Don Libes, NIST
# Version: 1.2

proc help {} {
	puts "Commands          Meaning"
	puts "--------          -------"
	puts "return            return to program"        
	puts "=                 list"
	puts "+ <display>       add"
	puts "- <tag>           drop"
	puts "where <display> is an X display name such as nist.gov or nist.gov:0.0"
	puts "and <tag> is a tag from the = command."
	puts "+ and - require whitespace before argument."
	puts {return command must be spelled out ("r", "e", "t", ...).}
}

proc prompt1 {} {
	return "xkibitz> "
}

proc h {} help
proc ? {} help

# disable history processing - there seems to be some incestuous relationship
# between history and unknown in Tcl 8.0
proc history {args} {}
proc unknown {args} {
	puts "$args: invalid command"
	help
}

set tag2pid(0)			[pid]
set pid2tty([pid])		"/dev/tty"
if [info exists env(DISPLAY)] {
	set pid2display([pid])	$env(DISPLAY)
} else {
	set pid2display([pid])	""
}

# small int allowing user to more easily identify display
# maxtag always points at highest in use
set maxtag 0

proc + {display} {
	global ids pid2display pid2tag tag2pid maxtag pid2sid
	global pid2tty env

	if ![string match *:* $display] {
		append display :0.0
	}

	if {![info exists env(XKIBITZ_XTERM_ARGS)]} {
		set env(XKIBITZ_XTERM_ARGS) ""
	}

	set dummy1 [open /dev/null]
	set dummy2 [open /dev/null]
	spawn -pty -noecho
	close $dummy1
	close $dummy2

	stty raw -echo < $spawn_out(slave,name)
	# Linux needs additional stty, sounds like a bug in its stty to me.
	# raw should imply this stuff, no?
	stty -icrnl -icanon < $spawn_out(slave,name)

	regexp ".*(.)(.)" $spawn_out(slave,name) dummy c1 c2
	if {[string compare $c1 "/"] == 0} {
		# On Pyramid and AIX, ttynames such as /dev/pts/1
		# requre suffix to be padded with a 0
		set c1 0
	}

	set pid [eval exec xterm \
			-display $display \
			-geometry [stty columns]x[stty rows] \
			-S$c1$c2$spawn_out(slave,fd) \
                        $env(XKIBITZ_XTERM_ARGS) &]
	close -slave

	# xterm first sends back window id, discard
	log_user 0
	expect {
		eof {wait;return}
		\n
	}
	log_user 1

	lappend ids $spawn_id
	set pid2display($pid) $display
	incr maxtag
	set tag2pid($maxtag) $pid
	set pid2tag($pid) $maxtag
	set pid2sid($pid) $spawn_id
	set pid2tty($pid) $spawn_out(slave,name)
	return
}

proc = {} {
	global pid2display tag2pid pid2tty

	puts "Tag  Size Display"
	foreach tag [lsort -integer [array names tag2pid]] {
		set pid $tag2pid($tag)
		set tty $pid2tty($pid)
		
		puts [format "%3d [stty columns < $tty]x[stty rows < $tty] $pid2display($pid)" $tag]
	}
}

proc - {tag} {
	global tag2pid pid2tag pid2display maxtag ids pid2sid
	global pid2tty

	if ![info exists tag2pid($tag)] {
		puts "no such tag"
		return
	}
	if {$tag == 0} {
		puts "cannot drop self"
		return
	}

	set pid $tag2pid($tag)

	# close and remove spawn_id from list
	set spawn_id $pid2sid($pid)
	set index [lsearch $ids $spawn_id]
	set ids [lreplace $ids $index $index]

	exec kill -9 $pid
	close
	wait

	unset tag2pid($tag)
	unset pid2tag($pid)
	unset pid2display($pid)
	unset pid2sid($pid)
	unset pid2tty($pid)

	# lower maxtag if possible
	while {![info exists tag2pid($maxtag)]} {
		incr maxtag -1
	}
}



exit -onexit {


	unset pid2display([pid])	;# avoid killing self

	foreach pid [array names pid2display] {
		catch {exec kill -9 $pid}
	}

}

trap exit HUP

trap {
	set r [stty rows]
	set c [stty columns]
	stty rows $r columns $c < $app_tty
	foreach pid [array names pid2tty] {
		if {$pid == [pid]} continue
		stty rows $r columns $c < $pid2tty($pid)
	}
} WINCH

set escape \035		;# control-right-bracket
set escape_printable "^\]"

while [llength $argv]>0 {
	set flag [lindex $argv 0]
	switch -- $flag \
	"-escape" {
		set escape [lindex $argv 1]
		set escape_printable $escape
		set argv [lrange $argv 2 end]
	} "-display" {
		+ [lindex $argv 1]
		set argv [lrange $argv 2 end]
	} default {
		break
	}
}

if [llength $argv]>0 {
	eval spawn -noecho $argv
} else {
	spawn -noecho $env(SHELL)
}
set prog $spawn_id
set app_tty $spawn_out(slave,name)

puts "Escape sequence is $escape_printable"

interact {
	-input $user_spawn_id -reset $escape {
		puts "\nfor help enter: ? or h or help"
		interpreter
	} -output $prog
	-input ids -output $prog
	-input $prog -output $user_spawn_id -output ids
}










|
|
|
|
|
|
|
|
|
|



|









|
|




|
|

|







|
|

|
|
|

|
|
|

|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|



|

|
|
|
|
|
|
|



|
|

|
|
|
|
|
|
|
|

|

|
|
|
|

|
|
|

|
|
|
|
|

|
|
|
|


>
>
|
>
>
|

|
|
|
>





|
|
|
|
|
|
|





|
|
|
|
|
|
|
|
|
|
|
|
|


|
|

|







|
|
|
|
|
|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!../expect --

# share an xterm with other users
# See xkibitz(1) man page for complete info.
# Compare with kibitz.
# Author: Don Libes, NIST
# Version: 1.2

proc help {} {
    puts "Commands          Meaning"
    puts "--------          -------"
    puts "return            return to program"        
    puts "=                 list"
    puts "+ <display>       add"
    puts "- <tag>           drop"
    puts "where <display> is an X display name such as nist.gov or nist.gov:0.0"
    puts "and <tag> is a tag from the = command."
    puts "+ and - require whitespace before argument."
    puts {return command must be spelled out ("r", "e", "t", ...).}
}

proc prompt1 {} {
    return "xkibitz> "
}

proc h {} help
proc ? {} help

# disable history processing - there seems to be some incestuous relationship
# between history and unknown in Tcl 8.0
proc history {args} {}
proc unknown {args} {
    puts "$args: invalid command"
    help
}

set tag2pid(0)			[pid]
set pid2tty([pid])		"/dev/tty"
if {[info exists env(DISPLAY)]} {
    set pid2display([pid])	$env(DISPLAY)
} else {
    set pid2display([pid])	""
}

# small int allowing user to more easily identify display
# maxtag always points at highest in use
set maxtag 0

proc + {display} {
    global ids pid2display pid2tag tag2pid maxtag pid2sid
    global pid2tty env

    if {![string match *:* $display]} {
	append display :0.0
    }

    if {![info exists env(XKIBITZ_XTERM_ARGS)]} {
	set env(XKIBITZ_XTERM_ARGS) ""
    }

    set dummy1 [open /dev/null]
    set dummy2 [open /dev/null]
    spawn -pty -noecho
    close $dummy1
    close $dummy2

    stty raw -echo < $spawn_out(slave,name)
    # Linux needs additional stty, sounds like a bug in its stty to me.
    # raw should imply this stuff, no?
    stty -icrnl -icanon < $spawn_out(slave,name)

    regexp ".*(.)(.)" $spawn_out(slave,name) dummy c1 c2
    if {[string compare $c1 "/"] == 0} {
	# On Pyramid and AIX, ttynames such as /dev/pts/1
	# requre suffix to be padded with a 0
	set c1 0
    }

    set pid [eval exec xterm \
	    -display $display \
	    -geometry [stty columns]x[stty rows] \
	    -S$c1$c2$spawn_out(slave,fd) \
	    $env(XKIBITZ_XTERM_ARGS) &]
    close -slave

    # xterm first sends back window id, discard
    log_user 0
    expect {
	eof {wait;return}
	\n
    }
    log_user 1

    lappend ids $spawn_id
    set pid2display($pid) $display
    incr maxtag
    set tag2pid($maxtag) $pid
    set pid2tag($pid) $maxtag
    set pid2sid($pid) $spawn_id
    set pid2tty($pid) $spawn_out(slave,name)
    return
}

proc = {} {
    global pid2display tag2pid pid2tty

    puts "Tag  Size Display"
    foreach tag [lsort -integer [array names tag2pid]] {
	set pid $tag2pid($tag)
	set tty $pid2tty($pid)
	
	puts [format "%3d [stty columns < $tty]x[stty rows < $tty] $pid2display($pid)" $tag]
    }
}

proc - {tag} {
    global tag2pid pid2tag pid2display maxtag ids pid2sid
    global pid2tty

    if {![info exists tag2pid($tag)]} {
	puts "no such tag"
	return
    }
    if {$tag == 0} {
	puts "cannot drop self"
	return
    }

    set pid $tag2pid($tag)

    # close and remove spawn_id from list
    set spawn_id $pid2sid($pid)
    set index [lsearch $ids $spawn_id]
    set ids [lreplace $ids $index $index]

    exec kill -9 $pid
    close
    wait

    unset tag2pid($tag)
    unset pid2tag($pid)
    unset pid2display($pid)
    unset pid2sid($pid)
    unset pid2tty($pid)

    # lower maxtag if possible
    while {![info exists tag2pid($maxtag)]} {
	incr maxtag -1
    }
}

rename exit exitReal

proc exit {} {
    global pid2display

    unset pid2display([pid])	;# avoid killing self

    foreach pid [array names pid2display] {
	catch {exec kill -9 $pid}
    }
    exitReal
}

trap exit HUP

trap {
    set r [stty rows]
    set c [stty columns]
    stty rows $r columns $c < $app_tty
    foreach pid [array names pid2tty] {
	if {$pid == [pid]} continue
	stty rows $r columns $c < $pid2tty($pid)
    }
} WINCH

set escape \035		;# control-right-bracket
set escape_printable "^\]"

while {[llength $argv]>0} {
    set flag [lindex $argv 0]
    switch -- $flag \
	    "-escape" {
	set escape [lindex $argv 1]
	set escape_printable $escape
	set argv [lrange $argv 2 end]
    } "-display" {
	+ [lindex $argv 1]
	set argv [lrange $argv 2 end]
    } default {
	break
    }
}

if {[llength $argv]>0} {
    eval spawn -noecho $argv
} else {
    spawn -noecho $env(SHELL)
}
set prog $spawn_id
set app_tty $spawn_out(slave,name)

puts "Escape sequence is $escape_printable"

interact {
    -input $user_spawn_id -reset $escape {
	puts "\nfor help enter: ? or h or help"
	interpreter -eof exit
    } -output $prog
    -input ids -output $prog
    -input $prog eof exit -output $user_spawn_id -output ids
}

Changes to example/xpstat.

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
Pan the world/author text, player list, or your own alias by holding the middle mouse button down and moving the mouse."
}

# if user presses "update" try to update screen immediately
proc prod {x y} {
	global cat_spawn_id updateflag

	if $updateflag {
		show-help $x $y "I heard you, gimme a break.  I'm waiting for the xpilot server to respond..."
	}
	set updateflag 1

	exp_send -i $cat_spawn_id "\r"
}

proc display {host} {
	global world db alias max env

	set w .$host
	#if 0==[llength [info com $w]]
	if ![winfo exists $w] {	

		# window does not exist, create it

		toplevel $w -class xpstat
		wm minsize $w 1 1
		wm title $w "xpilot@$host"
		wm iconname $w "$host xpilot stats"







|











<
|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
Pan the world/author text, player list, or your own alias by holding the middle mouse button down and moving the mouse."
}

# if user presses "update" try to update screen immediately
proc prod {x y} {
	global cat_spawn_id updateflag

	if {$updateflag} {
		show-help $x $y "I heard you, gimme a break.  I'm waiting for the xpilot server to respond..."
	}
	set updateflag 1

	exp_send -i $cat_spawn_id "\r"
}

proc display {host} {
	global world db alias max env

	set w .$host

	if {![winfo exists $w]} {	

		# window does not exist, create it

		toplevel $w -class xpstat
		wm minsize $w 1 1
		wm title $w "xpilot@$host"
		wm iconname $w "$host xpilot stats"
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
		pack $w.world -expand 1 -fill x
		pack $w.msg
		pack $w.help $w.update $w.play -side left
		pack $w.alias -side left -expand 1 -fill x
		set max($host,was) 0
	}

	if $max($host)==0 {
		# put up "no players" message?
		if $max($host,was)>0 {
			pack $w.msg -after $w.world -fill x -side top
			pack forget $w.world
		}
	} else {
		# remove "no players" message?
		if $max($host,was)==0 {
			pack $w.players -after $w.world -side top
			pack forget $w.msg
		}
	}		

	$w.players delete 0 end








|

|





|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
		pack $w.world -expand 1 -fill x
		pack $w.msg
		pack $w.help $w.update $w.play -side left
		pack $w.alias -side left -expand 1 -fill x
		set max($host,was) 0
	}

	if {$max($host)==0} {
		# put up "no players" message?
		if {$max($host,was)>0} {
			pack $w.msg -after $w.world -fill x -side top
			pack forget $w.world
		}
	} else {
		# remove "no players" message?
		if {$max($host,was)==0} {
			pack $w.players -after $w.world -side top
			pack forget $w.msg
		}
	}		

	$w.players delete 0 end

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
wm withdraw .
set oldhosts {}

set updateflag 0		;# 1 if user pressed "update" button

# look for desired alias in the .Xdefaults file
set status [catch {exec egrep "xpilot.name:" [glob ~/.Xdefaults]} output]
if $status==0 {
	regexp "xpilot.name:\[ \t]*(\[^\r]*)" $output dummy env(USER)
}

spawn cat -u; set cat_spawn_id $spawn_id

while 1 {
	global xpilot hosts

	set hosts {}

	eval spawn $xpilot $argv
	while {[probe]} {exp_send "N\r"}
	catch {expect_before}	;# disable expect_before from inside probe

	# clean up hosts that no longer are running xpilots

	foreach host $oldhosts {
		# if host not in hosts
		if -1==[lsearch $hosts $host] {
			destroy .$host
		}
	}
	set oldhosts $hosts

	set updateflag 0

	# sleep for a little while, subject to click from "update" button
	expect -i $cat_spawn_id -re "...."	;# two crlfs
}







|





|












|










232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
wm withdraw .
set oldhosts {}

set updateflag 0		;# 1 if user pressed "update" button

# look for desired alias in the .Xdefaults file
set status [catch {exec egrep "xpilot.name:" [glob ~/.Xdefaults]} output]
if {$status==0} {
	regexp "xpilot.name:\[ \t]*(\[^\r]*)" $output dummy env(USER)
}

spawn cat -u; set cat_spawn_id $spawn_id

while {1} {
	global xpilot hosts

	set hosts {}

	eval spawn $xpilot $argv
	while {[probe]} {exp_send "N\r"}
	catch {expect_before}	;# disable expect_before from inside probe

	# clean up hosts that no longer are running xpilots

	foreach host $oldhosts {
		# if host not in hosts
		if {-1==[lsearch $hosts $host]} {
			destroy .$host
		}
	}
	set oldhosts $hosts

	set updateflag 0

	# sleep for a little while, subject to click from "update" button
	expect -i $cat_spawn_id -re "...."	;# two crlfs
}

Changes to example/xrlogin.

11
12
13
14
15
16
17
18
19
20
21
22

set prompt "(%|#|\\$) $"		;# default prompt
catch {set prompt $env(EXPECT_PROMPT)}

set timeout -1
eval spawn rlogin $argv
expect eof exit -re $prompt
if [string match "unix:0.0" $env(DISPLAY)] {
	set env(DISPLAY) "[exec hostname].[exec domainname]:0.0\r"
}
send "setenv DISPLAY $env(DISPLAY)\r"
interact







|




11
12
13
14
15
16
17
18
19
20
21
22

set prompt "(%|#|\\$) $"		;# default prompt
catch {set prompt $env(EXPECT_PROMPT)}

set timeout -1
eval spawn rlogin $argv
expect eof exit -re $prompt
if {[string match "unix:0.0" $env(DISPLAY)]} {
	set env(DISPLAY) "[exec hostname].[exec domainname]:0.0\r"
}
send "setenv DISPLAY $env(DISPLAY)\r"
interact

Added expTcl.c.

Added expTcl.h.

Added exp_chan.c.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
/* 
 * tclUnixChan.c
 *
 *	Channel driver for Expect channels.
 *      Based on UNIX File channel from TclUnixChan.c
 *
 */

#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>	/* for isspace */
#include <time.h>	/* for time(3) */

#include "expect_cf.h"

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include	"tclInt.h"	/* Internal definitions for Tcl. */

#include "tcl.h"

#include "string.h"

#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"

static int		ExpCloseProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_Interp *interp));
static int		ExpInputProc _ANSI_ARGS_((ClientData instanceData,
		            char *buf, int toRead, int *errorCode));
static int		ExpOutputProc _ANSI_ARGS_((
			    ClientData instanceData, char *buf, int toWrite,
                            int *errorCode));
static void		ExpWatchProc _ANSI_ARGS_((ClientData instanceData,
		            int mask));
static int		ExpGetHandleProc _ANSI_ARGS_((ClientData instanceData,
		            int direction, ClientData *handlePtr));

/*
 * This structure describes the channel type structure for Expect-based IO:
 */

Tcl_ChannelType expChannelType = {
    "exp",				/* Type name. */
    /* Expect channels are always blocking */
    NULL,				/* Set blocking/nonblocking mode.*/
    ExpCloseProc,			/* Close proc. */
    ExpInputProc,			/* Input proc. */
    ExpOutputProc,			/* Output proc. */
    NULL,				/* Seek proc. */
    NULL,				/* Set option proc. */
    NULL,				/* Get option proc. */
    ExpWatchProc,			/* Initialize notifier. */
    ExpGetHandleProc,			/* Get OS handles out of channel. */
    NULL,				/* Close2 proc */
};

typedef struct ThreadSpecificData {
    /*
     * List of all exp channels currently open.  This is per thread and is
     * used to match up fd's to channels, which rarely occurs.
     */
    
    ExpState *firstExpPtr;
    int channelCount;	 /* this is process-wide as it is used to
			     give user some hint as to why a spawn has failed
			     by looking at process-wide resource usage */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;


/*
 *----------------------------------------------------------------------
 *
 * ExpInputProc --
 *
 *	This procedure is invoked from the generic IO level to read
 *	input from an exp-based channel.
 *
 * Results:
 *	The number of bytes read is returned or -1 on error. An output
 *	argument contains a POSIX error code if an error occurs, or zero.
 *
 * Side effects:
 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
ExpInputProc(instanceData, buf, toRead, errorCodePtr)
    ClientData instanceData;		/* Exp state. */
    char *buf;				/* Where to store data read. */
    int toRead;				/* How much space is available
                                         * in the buffer? */
    int *errorCodePtr;			/* Where to store error code. */
{
    ExpState *esPtr = (ExpState *) instanceData;
    int bytesRead;			/* How many bytes were actually
                                         * read from the input device? */

    *errorCodePtr = 0;
    
    /*
     * Assume there is always enough input available. This will block
     * appropriately, and read will unblock as soon as a short read is
     * possible, if the channel is in blocking mode. If the channel is
     * nonblocking, the read will never block.
     */

    bytesRead = read(esPtr->fdin, buf, (size_t) toRead);
    /*printf("ExpInputProc: read(%d,,) = %d\r\n",esPtr->fdin,bytesRead);*/
    if (bytesRead > -1) {
	/* strip parity if requested */
	if (esPtr->parity == 0) {
	    char *end = buf+bytesRead;
	    for (;buf < end;buf++) {
		*buf &= 0x7f;
	    }
	}
        return bytesRead;
    }
    *errorCodePtr = errno;
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * ExpOutputProc--
 *
 *	This procedure is invoked from the generic IO level to write
 *	output to an exp channel.
 *
 * Results:
 *	The number of bytes written is returned or -1 on error. An
 *	output argument	contains a POSIX error code if an error occurred,
 *	or zero.
 *
 * Side effects:
 *	Writes output on the output device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
ExpOutputProc(instanceData, buf, toWrite, errorCodePtr)
    ClientData instanceData;		/* Exp state. */
    char *buf;				/* The data buffer. */
    int toWrite;			/* How many bytes to write? */
    int *errorCodePtr;			/* Where to store error code. */
{
    ExpState *esPtr = (ExpState *) instanceData;
    int written = 0;

    *errorCodePtr = 0;

    if (toWrite < 0) Tcl_Panic("ExpOutputProc: called with negative char count");

    while (toWrite > 0) {
	written = write(esPtr->fdout, buf, (size_t) toWrite);
	if (written == 0) {
	    /* This shouldn't happen but I'm told that it does
	     * nonetheless (at least on SunOS 4.1.3).  Since this is
	     * not a documented return value, the most reasonable
	     * thing is to complain here and retry in the hopes that
	     * it is some transient condition.  */
	    sleep(1);
	    expDiagLogU("write() failed to write anything - will sleep(1) and retry...\n");
	} else if (written < 0) {
	    *errorCodePtr = errno;
	    return -1;
	}
	buf += written;
	toWrite -= written;
    }
    return written;
}

/*
 *----------------------------------------------------------------------
 *
 * ExpCloseProc --
 *
 *	This procedure is called from the generic IO level to perform
 *	channel-type-specific cleanup when an exp-based channel is closed.
 *
 * Results:
 *	0 if successful, errno if failed.
 *
 * Side effects:
 *	Closes the device of the channel.
 *
 *----------------------------------------------------------------------
 */

/*ARGSUSED*/
static int
ExpCloseProc(instanceData, interp)
    ClientData instanceData;	/* Exp state. */
    Tcl_Interp *interp;		/* For error reporting - unused. */
{
    ExpState *esPtr = (ExpState *) instanceData;
    ExpState **nextPtrPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    esPtr->registered = FALSE;

#if 0
    /*
      Really should check that we created one first.  Since we're sharing fds
      with Tcl, perhaps a filehandler was created with a plain tcl file - we
      wouldn't want to delete that.  Although if user really close Expect's
      user_spawn_id, it probably doesn't matter anyway.
    */

    Tcl_DeleteFileHandler(esPtr->fdin);
#endif /*0*/

    Tcl_DecrRefCount(esPtr->buffer);

    /* Actually file descriptor should have been closed earlier. */
    /* So do nothing here */

    /*
     * Conceivably, the process may not yet have been waited for.  If this
     * becomes a requirement, we'll have to revisit this code.  But for now, if
     * it's just Tcl exiting, the processes will exit on their own soon
     * anyway.
     */

    for (nextPtrPtr = &(tsdPtr->firstExpPtr); (*nextPtrPtr) != NULL;
	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {
	if ((*nextPtrPtr) == esPtr) {
	    (*nextPtrPtr) = esPtr->nextPtr;
	    break;
	}
    }
    tsdPtr->channelCount--;

    if (esPtr->bg_status == blocked ||
	    esPtr->bg_status == disarm_req_while_blocked) {
	esPtr->freeWhenBgHandlerUnblocked = 1;
	/*
	 * If we're in the middle of a bg event handler, then the event
	 * handler will have to take care of freeing esPtr.
	 */
    } else {
	expStateFree(esPtr);
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * ExpWatchProc --
 *
 *	Initialize the notifier to watch the fd from this channel.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets up the notifier so that a future event on the channel will
 *	be seen by Tcl.
 *
 *----------------------------------------------------------------------
 */

static void
ExpWatchProc(instanceData, mask)
    ClientData instanceData;		/* The exp state. */
    int mask;				/* Events of interest; an OR-ed
                                         * combination of TCL_READABLE,
                                         * TCL_WRITABLE and TCL_EXCEPTION. */
{
    ExpState *esPtr = (ExpState *) instanceData;

    /*
     * Make sure we only register for events that are valid on this exp.
     * Note that we are passing Tcl_NotifyChannel directly to
     * Tcl_CreateExpHandler with the channel pointer as the client data.
     */

    mask &= esPtr->validMask;
    if (mask) {
	/*printf("  CreateFileHandler: %d (mask = %d)\r\n",esPtr->fdin,mask);*/
	Tcl_CreateFileHandler(esPtr->fdin, mask,
		(Tcl_FileProc *) Tcl_NotifyChannel,
		(ClientData) esPtr->channel);
    } else {
	/*printf("  DeleteFileHandler: %d (mask = %d)\r\n",esPtr->fdin,mask);*/
	Tcl_DeleteFileHandler(esPtr->fdin);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ExpGetHandleProc --
 *
 *	Called from Tcl_GetChannelHandle to retrieve OS handles from
 *	an exp-based channel.
 *
 * Results:
 *	Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if
 *	there is no handle for the specified direction. 
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ExpGetHandleProc(instanceData, direction, handlePtr)
    ClientData instanceData;	/* The exp state. */
    int direction;		/* TCL_READABLE or TCL_WRITABLE */
    ClientData *handlePtr;	/* Where to store the handle.  */
{
    ExpState *esPtr = (ExpState *) instanceData;

    if (direction & TCL_WRITABLE) {
	*handlePtr = (ClientData) esPtr->fdin;
    }
    if (direction & TCL_READABLE) {
	*handlePtr = (ClientData) esPtr->fdin;
    } else {
	return TCL_ERROR;
    }
    return TCL_OK;
}

int
expChannelCountGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->channelCount;
}

int
expSizeGet(esPtr)
    ExpState *esPtr;
{
    int len;
    Tcl_GetStringFromObj(esPtr->buffer,&len);
    return len;
}

int
expSizeZero(esPtr)
    ExpState *esPtr;
{
    int len;
    Tcl_GetStringFromObj(esPtr->buffer,&len);
    return (len == 0);
}

void
expStateFree(esPtr)
    ExpState *esPtr;
{
  if (esPtr->fdBusy) {
    close(esPtr->fdin);
  }

    esPtr->valid = FALSE;
    
    if (!esPtr->keepForever) {
	ckfree((char *)esPtr);
    }
}

/* close all connections
 * 
 * The kernel would actually do this by default, however Tcl is going to come
 * along later and try to reap its exec'd processes.  If we have inherited any
 * via spawn -open, Tcl can hang if we don't close the connections first.
 */
void
exp_close_all(interp)
Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ExpState *esPtr;

    /* no need to keep things in sync (i.e., tsdPtr, count) since we could only
       be doing this if we're exiting.  Just close everything down. */

    for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) {
	exp_close(interp,esPtr);
    }
}

/* wait for any of our own spawned processes we call waitpid rather
 * than wait to avoid running into someone else's processes.  Yes,
 * according to Ousterhout this is the best way to do it.
 * returns the ExpState or 0 if nothing to wait on */
ExpState *
expWaitOnAny()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int result;
    ExpState *esPtr;

    for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) {
	if (esPtr->pid == exp_getpid) continue; /* skip ourself */
	if (esPtr->user_waited) continue;	/* one wait only! */
	if (esPtr->sys_waited) break;
      restart:
	result = waitpid(esPtr->pid,&esPtr->wait,WNOHANG);
	if (result == esPtr->pid) break;
	if (result == 0) continue;	/* busy, try next */
	if (result == -1) {
	    if (errno == EINTR) goto restart;
	    else break;
	}
    }
    return esPtr;
}

ExpState *
expWaitOnOne() {
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ExpState *esPtr;
    int pid;
    /* should really be recoded using the common wait code in command.c */
    WAIT_STATUS_TYPE status;

    pid = wait(&status);
    for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) {
	if (esPtr->pid == pid) {
	    esPtr->sys_waited = TRUE;
	    esPtr->wait = status;
	    return esPtr;
	}
    }
}

void
exp_background_channelhandlers_run_all()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ExpState *esPtr;

    /* kick off any that already have input waiting */
    for (esPtr = tsdPtr->firstExpPtr;esPtr;esPtr = esPtr->nextPtr) {
	/* is bg_interp the best way to check if armed? */
	if (esPtr->bg_interp && !expSizeZero(esPtr)) {
	    exp_background_channelhandler((ClientData)esPtr,0);
	}
    }
}

ExpState *
expCreateChannel(interp,fdin,fdout,pid)
    Tcl_Interp *interp;
    int fdin;
    int fdout;
    int pid;
{
    ExpState *esPtr;
    int mask;
    Tcl_ChannelType *channelTypePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    channelTypePtr = &expChannelType;

    esPtr = (ExpState *) ckalloc((unsigned) sizeof(ExpState));

    esPtr->nextPtr = tsdPtr->firstExpPtr;
    tsdPtr->firstExpPtr = esPtr;

    sprintf(esPtr->name,"exp%d",fdin);

    /*
     * For now, stupidly assume this.  We we will likely have to revisit this
     * later to prevent people from doing stupid things.
     */
    mask = TCL_READABLE | TCL_WRITABLE;

    /* not sure about this - what about adopted channels */
    esPtr->validMask = mask | TCL_EXCEPTION;
    esPtr->fdin = fdin;
    esPtr->fdout = fdout;

    /* set close-on-exec for everything but std channels */
    /* (system and stty commands need access to std channels) */
    if (fdin != 0 && fdin != 2) {
      expCloseOnExec(fdin);
      if (fdin != fdout) expCloseOnExec(fdout);
    }

    esPtr->fdBusy = FALSE;
    esPtr->channel = Tcl_CreateChannel(channelTypePtr, esPtr->name,
	    (ClientData) esPtr, mask);
    Tcl_RegisterChannel(interp,esPtr->channel);
    esPtr->registered = TRUE;
    Tcl_SetChannelOption(interp,esPtr->channel,"-buffering","none");
    Tcl_SetChannelOption(interp,esPtr->channel,"-blocking","0");
    Tcl_SetChannelOption(interp,esPtr->channel,"-translation","lf");

    esPtr->pid = pid;
    esPtr->msize = 0;

    /* initialize a dummy buffer */
    esPtr->buffer = Tcl_NewStringObj("",0);
    Tcl_IncrRefCount(esPtr->buffer);
    esPtr->umsize = exp_default_match_max;
    /* this will reallocate object with an appropriate sized buffer */
    expAdjust(esPtr);

    esPtr->printed = 0;
    esPtr->echoed = 0;
    esPtr->rm_nulls = exp_default_rm_nulls;
    esPtr->parity = exp_default_parity;
    esPtr->key = expect_key++;
    esPtr->force_read = FALSE;
    esPtr->fg_armed = FALSE;
    esPtr->channel_orig = 0;
    esPtr->fd_slave = EXP_NOFD;
#ifdef HAVE_PTYTRAP
    esPtr->slave_name = 0;
#endif /* HAVE_PTYTRAP */
    esPtr->open = TRUE;
    esPtr->notified = FALSE;
    esPtr->user_waited = FALSE;
    esPtr->sys_waited = FALSE;
    esPtr->bg_interp = 0;
    esPtr->bg_status = unarmed;
    esPtr->bg_ecount = 0;
    esPtr->freeWhenBgHandlerUnblocked = FALSE;
    esPtr->keepForever = FALSE;
    esPtr->valid = TRUE;
    tsdPtr->channelCount++;

    return esPtr;
}

void
expChannelInit() {
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tsdPtr->channelCount = 0;
}

Changes to exp_clib.c.

51
52
53
54
55
56
57
58


























59
60
61
62
















63


64
65


66


67
68
69


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90



91


92
93


94






95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#endif

#include <signal.h>
/*#include <memory.h> - deprecated - ANSI C moves them into string.h */
#include "string.h"

#include <errno.h>
#include "exp_rename.h"


























#define EXP_AVOID_INCLUDING_TCL_H
#include "expect.h"
#include "exp_int.h"

















#include "exp_printify.h"



#ifdef NO_STDLIB_H


#include "../compat/stdlib.h"


#else
#include <stdlib.h>		/* for malloc */
#endif



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































#define EXP_MATCH_MAX	2000
/* public */
char *exp_buffer = 0;
char *exp_buffer_end = 0;
char *exp_match = 0;
char *exp_match_end = 0;
int exp_match_max = EXP_MATCH_MAX;	/* bytes */
int exp_full_buffer = FALSE;		/* don't return on full buffer */
int exp_remove_nulls = TRUE;
int exp_timeout = 10;			/* seconds */
int exp_pty_timeout = 5;		/* seconds - see CRAY below */
int exp_autoallocpty = TRUE;		/* if TRUE, we do allocation */
int exp_pty[2];				/* master is [0], slave is [1] */
int exp_pid;
char *exp_stty_init = 0;		/* initial stty args */
int exp_ttycopy = TRUE;			/* copy tty parms from /dev/tty */
int exp_ttyinit = TRUE;			/* set tty parms to sane state */
int exp_console = FALSE;		/* redirect console */
void (*exp_child_exec_prelude)() = 0;





jmp_buf exp_readenv;		/* for interruptable read() */


int exp_reading = FALSE;	/* whether we can longjmp or not */



void debuglog();






int getptymaster();
int getptyslave();
int Exp_StringMatch();

#define sysreturn(x)	return(errno = x, -1)

void exp_init_pty();

/*
   The following functions are linked from the Tcl library.  They
   don't cause anything else in the library to be dragged in, so it
   shouldn't cause any problems (e.g., bloat).

   The functions are relatively small but painful enough that I don't care
   to recode them.  You may, if you absolutely want to get rid of any
   vestiges of Tcl.
*/
extern char *TclGetRegError();
extern void TclRegError();
char *Tcl_ErrnoMsg();



static unsigned int bufsiz = 2*EXP_MATCH_MAX;

static struct f {
	int valid;

	char *buffer;		/* buffer of matchable chars */
	char *buffer_end;	/* one beyond end of matchable chars */
	/*char *match;		/* start of matched string */
	char *match_end;	/* one beyond end of matched string */
	int msize;		/* size of allocate space */
				/* actual size is one larger for null */
} *fs = 0;

static int fd_alloc_max = -1;	/* max fd allocated */








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

|
>
>
|
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















>

>
>
>

>
>


>
>
|
>
>
>
>
>
>
|
|
<














<
<
<
<
<








<







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206





2207
2208
2209
2210
2211
2212
2213
2214

2215
2216
2217
2218
2219
2220
2221
#endif

#include <signal.h>
/*#include <memory.h> - deprecated - ANSI C moves them into string.h */
#include "string.h"

#include <errno.h>

#ifdef NO_STDLIB_H

/*
 * Tcl's compat/stdlib.h
 */

/*
 * stdlib.h --
 *
 *	Declares facilities exported by the "stdlib" portion of
 *	the C library.  This file isn't complete in the ANSI-C
 *	sense;  it only declares things that are needed by Tcl.
 *	This file is needed even on many systems with their own
 *	stdlib.h (e.g. SunOS) because not all stdlib.h files
 *	declare all the procedures needed here (such as strtod).
 *
 * Copyright (c) 1991 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: exp_clib.c,v 5.28.1.1.2.13 1999/12/22 17:45:57 libes Exp $
 */

#ifndef _STDLIB
#define _STDLIB

#include <tcl.h>

extern void		abort _ANSI_ARGS_((void));
extern double		atof _ANSI_ARGS_((CONST char *string));
extern int		atoi _ANSI_ARGS_((CONST char *string));
extern long		atol _ANSI_ARGS_((CONST char *string));
extern char *		calloc _ANSI_ARGS_((unsigned int numElements,
			    unsigned int size));
extern void		exit _ANSI_ARGS_((int status));
extern int		free _ANSI_ARGS_((char *blockPtr));
extern char *		getenv _ANSI_ARGS_((CONST char *name));
extern char *		malloc _ANSI_ARGS_((unsigned int numBytes));
extern void		qsort _ANSI_ARGS_((VOID *base, int n, int size,
			    int (*compar)(CONST VOID *element1, CONST VOID
			    *element2)));
extern char *		realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes));
extern double		strtod _ANSI_ARGS_((CONST char *string, char **endPtr));
extern long		strtol _ANSI_ARGS_((CONST char *string, char **endPtr,
			    int base));
extern unsigned long	strtoul _ANSI_ARGS_((CONST char *string,
			    char **endPtr, int base));

#endif /* _STDLIB */

/*
 * end of Tcl's compat/stdlib.h
 */

#else
#include <stdlib.h>		/* for malloc */
#endif

#include "expect.h"
#define TclRegError exp_TclRegError

/*
 * regexp code - from tcl8.0.4/generic/regexp.c
 */

/*
 * TclRegComp and TclRegExec -- TclRegSub is elsewhere
 *
 *	Copyright (c) 1986 by University of Toronto.
 *	Written by Henry Spencer.  Not derived from licensed software.
 *
 *	Permission is granted to anyone to use this software for any
 *	purpose on any computer system, and to redistribute it freely,
 *	subject to the following restrictions:
 *
 *	1. The author is not responsible for the consequences of use of
 *		this software, no matter how awful, even if they arise
 *		from defects in it.
 *
 *	2. The origin of this software must not be misrepresented, either
 *		by explicit claim or by omission.
 *
 *	3. Altered versions must be plainly marked as such, and must not
 *		be misrepresented as being the original software.
 *
 * Beware that some of this code is subtly aware of the way operator
 * precedence is structured in regular expressions.  Serious changes in
 * regular-expression syntax might require a total rethink.
 *
 * *** NOTE: this code has been altered slightly for use in Tcl: ***
 * *** 1. Use ckalloc and ckfree instead of  malloc and free.	 ***
 * *** 2. Add extra argument to regexp to specify the real	 ***
 * ***    start of the string separately from the start of the	 ***
 * ***    current search. This is needed to search for multiple	 ***
 * ***    matches within a string.				 ***
 * *** 3. Names have been changed, e.g. from regcomp to		 ***
 * ***    TclRegComp, to avoid clashes with other 		 ***
 * ***    regexp implementations used by applications. 		 ***
 * *** 4. Added errMsg declaration and TclRegError procedure	 ***
 * *** 5. Various lint-like things, such as casting arguments	 ***
 * ***	  in procedure calls.					 ***
 *
 * *** NOTE: This code has been altered for use in MT-Sturdy Tcl ***
 * *** 1. All use of static variables has been changed to access ***
 * ***    fields of a structure.                                 ***
 * *** 2. This in addition to changes to TclRegError makes the   ***
 * ***    code multi-thread safe.                                ***
 *
 * RCS: @(#) $Id: exp_clib.c,v 5.28.1.1.2.13 1999/12/22 17:45:57 libes Exp $
 */

#if 0
#include "tclInt.h"
#include "tclPort.h"
#endif

/*
 * The variable below is set to NULL before invoking regexp functions
 * and checked after those functions.  If an error occurred then TclRegError
 * will set the variable to point to a (static) error message.  This
 * mechanism unfortunately does not support multi-threading, but the
 * procedures TclRegError and TclGetRegError can be modified to use
 * thread-specific storage for the variable and thereby make the code
 * thread-safe.
 */

static char *errMsg = NULL;

/*
 * The "internal use only" fields in regexp.h are present to pass info from
 * compile to execute that permits the execute phase to run lots faster on
 * simple cases.  They are:
 *
 * regstart	char that must begin a match; '\0' if none obvious
 * reganch	is the match anchored (at beginning-of-line only)?
 * regmust	string (pointer into program) that match must include, or NULL
 * regmlen	length of regmust string
 *
 * Regstart and reganch permit very fast decisions on suitable starting points
 * for a match, cutting down the work a lot.  Regmust permits fast rejection
 * of lines that cannot possibly match.  The regmust tests are costly enough
 * that TclRegComp() supplies a regmust only if the r.e. contains something
 * potentially expensive (at present, the only such thing detected is * or +
 * at the start of the r.e., which can involve a lot of backup).  Regmlen is
 * supplied because the test in TclRegExec() needs it and TclRegComp() is
 * computing it anyway.
 */

/*
 * Structure for regexp "program".  This is essentially a linear encoding
 * of a nondeterministic finite-state machine (aka syntax charts or
 * "railroad normal form" in parsing technology).  Each node is an opcode
 * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
 * all nodes except BRANCH implement concatenation; a "next" pointer with
 * a BRANCH on both ends of it is connecting two alternatives.  (Here we
 * have one of the subtle syntax dependencies:  an individual BRANCH (as
 * opposed to a collection of them) is never concatenated with anything
 * because of operator precedence.)  The operand of some types of node is
 * a literal string; for others, it is a node leading into a sub-FSM.  In
 * particular, the operand of a BRANCH node is the first node of the branch.
 * (NB this is *not* a tree structure:  the tail of the branch connects
 * to the thing following the set of BRANCHes.)  The opcodes are:
 */

/* definition	number	opnd?	meaning */
#define	END	0	/* no	End of program. */
#define	BOL	1	/* no	Match "" at beginning of line. */
#define	EOL	2	/* no	Match "" at end of line. */
#define	ANY	3	/* no	Match any one character. */
#define	ANYOF	4	/* str	Match any character in this string. */
#define	ANYBUT	5	/* str	Match any character not in this string. */
#define	BRANCH	6	/* node	Match this alternative, or the next... */
#define	BACK	7	/* no	Match "", "next" ptr points backward. */
#define	EXACTLY	8	/* str	Match this string. */
#define	NOTHING	9	/* no	Match empty string. */
#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
#define	OPEN	20	/* no	Mark this point in input as start of #n. */
			/*	OPEN+1 is number 1, etc. */
#define	CLOSE	(OPEN+NSUBEXP)	/* no	Analogous to OPEN. */

/*
 * Opcode notes:
 *
 * BRANCH	The set of branches constituting a single choice are hooked
 *		together with their "next" pointers, since precedence prevents
 *		anything being concatenated to any individual branch.  The
 *		"next" pointer of the last BRANCH in a choice points to the
 *		thing following the whole choice.  This is also where the
 *		final "next" pointer of each individual branch points; each
 *		branch starts with the operand node of a BRANCH node.
 *
 * BACK		Normal "next" pointers all implicitly point forward; BACK
 *		exists to make loop structures possible.
 *
 * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
 *		BRANCH structures using BACK.  Simple cases (one character
 *		per match) are implemented with STAR and PLUS for speed
 *		and to minimize recursive plunges.
 *
 * OPEN,CLOSE	...are numbered at compile time.
 */

/*
 * A node is one char of opcode followed by two chars of "next" pointer.
 * "Next" pointers are stored as two 8-bit pieces, high order first.  The
 * value is a positive offset from the opcode of the node containing it.
 * An operand, if any, simply follows the node.  (Note that much of the
 * code generation knows about this implicit relationship.)
 *
 * Using two bytes for the "next" pointer is vast overkill for most things,
 * but allows patterns to get big without disasters.
 */
#define	OP(p)	(*(p))
#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
#define	OPERAND(p)	((p) + 3)

/*
 * See regmagic.h for one further detail of program structure.
 */


/*
 * Utility definitions.
 */
#ifndef CHARBITS
#define	UCHARAT(p)	((int)*(unsigned char *)(p))
#else
#define	UCHARAT(p)	((int)*(p)&CHARBITS)
#endif

#define	FAIL(m)	{ TclRegError(m); return(NULL); }
#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
#define	META	"^$.[()|?+*\\"

/*
 * Flags to be passed up and down.
 */
#define	HASWIDTH	01	/* Known never to match null string. */
#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
#define	SPSTART		04	/* Starts with * or +. */
#define	WORST		0	/* Worst case. */

/*
 * Global work variables for TclRegComp().
 */
struct regcomp_state  {
    char *regparse;		/* Input-scan pointer. */
    int regnpar;		/* () count. */
    char *regcode;		/* Code-emit pointer; &regdummy = don't. */
    long regsize;		/* Code size. */
};

static char regdummy;

/*
 * The first byte of the regexp internal "program" is actually this magic
 * number; the start node begins in the second byte.
 */
#define	MAGIC	0234


/*
 * Forward declarations for TclRegComp()'s friends.
 */

static char *		reg _ANSI_ARGS_((int paren, int *flagp,
			    struct regcomp_state *rcstate));
static char *		regatom _ANSI_ARGS_((int *flagp,
			    struct regcomp_state *rcstate));
static char *		regbranch _ANSI_ARGS_((int *flagp,
			    struct regcomp_state *rcstate));
static void		regc _ANSI_ARGS_((int b,
			    struct regcomp_state *rcstate));
static void		reginsert _ANSI_ARGS_((int op, char *opnd,
			    struct regcomp_state *rcstate));
static char *		regnext _ANSI_ARGS_((char *p));
static char *		regnode _ANSI_ARGS_((int op,
			    struct regcomp_state *rcstate));
static void 		regoptail _ANSI_ARGS_((char *p, char *val));
static char *		regpiece _ANSI_ARGS_((int *flagp,
			    struct regcomp_state *rcstate));
static void 		regtail _ANSI_ARGS_((char *p, char *val));

#ifdef STRCSPN
static int strcspn _ANSI_ARGS_((char *s1, char *s2));
#endif

/*
 - TclRegComp - compile a regular expression into internal code
 *
 * We can't allocate space until we know how big the compiled form will be,
 * but we can't compile it (and thus know how big it is) until we've got a
 * place to put the code.  So we cheat:  we compile it twice, once with code
 * generation turned off and size counting turned on, and once "for real".
 * This also means that we don't allocate space until we are sure that the
 * thing really will compile successfully, and we never have to move the
 * code and thus invalidate pointers into it.  (Note that it has to be in
 * one piece because free() must be able to free it all.)
 *
 * Beware that the optimization-preparation code in here knows about some
 * of the structure of the compiled regexp.
 */
regexp *
TclRegComp(exp)
char *exp;
{
	register regexp *r;
	register char *scan;
	register char *longest;
	register int len;
	int flags;
	struct regcomp_state state;
	struct regcomp_state *rcstate= &state;

	if (exp == NULL)
		FAIL("NULL argument");

	/* First pass: determine size, legality. */
	rcstate->regparse = exp;
	rcstate->regnpar = 1;
	rcstate->regsize = 0L;
	rcstate->regcode = &regdummy;
	regc(MAGIC, rcstate);
	if (reg(0, &flags, rcstate) == NULL)
		return(NULL);

	/* Small enough for pointer-storage convention? */
	if (rcstate->regsize >= 32767L)		/* Probably could be 65535L. */
		FAIL("regexp too big");

	/* Allocate space. */
	r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)rcstate->regsize);
	if (r == NULL)
		FAIL("out of space");

	/* Second pass: emit code. */
	rcstate->regparse = exp;
	rcstate->regnpar = 1;
	rcstate->regcode = r->program;
	regc(MAGIC, rcstate);
	if (reg(0, &flags, rcstate) == NULL)
		return(NULL);

	/* Dig out information for optimizations. */
	r->regstart = '\0';	/* Worst-case defaults. */
	r->reganch = 0;
	r->regmust = NULL;
	r->regmlen = 0;
	scan = r->program+1;			/* First BRANCH. */
	if (OP(regnext(scan)) == END) {		/* Only one top-level choice. */
		scan = OPERAND(scan);

		/* Starting-point info. */
		if (OP(scan) == EXACTLY)
			r->regstart = *OPERAND(scan);
		else if (OP(scan) == BOL)
			r->reganch++;

		/*
		 * If there's something expensive in the r.e., find the
		 * longest literal string that must appear and make it the
		 * regmust.  Resolve ties in favor of later strings, since
		 * the regstart check works with the beginning of the r.e.
		 * and avoiding duplication strengthens checking.  Not a
		 * strong reason, but sufficient in the absence of others.
		 */
		if (flags&SPSTART) {
			longest = NULL;
			len = 0;
			for (; scan != NULL; scan = regnext(scan))
				if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) {
					longest = OPERAND(scan);
					len = strlen(OPERAND(scan));
				}
			r->regmust = longest;
			r->regmlen = len;
		}
	}

	return(r);
}

/*
 - reg - regular expression, i.e. main body or parenthesized thing
 *
 * Caller must absorb opening parenthesis.
 *
 * Combining parenthesis handling with the base level of regular expression
 * is a trifle forced, but the need to tie the tails of the branches to what
 * follows makes it hard to avoid.
 */
static char *
reg(paren, flagp, rcstate)
int paren;			/* Parenthesized? */
int *flagp;
struct regcomp_state *rcstate;
{
	register char *ret;
	register char *br;
	register char *ender;
	register int parno = 0;
	int flags;

	*flagp = HASWIDTH;	/* Tentatively. */

	/* Make an OPEN node, if parenthesized. */
	if (paren) {
		if (rcstate->regnpar >= NSUBEXP)
			FAIL("too many ()");
		parno = rcstate->regnpar;
		rcstate->regnpar++;
		ret = regnode(OPEN+parno,rcstate);
	} else
		ret = NULL;

	/* Pick up the branches, linking them together. */
	br = regbranch(&flags,rcstate);
	if (br == NULL)
		return(NULL);
	if (ret != NULL)
		regtail(ret, br);	/* OPEN -> first. */
	else
		ret = br;
	if (!(flags&HASWIDTH))
		*flagp &= ~HASWIDTH;
	*flagp |= flags&SPSTART;
	while (*rcstate->regparse == '|') {
		rcstate->regparse++;
		br = regbranch(&flags,rcstate);
		if (br == NULL)
			return(NULL);
		regtail(ret, br);	/* BRANCH -> BRANCH. */
		if (!(flags&HASWIDTH))
			*flagp &= ~HASWIDTH;
		*flagp |= flags&SPSTART;
	}

	/* Make a closing node, and hook it on the end. */
	ender = regnode((paren) ? CLOSE+parno : END,rcstate);	
	regtail(ret, ender);

	/* Hook the tails of the branches to the closing node. */
	for (br = ret; br != NULL; br = regnext(br))
		regoptail(br, ender);

	/* Check for proper termination. */
	if (paren && *rcstate->regparse++ != ')') {
		FAIL("unmatched ()");
	} else if (!paren && *rcstate->regparse != '\0') {
		if (*rcstate->regparse == ')') {
			FAIL("unmatched ()");
		} else
			FAIL("junk on end");	/* "Can't happen". */
		/* NOTREACHED */
	}

	return(ret);
}

/*
 - regbranch - one alternative of an | operator
 *
 * Implements the concatenation operator.
 */
static char *
regbranch(flagp, rcstate)
int *flagp;
struct regcomp_state *rcstate;
{
	register char *ret;
	register char *chain;
	register char *latest;
	int flags;

	*flagp = WORST;		/* Tentatively. */

	ret = regnode(BRANCH,rcstate);
	chain = NULL;
	while (*rcstate->regparse != '\0' && *rcstate->regparse != '|' &&
				*rcstate->regparse != ')') {
		latest = regpiece(&flags, rcstate);
		if (latest == NULL)
			return(NULL);
		*flagp |= flags&HASWIDTH;
		if (chain == NULL)	/* First piece. */
			*flagp |= flags&SPSTART;
		else
			regtail(chain, latest);
		chain = latest;
	}
	if (chain == NULL)	/* Loop ran zero times. */
		(void) regnode(NOTHING,rcstate);

	return(ret);
}

/*
 - regpiece - something followed by possible [*+?]
 *
 * Note that the branching code sequences used for ? and the general cases
 * of * and + are somewhat optimized:  they use the same NOTHING node as
 * both the endmarker for their branch list and the body of the last branch.
 * It might seem that this node could be dispensed with entirely, but the
 * endmarker role is not redundant.
 */
static char *
regpiece(flagp, rcstate)
int *flagp;
struct regcomp_state *rcstate;
{
	register char *ret;
	register char op;
	register char *next;
	int flags;

	ret = regatom(&flags,rcstate);
	if (ret == NULL)
		return(NULL);

	op = *rcstate->regparse;
	if (!ISMULT(op)) {
		*flagp = flags;
		return(ret);
	}

	if (!(flags&HASWIDTH) && op != '?')
		FAIL("*+ operand could be empty");
	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);

	if (op == '*' && (flags&SIMPLE))
		reginsert(STAR, ret, rcstate);
	else if (op == '*') {
		/* Emit x* as (x&|), where & means "self". */
		reginsert(BRANCH, ret, rcstate);			/* Either x */
		regoptail(ret, regnode(BACK,rcstate));		/* and loop */
		regoptail(ret, ret);			/* back */
		regtail(ret, regnode(BRANCH,rcstate));		/* or */
		regtail(ret, regnode(NOTHING,rcstate));		/* null. */
	} else if (op == '+' && (flags&SIMPLE))
		reginsert(PLUS, ret, rcstate);
	else if (op == '+') {
		/* Emit x+ as x(&|), where & means "self". */
		next = regnode(BRANCH,rcstate);			/* Either */
		regtail(ret, next);
		regtail(regnode(BACK,rcstate), ret);		/* loop back */
		regtail(next, regnode(BRANCH,rcstate));		/* or */
		regtail(ret, regnode(NOTHING,rcstate));		/* null. */
	} else if (op == '?') {
		/* Emit x? as (x|) */
		reginsert(BRANCH, ret, rcstate);			/* Either x */
		regtail(ret, regnode(BRANCH,rcstate));		/* or */
		next = regnode(NOTHING,rcstate);		/* null. */
		regtail(ret, next);
		regoptail(ret, next);
	}
	rcstate->regparse++;
	if (ISMULT(*rcstate->regparse))
		FAIL("nested *?+");

	return(ret);
}

/*
 - regatom - the lowest level
 *
 * Optimization:  gobbles an entire sequence of ordinary characters so that
 * it can turn them into a single node, which is smaller to store and
 * faster to run.  Backslashed characters are exceptions, each becoming a
 * separate node; the code is simpler that way and it's not worth fixing.
 */
static char *
regatom(flagp, rcstate)
int *flagp;
struct regcomp_state *rcstate;
{
	register char *ret;
	int flags;

	*flagp = WORST;		/* Tentatively. */

	switch (*rcstate->regparse++) {
	case '^':
		ret = regnode(BOL,rcstate);
		break;
	case '$':
		ret = regnode(EOL,rcstate);
		break;
	case '.':
		ret = regnode(ANY,rcstate);
		*flagp |= HASWIDTH|SIMPLE;
		break;
	case '[': {
			register int clss;
			register int classend;

			if (*rcstate->regparse == '^') {	/* Complement of range. */
				ret = regnode(ANYBUT,rcstate);
				rcstate->regparse++;
			} else
				ret = regnode(ANYOF,rcstate);
			if (*rcstate->regparse == ']' || *rcstate->regparse == '-')
				regc(*rcstate->regparse++,rcstate);
			while (*rcstate->regparse != '\0' && *rcstate->regparse != ']') {
				if (*rcstate->regparse == '-') {
					rcstate->regparse++;
					if (*rcstate->regparse == ']' || *rcstate->regparse == '\0')
						regc('-',rcstate);
					else {
						clss = UCHARAT(rcstate->regparse-2)+1;
						classend = UCHARAT(rcstate->regparse);
						if (clss > classend+1)
							FAIL("invalid [] range");
						for (; clss <= classend; clss++)
							regc((char)clss,rcstate);
						rcstate->regparse++;
					}
				} else
					regc(*rcstate->regparse++,rcstate);
			}
			regc('\0',rcstate);
			if (*rcstate->regparse != ']')
				FAIL("unmatched []");
			rcstate->regparse++;
			*flagp |= HASWIDTH|SIMPLE;
		}
		break;
	case '(':
		ret = reg(1, &flags, rcstate);
		if (ret == NULL)
			return(NULL);
		*flagp |= flags&(HASWIDTH|SPSTART);
		break;
	case '\0':
	case '|':
	case ')':
		FAIL("internal urp");	/* Supposed to be caught earlier. */
		/* NOTREACHED */
	case '?':
	case '+':
	case '*':
		FAIL("?+* follows nothing");
		/* NOTREACHED */
	case '\\':
		if (*rcstate->regparse == '\0')
			FAIL("trailing \\");
		ret = regnode(EXACTLY,rcstate);
		regc(*rcstate->regparse++,rcstate);
		regc('\0',rcstate);
		*flagp |= HASWIDTH|SIMPLE;
		break;
	default: {
			register int len;
			register char ender;

			rcstate->regparse--;
			len = strcspn(rcstate->regparse, META);
			if (len <= 0)
				FAIL("internal disaster");
			ender = *(rcstate->regparse+len);
			if (len > 1 && ISMULT(ender))
				len--;		/* Back off clear of ?+* operand. */
			*flagp |= HASWIDTH;
			if (len == 1)
				*flagp |= SIMPLE;
			ret = regnode(EXACTLY,rcstate);
			while (len > 0) {
				regc(*rcstate->regparse++,rcstate);
				len--;
			}
			regc('\0',rcstate);
		}
		break;
	}

	return(ret);
}

/*
 - regnode - emit a node
 */
static char *			/* Location. */
regnode(op, rcstate)
int op;
struct regcomp_state *rcstate;
{
	register char *ret;
	register char *ptr;

	ret = rcstate->regcode;
	if (ret == &regdummy) {
		rcstate->regsize += 3;
		return(ret);
	}

	ptr = ret;
	*ptr++ = (char)op;
	*ptr++ = '\0';		/* Null "next" pointer. */
	*ptr++ = '\0';
	rcstate->regcode = ptr;

	return(ret);
}

/*
 - regc - emit (if appropriate) a byte of code
 */
static void
regc(b, rcstate)
int b;
struct regcomp_state *rcstate;
{
	if (rcstate->regcode != &regdummy)
		*rcstate->regcode++ = (char)b;
	else
		rcstate->regsize++;
}

/*
 - reginsert - insert an operator in front of already-emitted operand
 *
 * Means relocating the operand.
 */
static void
reginsert(op, opnd, rcstate)
int op;
char *opnd;
struct regcomp_state *rcstate;
{
	register char *src;
	register char *dst;
	register char *place;

	if (rcstate->regcode == &regdummy) {
		rcstate->regsize += 3;
		return;
	}

	src = rcstate->regcode;
	rcstate->regcode += 3;
	dst = rcstate->regcode;
	while (src > opnd)
		*--dst = *--src;

	place = opnd;		/* Op node, where operand used to be. */
	*place++ = (char)op;
	*place++ = '\0';
	*place = '\0';
}

/*
 - regtail - set the next-pointer at the end of a node chain
 */
static void
regtail(p, val)
char *p;
char *val;
{
	register char *scan;
	register char *temp;
	register int offset;

	if (p == &regdummy)
		return;

	/* Find last node. */
	scan = p;
	for (;;) {
		temp = regnext(scan);
		if (temp == NULL)
			break;
		scan = temp;
	}

	if (OP(scan) == BACK)
		offset = scan - val;
	else
		offset = val - scan;
	*(scan+1) = (char)((offset>>8)&0377);
	*(scan+2) = (char)(offset&0377);
}

/*
 - regoptail - regtail on operand of first argument; nop if operandless
 */
static void
regoptail(p, val)
char *p;
char *val;
{
	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
	if (p == NULL || p == &regdummy || OP(p) != BRANCH)
		return;
	regtail(OPERAND(p), val);
}

/*
 * TclRegExec and friends
 */

/*
 * Global work variables for TclRegExec().
 */
struct regexec_state  {
    char *reginput;		/* String-input pointer. */
    char *regbol;		/* Beginning of input, for ^ check. */
    char **regstartp;	/* Pointer to startp array. */
    char **regendp;		/* Ditto for endp. */
};

/*
 * Forwards.
 */
static int 		regtry _ANSI_ARGS_((regexp *prog, char *string,
			    struct regexec_state *restate));
static int 		regmatch _ANSI_ARGS_((char *prog,
			    struct regexec_state *restate));
static int 		regrepeat _ANSI_ARGS_((char *p,
			    struct regexec_state *restate));

#ifdef DEBUG
int regnarrate = 0;
void regdump _ANSI_ARGS_((regexp *r));
static char *regprop _ANSI_ARGS_((char *op));
#endif

/*
 - TclRegExec - match a regexp against a string
 */
int
TclRegExec(prog, string, start)
register regexp *prog;
register char *string;
char *start;
{
	register char *s;
	struct regexec_state state;
	struct regexec_state *restate= &state;

	/* Be paranoid... */
	if (prog == NULL || string == NULL) {
		TclRegError("NULL parameter");
		return(0);
	}

	/* Check validity of program. */
	if (UCHARAT(prog->program) != MAGIC) {
		TclRegError("corrupted program");
		return(0);
	}

	/* If there is a "must appear" string, look for it. */
	if (prog->regmust != NULL) {
		s = string;
		while ((s = strchr(s, prog->regmust[0])) != NULL) {
			if (strncmp(s, prog->regmust, (size_t) prog->regmlen)
			    == 0)
				break;	/* Found it. */
			s++;
		}
		if (s == NULL)	/* Not present. */
			return(0);
	}

	/* Mark beginning of line for ^ . */
	restate->regbol = start;

	/* Simplest case:  anchored match need be tried only once. */
	if (prog->reganch)
		return(regtry(prog, string, restate));

	/* Messy cases:  unanchored match. */
	s = string;
	if (prog->regstart != '\0')
		/* We know what char it must start with. */
		while ((s = strchr(s, prog->regstart)) != NULL) {
			if (regtry(prog, s, restate))
				return(1);
			s++;
		}
	else
		/* We don't -- general case. */
		do {
			if (regtry(prog, s, restate))
				return(1);
		} while (*s++ != '\0');

	/* Failure. */
	return(0);
}

/*
 - regtry - try match at specific point
 */
static int			/* 0 failure, 1 success */
regtry(prog, string, restate)
regexp *prog;
char *string;
struct regexec_state *restate;
{
	register int i;
	register char **sp;
	register char **ep;

	restate->reginput = string;
	restate->regstartp = prog->startp;
	restate->regendp = prog->endp;

	sp = prog->startp;
	ep = prog->endp;
	for (i = NSUBEXP; i > 0; i--) {
		*sp++ = NULL;
		*ep++ = NULL;
	}
	if (regmatch(prog->program + 1,restate)) {
		prog->startp[0] = string;
		prog->endp[0] = restate->reginput;
		return(1);
	} else
		return(0);
}

/*
 - regmatch - main matching routine
 *
 * Conceptually the strategy is simple:  check to see whether the current
 * node matches, call self recursively to see whether the rest matches,
 * and then act accordingly.  In practice we make some effort to avoid
 * recursion, in particular by going through "ordinary" nodes (that don't
 * need to know whether the rest of the match failed) by a loop instead of
 * by recursion.
 */
static int			/* 0 failure, 1 success */
regmatch(prog, restate)
char *prog;
struct regexec_state *restate;
{
    register char *scan;	/* Current node. */
    char *next;		/* Next node. */

    scan = prog;
#ifdef DEBUG
    if (scan != NULL && regnarrate)
	fprintf(stderr, "%s(\n", regprop(scan));
#endif
    while (scan != NULL) {
#ifdef DEBUG
	if (regnarrate)
	    fprintf(stderr, "%s...\n", regprop(scan));
#endif
	next = regnext(scan);

	switch (OP(scan)) {
	    case BOL:
		if (restate->reginput != restate->regbol) {
		    return 0;
		}
		break;
	    case EOL:
		if (*restate->reginput != '\0') {
		    return 0;
		}
		break;
	    case ANY:
		if (*restate->reginput == '\0') {
		    return 0;
		}
		restate->reginput++;
		break;
	    case EXACTLY: {
		register int len;
		register char *opnd;

		opnd = OPERAND(scan);
		/* Inline the first character, for speed. */
		if (*opnd != *restate->reginput) {
		    return 0 ;
		}
		len = strlen(opnd);
		if (len > 1 && strncmp(opnd, restate->reginput, (size_t) len)
			!= 0) {
		    return 0;
		}
		restate->reginput += len;
		break;
	    }
	    case ANYOF:
		if (*restate->reginput == '\0'
			|| strchr(OPERAND(scan), *restate->reginput) == NULL) {
		    return 0;
		}
		restate->reginput++;
		break;
	    case ANYBUT:
		if (*restate->reginput == '\0'
			|| strchr(OPERAND(scan), *restate->reginput) != NULL) {
		    return 0;
		}
		restate->reginput++;
		break;
	    case NOTHING:
		break;
	    case BACK:
		break;
	    case OPEN+1:
	    case OPEN+2:
	    case OPEN+3:
	    case OPEN+4:
	    case OPEN+5:
	    case OPEN+6:
	    case OPEN+7:
	    case OPEN+8:
	    case OPEN+9: {
		register int no;
		register char *save;

	doOpen:
		no = OP(scan) - OPEN;
		save = restate->reginput;

		if (regmatch(next,restate)) {
		    /*
		     * Don't set startp if some later invocation of the
		     * same parentheses already has.
		     */
		    if (restate->regstartp[no] == NULL) {
			restate->regstartp[no] = save;
		    }
		    return 1;
		} else {
		    return 0;
		}
	    }
	    case CLOSE+1:
	    case CLOSE+2:
	    case CLOSE+3:
	    case CLOSE+4:
	    case CLOSE+5:
	    case CLOSE+6:
	    case CLOSE+7:
	    case CLOSE+8:
	    case CLOSE+9: {
		register int no;
		register char *save;

	doClose:
		no = OP(scan) - CLOSE;
		save = restate->reginput;

		if (regmatch(next,restate)) {
				/*
				 * Don't set endp if some later
				 * invocation of the same parentheses
				 * already has.
				 */
		    if (restate->regendp[no] == NULL)
			restate->regendp[no] = save;
		    return 1;
		} else {
		    return 0;
		}
	    }
	    case BRANCH: {
		register char *save;

		if (OP(next) != BRANCH) { /* No choice. */
		    next = OPERAND(scan); /* Avoid recursion. */
		} else {
		    do {
			save = restate->reginput;
			if (regmatch(OPERAND(scan),restate))
			    return(1);
			restate->reginput = save;
			scan = regnext(scan);
		    } while (scan != NULL && OP(scan) == BRANCH);
		    return 0;
		}
		break;
	    }
	    case STAR:
	    case PLUS: {
		register char nextch;
		register int no;
		register char *save;
		register int min;

		/*
		 * Lookahead to avoid useless match attempts
		 * when we know what character comes next.
		 */
		nextch = '\0';
		if (OP(next) == EXACTLY)
		    nextch = *OPERAND(next);
		min = (OP(scan) == STAR) ? 0 : 1;
		save = restate->reginput;
		no = regrepeat(OPERAND(scan),restate);
		while (no >= min) {
		    /* If it could work, try it. */
		    if (nextch == '\0' || *restate->reginput == nextch)
			if (regmatch(next,restate))
			    return(1);
		    /* Couldn't or didn't -- back up. */
		    no--;
		    restate->reginput = save + no;
		}
		return(0);
	    }
	    case END:
		return(1);	/* Success! */
	    default:
		if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) {
		    goto doOpen;
		} else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) {
		    goto doClose;
		}
		TclRegError("memory corruption");
		return 0;
	}

	scan = next;
    }

    /*
     * We get here only if there's trouble -- normally "case END" is
     * the terminating point.
     */
    TclRegError("corrupted pointers");
    return(0);
}

/*
 - regrepeat - repeatedly match something simple, report how many
 */
static int
regrepeat(p, restate)
char *p;
struct regexec_state *restate;
{
	register int count = 0;
	register char *scan;
	register char *opnd;

	scan = restate->reginput;
	opnd = OPERAND(p);
	switch (OP(p)) {
	case ANY:
		count = strlen(scan);
		scan += count;
		break;
	case EXACTLY:
		while (*opnd == *scan) {
			count++;
			scan++;
		}
		break;
	case ANYOF:
		while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
			count++;
			scan++;
		}
		break;
	case ANYBUT:
		while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
			count++;
			scan++;
		}
		break;
	default:		/* Oh dear.  Called inappropriately. */
		TclRegError("internal foulup");
		count = 0;	/* Best compromise. */
		break;
	}
	restate->reginput = scan;

	return(count);
}

/*
 - regnext - dig the "next" pointer out of a node
 */
static char *
regnext(p)
register char *p;
{
	register int offset;

	if (p == &regdummy)
		return(NULL);

	offset = NEXT(p);
	if (offset == 0)
		return(NULL);

	if (OP(p) == BACK)
		return(p-offset);
	else
		return(p+offset);
}

#ifdef DEBUG

static char *regprop();

/*
 - regdump - dump a regexp onto stdout in vaguely comprehensible form
 */
void
regdump(r)
regexp *r;
{
	register char *s;
	register char op = EXACTLY;	/* Arbitrary non-END op. */
	register char *next;


	s = r->program + 1;
	while (op != END) {	/* While that wasn't END last time... */
		op = OP(s);
		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
		next = regnext(s);
		if (next == NULL)		/* Next ptr. */
			printf("(0)");
		else 
			printf("(%d)", (s-r->program)+(next-s));
		s += 3;
		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
			/* Literal string, where present. */
			while (*s != '\0') {
				putchar(*s);
				s++;
			}
			s++;
		}
		putchar('\n');
	}

	/* Header fields of interest. */
	if (r->regstart != '\0')
		printf("start `%c' ", r->regstart);
	if (r->reganch)
		printf("anchored ");
	if (r->regmust != NULL)
		printf("must have \"%s\"", r->regmust);
	printf("\n");
}

/*
 - regprop - printable representation of opcode
 */
static char *
regprop(op)
char *op;
{
	register char *p;
	static char buf[50];

	(void) strcpy(buf, ":");

	switch (OP(op)) {
	case BOL:
		p = "BOL";
		break;
	case EOL:
		p = "EOL";
		break;
	case ANY:
		p = "ANY";
		break;
	case ANYOF:
		p = "ANYOF";
		break;
	case ANYBUT:
		p = "ANYBUT";
		break;
	case BRANCH:
		p = "BRANCH";
		break;
	case EXACTLY:
		p = "EXACTLY";
		break;
	case NOTHING:
		p = "NOTHING";
		break;
	case BACK:
		p = "BACK";
		break;
	case END:
		p = "END";
		break;
	case OPEN+1:
	case OPEN+2:
	case OPEN+3:
	case OPEN+4:
	case OPEN+5:
	case OPEN+6:
	case OPEN+7:
	case OPEN+8:
	case OPEN+9:
		sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
		p = NULL;
		break;
	case CLOSE+1:
	case CLOSE+2:
	case CLOSE+3:
	case CLOSE+4:
	case CLOSE+5:
	case CLOSE+6:
	case CLOSE+7:
	case CLOSE+8:
	case CLOSE+9:
		sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
		p = NULL;
		break;
	case STAR:
		p = "STAR";
		break;
	case PLUS:
		p = "PLUS";
		break;
	default:
		if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) {
		    sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
		    p = NULL;
		    break;
		} else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) {
		    sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
		    p = NULL;
		} else {
		    TclRegError("corrupted opcode");
		}
		break;
	}
	if (p != NULL)
		(void) strcat(buf, p);
	return(buf);
}
#endif

/*
 * The following is provided for those people who do not have strcspn() in
 * their C libraries.  They should get off their butts and do something
 * about it; at least one public-domain implementation of those (highly
 * useful) string routines has been published on Usenet.
 */
#ifdef STRCSPN
/*
 * strcspn - find length of initial segment of s1 consisting entirely
 * of characters not from s2
 */

static int
strcspn(s1, s2)
char *s1;
char *s2;
{
	register char *scan1;
	register char *scan2;
	register int count;

	count = 0;
	for (scan1 = s1; *scan1 != '\0'; scan1++) {
		for (scan2 = s2; *scan2 != '\0';)	/* ++ moved down. */
			if (*scan1 == *scan2++)
				return(count);
		count++;
	}
	return(count);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * TclRegError --
 *
 *	This procedure is invoked by the regexp code when an error
 *	occurs.  It saves the error message so it can be seen by the
 *	code that called Spencer's code.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The value of "string" is saved in "errMsg".
 *
 *----------------------------------------------------------------------
 */

void
exp_TclRegError(string)
    char *string;			/* Error message. */
{
    errMsg = string;
}

char *
TclGetRegError()
{
    return errMsg;
}

/*
 * end of regexp definitions and code
 */

/*
 * following stolen from tcl8.0.4/generic/tclPosixStr.c
 */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ErrnoMsg --
 *
 *	Return a human-readable message corresponding to a given
 *	errno value.
 *
 * Results:
 *	The return value is the standard POSIX error message for
 *	errno.  This procedure is used instead of strerror because
 *	strerror returns slightly different values on different
 *	machines (e.g. different capitalizations), which cause
 *	problems for things such as regression tests.  This procedure
 *	provides messages for most standard errors, then it calls
 *	strerror for things it doesn't understand.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static
char *
Tcl_ErrnoMsg(err)
    int err;			/* Error number (such as in errno variable). */
{
    switch (err) {
#ifdef E2BIG
	case E2BIG: return "argument list too long";
#endif
#ifdef EACCES
	case EACCES: return "permission denied";
#endif
#ifdef EADDRINUSE
	case EADDRINUSE: return "address already in use";
#endif
#ifdef EADDRNOTAVAIL
	case EADDRNOTAVAIL: return "can't assign requested address";
#endif
#ifdef EADV
	case EADV: return "advertise error";
#endif
#ifdef EAFNOSUPPORT
	case EAFNOSUPPORT: return "address family not supported by protocol family";
#endif
#ifdef EAGAIN
	case EAGAIN: return "resource temporarily unavailable";
#endif
#ifdef EALIGN
	case EALIGN: return "EALIGN";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY ))
	case EALREADY: return "operation already in progress";
#endif
#ifdef EBADE
	case EBADE: return "bad exchange descriptor";
#endif
#ifdef EBADF
	case EBADF: return "bad file number";
#endif
#ifdef EBADFD
	case EBADFD: return "file descriptor in bad state";
#endif
#ifdef EBADMSG
	case EBADMSG: return "not a data message";
#endif
#ifdef EBADR
	case EBADR: return "bad request descriptor";
#endif
#ifdef EBADRPC
	case EBADRPC: return "RPC structure is bad";
#endif
#ifdef EBADRQC
	case EBADRQC: return "bad request code";
#endif
#ifdef EBADSLT
	case EBADSLT: return "invalid slot";
#endif
#ifdef EBFONT
	case EBFONT: return "bad font file format";
#endif
#ifdef EBUSY
	case EBUSY: return "file busy";
#endif
#ifdef ECHILD
	case ECHILD: return "no children";
#endif
#ifdef ECHRNG
	case ECHRNG: return "channel number out of range";
#endif
#ifdef ECOMM
	case ECOMM: return "communication error on send";
#endif
#ifdef ECONNABORTED
	case ECONNABORTED: return "software caused connection abort";
#endif
#ifdef ECONNREFUSED
	case ECONNREFUSED: return "connection refused";
#endif
#ifdef ECONNRESET
	case ECONNRESET: return "connection reset by peer";
#endif
#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
	case EDEADLK: return "resource deadlock avoided";
#endif
#if defined(EDEADLOCK) && (!defined(EDEADLK) || (EDEADLOCK != EDEADLK))
	case EDEADLOCK: return "resource deadlock avoided";
#endif
#ifdef EDESTADDRREQ
	case EDESTADDRREQ: return "destination address required";
#endif
#ifdef EDIRTY
	case EDIRTY: return "mounting a dirty fs w/o force";
#endif
#ifdef EDOM
	case EDOM: return "math argument out of range";
#endif
#ifdef EDOTDOT
	case EDOTDOT: return "cross mount point";
#endif
#ifdef EDQUOT
	case EDQUOT: return "disk quota exceeded";
#endif
#ifdef EDUPPKG
	case EDUPPKG: return "duplicate package name";
#endif
#ifdef EEXIST
	case EEXIST: return "file already exists";
#endif
#ifdef EFAULT
	case EFAULT: return "bad address in system call argument";
#endif
#ifdef EFBIG
	case EFBIG: return "file too large";
#endif
#ifdef EHOSTDOWN
	case EHOSTDOWN: return "host is down";
#endif
#ifdef EHOSTUNREACH
	case EHOSTUNREACH: return "host is unreachable";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
	case EIDRM: return "identifier removed";
#endif
#ifdef EINIT
	case EINIT: return "initialization error";
#endif
#ifdef EINPROGRESS
	case EINPROGRESS: return "operation now in progress";
#endif
#ifdef EINTR
	case EINTR: return "interrupted system call";
#endif
#ifdef EINVAL
	case EINVAL: return "invalid argument";
#endif
#ifdef EIO
	case EIO: return "I/O error";
#endif
#ifdef EISCONN
	case EISCONN: return "socket is already connected";
#endif
#ifdef EISDIR
	case EISDIR: return "illegal operation on a directory";
#endif
#ifdef EISNAME
	case EISNAM: return "is a name file";
#endif
#ifdef ELBIN
	case ELBIN: return "ELBIN";
#endif
#ifdef EL2HLT
	case EL2HLT: return "level 2 halted";
#endif
#ifdef EL2NSYNC
	case EL2NSYNC: return "level 2 not synchronized";
#endif
#ifdef EL3HLT
	case EL3HLT: return "level 3 halted";
#endif
#ifdef EL3RST
	case EL3RST: return "level 3 reset";
#endif
#ifdef ELIBACC
	case ELIBACC: return "can not access a needed shared library";
#endif
#ifdef ELIBBAD
	case ELIBBAD: return "accessing a corrupted shared library";
#endif
#ifdef ELIBEXEC
	case ELIBEXEC: return "can not exec a shared library directly";
#endif
#ifdef ELIBMAX
	case ELIBMAX: return
		"attempting to link in more shared libraries than system limit";
#endif
#ifdef ELIBSCN
	case ELIBSCN: return ".lib section in a.out corrupted";
#endif
#ifdef ELNRNG
	case ELNRNG: return "link number out of range";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
	case ELOOP: return "too many levels of symbolic links";
#endif
#ifdef EMFILE
	case EMFILE: return "too many open files";
#endif
#ifdef EMLINK
	case EMLINK: return "too many links";
#endif
#ifdef EMSGSIZE
	case EMSGSIZE: return "message too long";
#endif
#ifdef EMULTIHOP
	case EMULTIHOP: return "multihop attempted";
#endif
#ifdef ENAMETOOLONG
	case ENAMETOOLONG: return "file name too long";
#endif
#ifdef ENAVAIL
	case ENAVAIL: return "not available";
#endif
#ifdef ENET
	case ENET: return "ENET";
#endif
#ifdef ENETDOWN
	case ENETDOWN: return "network is down";
#endif
#ifdef ENETRESET
	case ENETRESET: return "network dropped connection on reset";
#endif
#ifdef ENETUNREACH
	case ENETUNREACH: return "network is unreachable";
#endif
#ifdef ENFILE
	case ENFILE: return "file table overflow";
#endif
#ifdef ENOANO
	case ENOANO: return "anode table overflow";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
	case ENOBUFS: return "no buffer space available";
#endif
#ifdef ENOCSI
	case ENOCSI: return "no CSI structure available";
#endif
#if defined(ENODATA) && (!defined(ECONNREFUSED) || (ENODATA != ECONNREFUSED))
	case ENODATA: return "no data available";
#endif
#ifdef ENODEV
	case ENODEV: return "no such device";
#endif
#ifdef ENOENT
	case ENOENT: return "no such file or directory";
#endif
#ifdef ENOEXEC
	case ENOEXEC: return "exec format error";
#endif
#ifdef ENOLCK
	case ENOLCK: return "no locks available";
#endif
#ifdef ENOLINK
	case ENOLINK: return "link has be severed";
#endif
#ifdef ENOMEM
	case ENOMEM: return "not enough memory";
#endif
#ifdef ENOMSG
	case ENOMSG: return "no message of desired type";
#endif
#ifdef ENONET
	case ENONET: return "machine is not on the network";
#endif
#ifdef ENOPKG
	case ENOPKG: return "package not installed";
#endif
#ifdef ENOPROTOOPT
	case ENOPROTOOPT: return "bad proocol option";
#endif
#ifdef ENOSPC
	case ENOSPC: return "no space left on device";
#endif
#if defined(ENOSR) && (!defined(ENAMETOOLONG) || (ENAMETOOLONG != ENOSR))
	case ENOSR: return "out of stream resources";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
	case ENOSTR: return "not a stream device";
#endif
#ifdef ENOSYM
	case ENOSYM: return "unresolved symbol name";
#endif
#ifdef ENOSYS
	case ENOSYS: return "function not implemented";
#endif
#ifdef ENOTBLK
	case ENOTBLK: return "block device required";
#endif
#ifdef ENOTCONN
	case ENOTCONN: return "socket is not connected";
#endif
#ifdef ENOTDIR
	case ENOTDIR: return "not a directory";
#endif
#if defined(ENOTEMPTY) && (!defined(EEXIST) || (ENOTEMPTY != EEXIST))
	case ENOTEMPTY: return "directory not empty";
#endif
#ifdef ENOTNAM
	case ENOTNAM: return "not a name file";
#endif
#ifdef ENOTSOCK
	case ENOTSOCK: return "socket operation on non-socket";
#endif
#ifdef ENOTSUP
	case ENOTSUP: return "operation not supported";
#endif
#ifdef ENOTTY
	case ENOTTY: return "inappropriate device for ioctl";
#endif
#ifdef ENOTUNIQ
	case ENOTUNIQ: return "name not unique on network";
#endif
#ifdef ENXIO
	case ENXIO: return "no such device or address";
#endif
#if defined(EOPNOTSUPP) &&  (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
	case EOPNOTSUPP: return "operation not supported on socket";
#endif
#ifdef EPERM
	case EPERM: return "not owner";
#endif
#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
	case EPFNOSUPPORT: return "protocol family not supported";
#endif
#ifdef EPIPE
	case EPIPE: return "broken pipe";
#endif
#ifdef EPROCLIM
	case EPROCLIM: return "too many processes";
#endif
#ifdef EPROCUNAVAIL
	case EPROCUNAVAIL: return "bad procedure for program";
#endif
#ifdef EPROGMISMATCH
	case EPROGMISMATCH: return "program version wrong";
#endif
#ifdef EPROGUNAVAIL
	case EPROGUNAVAIL: return "RPC program not available";
#endif
#ifdef EPROTO
	case EPROTO: return "protocol error";
#endif
#ifdef EPROTONOSUPPORT
	case EPROTONOSUPPORT: return "protocol not suppored";
#endif
#ifdef EPROTOTYPE
	case EPROTOTYPE: return "protocol wrong type for socket";
#endif
#ifdef ERANGE
	case ERANGE: return "math result unrepresentable";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
	case EREFUSED: return "EREFUSED";
#endif
#ifdef EREMCHG
	case EREMCHG: return "remote address changed";
#endif
#ifdef EREMDEV
	case EREMDEV: return "remote device";
#endif
#ifdef EREMOTE
	case EREMOTE: return "pathname hit remote file system";
#endif
#ifdef EREMOTEIO
	case EREMOTEIO: return "remote i/o error";
#endif
#ifdef EREMOTERELEASE
	case EREMOTERELEASE: return "EREMOTERELEASE";
#endif
#ifdef EROFS
	case EROFS: return "read-only file system";
#endif
#ifdef ERPCMISMATCH
	case ERPCMISMATCH: return "RPC version is wrong";
#endif
#ifdef ERREMOTE
	case ERREMOTE: return "object is remote";
#endif
#ifdef ESHUTDOWN
	case ESHUTDOWN: return "can't send afer socket shutdown";
#endif
#ifdef ESOCKTNOSUPPORT
	case ESOCKTNOSUPPORT: return "socket type not supported";
#endif
#ifdef ESPIPE
	case ESPIPE: return "invalid seek";
#endif
#ifdef ESRCH
	case ESRCH: return "no such process";
#endif
#ifdef ESRMNT
	case ESRMNT: return "srmount error";
#endif
#ifdef ESTALE
	case ESTALE: return "stale remote file handle";
#endif
#ifdef ESUCCESS
	case ESUCCESS: return "Error 0";
#endif
#if defined(ETIME) && (!defined(ELOOP) || (ETIME != ELOOP))
	case ETIME: return "timer expired";
#endif
#if defined(ETIMEDOUT) && (!defined(ENOSTR) || (ETIMEDOUT != ENOSTR))
	case ETIMEDOUT: return "connection timed out";
#endif
#ifdef ETOOMANYREFS
	case ETOOMANYREFS: return "too many references: can't splice";
#endif
#ifdef ETXTBSY
	case ETXTBSY: return "text file or pseudo-device busy";
#endif
#ifdef EUCLEAN
	case EUCLEAN: return "structure needs cleaning";
#endif
#ifdef EUNATCH
	case EUNATCH: return "protocol driver not attached";
#endif
#ifdef EUSERS
	case EUSERS: return "too many users";
#endif
#ifdef EVERSION
	case EVERSION: return "version mismatch";
#endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
	case EWOULDBLOCK: return "operation would block";
#endif
#ifdef EXDEV
	case EXDEV: return "cross-domain link";
#endif
#ifdef EXFULL
	case EXFULL: return "message tables full";
#endif
	default:
#ifdef NO_STRERROR
	    return "unknown POSIX error";
#else
	    return strerror(errno);
#endif
    }
}

/*
 * end of excerpt from tcl8.0.X/generic/tclPosixStr.c
 */

/*
 * stolen from exp_log.c - this function is called from the Expect library
 * but the one that the library supplies calls Tcl functions.  So we supply
 * our own.
 */

static
void
expDiagLogU(str)
     char *str;
{
  if (exp_is_debugging) {
    fprintf(stderr,str);
    if (exp_logfile) fprintf(exp_logfile,str);
  }
}

/*
 * expect-specific definitions and code
 */

#include "expect.h"
#include "exp_int.h"

/* exp_glob.c - expect functions for doing glob
 *
 * Based on Tcl's glob functions but modified to support anchors and to
 * return information about the possibility of future matches
 *
 * Modifications by: Don Libes, NIST, 2/6/90
 */

/* The following functions implement expect's glob-style string
 * matching Exp_StringMatch allow's implements the unanchored front
 * (or conversely the '^') feature.  Exp_StringMatch2 does the rest of
 * the work.
 */

/* Exp_StringMatch2 --
 *
 * Like Tcl_StringMatch except that
 * 1) returns number of characters matched, -1 if failed.
 *	(Can return 0 on patterns like "" or "$")
 * 2) does not require pattern to match to end of string
 * 3) much of code is stolen from Tcl_StringMatch
 * 4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor)
 */
static
int
Exp_StringMatch2(string,pattern)
    register char *string;	/* String. */
    register char *pattern;	/* Pattern, which may contain
				 * special characters. */
{
    char c2;
    int match = 0;	/* # of chars matched */

    while (1) {
	/* If at end of pattern, success! */
	if (*pattern == 0) {
		return match;
	}

	/* If last pattern character is '$', verify that entire
	 * string has been matched.
	 */
	if ((*pattern == '$') && (pattern[1] == 0)) {
		if (*string == 0) return(match);
		else return(-1);		
	}

	/* Check for a "*" as the next pattern character.  It matches
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
	 * match or we reach the end of the string.
	 */
	
	if (*pattern == '*') {
	    int head_len;
	    char *tail;
	    pattern += 1;
	    if (*pattern == 0) {
		return(strlen(string)+match); /* DEL */
	    }
	    /* find longest match - switched to this on 12/31/93 */
	    head_len = strlen(string);	/* length before tail */
	    tail = string + head_len;
	    while (head_len >= 0) {
		int rc;

		if (-1 != (rc = Exp_StringMatch2(tail, pattern))) {
		    return rc + match + head_len;	/* DEL */
		}
		tail--;
		head_len--;
	    }
	    return -1;					/* DEL */
	}
    
	/*
	 * after this point, all patterns must match at least one
	 * character, so check this
	 */

	if (*string == 0) return -1;

	/* Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (*pattern == '?') {
	    goto thisCharOK;
	}

	/* Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (*pattern == '[') {
	    pattern += 1;
	    while (1) {
		if ((*pattern == ']') || (*pattern == 0)) {
		    return -1;			/* was 0; DEL */
		}
		if (*pattern == *string) {
		    break;
		}
		if (pattern[1] == '-') {
		    c2 = pattern[2];
		    if (c2 == 0) {
			return -1;		/* DEL */
		    }
		    if ((*pattern <= *string) && (c2 >= *string)) {
			break;
		    }
		    if ((*pattern >= *string) && (c2 <= *string)) {
			break;
		    }
		    pattern += 2;
		}
		pattern += 1;
	    }

	    while (*pattern != ']') {
		if (*pattern == 0) {
		    pattern--;
		    break;
	        }
		pattern += 1;
	    }
	    goto thisCharOK;
	}
    
	/* If the next pattern character is backslash, strip it off
	 * so we do exact matching on the character that follows.
	 */
	
	if (*pattern == '\\') {
	    pattern += 1;
	    if (*pattern == 0) {
		return -1;
	    }
	}

	/* There's no special character.  Just make sure that the next
	 * characters of each string match.
	 */
	
	if (*pattern != *string) {
	    return -1;
	}

	thisCharOK: pattern += 1;
	string += 1;
	match++;
    }
}


static
int	/* returns # of chars that matched */
Exp_StringMatch(string, pattern,offset)
char *string;
char *pattern;
int *offset;	/* offset from beginning of string where pattern matches */
{
	char *s;
	int sm;	/* count of chars matched or -1 */
	int caret = FALSE;
	int star = FALSE;

	*offset = 0;

	if (pattern[0] == '^') {
		caret = TRUE;
		pattern++;
	} else if (pattern[0] == '*') {
		star = TRUE;
	}

	/*
	 * test if pattern matches in initial position.
	 * This handles front-anchor and 1st iteration of non-front-anchor.
	 * Note that 1st iteration must be tried even if string is empty.
	 */

	sm = Exp_StringMatch2(string,pattern);
	if (sm >= 0) return(sm);

	if (caret) return -1;
	if (star) return -1;

	if (*string == '\0') return -1;

	for (s = string+1;*s;s++) {
 		sm = Exp_StringMatch2(s,pattern);
		if (sm != -1) {
			*offset = s-string;
			return(sm);
		}
	}
	return -1;
}


#define EXP_MATCH_MAX	2000
/* public */
char *exp_buffer = 0;
char *exp_buffer_end = 0;
char *exp_match = 0;
char *exp_match_end = 0;
int exp_match_max = EXP_MATCH_MAX;	/* bytes */
int exp_full_buffer = FALSE;		/* don't return on full buffer */
int exp_remove_nulls = TRUE;
int exp_timeout = 10;			/* seconds */
int exp_pty_timeout = 5;		/* seconds - see CRAY below */
int exp_autoallocpty = TRUE;		/* if TRUE, we do allocation */
int exp_pty[2];				/* master is [0], slave is [1] */
int exp_pid;
char *exp_stty_init = 0;		/* initial stty args */
int exp_ttycopy = TRUE;			/* copy tty parms from /dev/tty */
int exp_ttyinit = TRUE;			/* set tty parms to sane state */
int exp_console = FALSE;		/* redirect console */
void (*exp_child_exec_prelude)() = 0;
void (*exp_close_in_child)() = 0;

#ifdef HAVE_SIGLONGJMP
sigjmp_buf exp_readenv;		/* for interruptable read() */
#else
jmp_buf exp_readenv;		/* for interruptable read() */
#endif /* HAVE_SIGLONGJMP */

int exp_reading = FALSE;	/* whether we can longjmp or not */

int exp_is_debugging = FALSE;
FILE *exp_debugfile = 0;

FILE *exp_logfile = 0;
int exp_logfile_all = FALSE;	/* if TRUE, write log of all interactions */
int exp_loguser = TRUE;		/* if TRUE, user sees interactions on stdout */


char *exp_printify();
int exp_getptymaster();
int exp_getptyslave();


#define sysreturn(x)	return(errno = x, -1)

void exp_init_pty();

/*
   The following functions are linked from the Tcl library.  They
   don't cause anything else in the library to be dragged in, so it
   shouldn't cause any problems (e.g., bloat).

   The functions are relatively small but painful enough that I don't care
   to recode them.  You may, if you absolutely want to get rid of any
   vestiges of Tcl.
*/






static unsigned int bufsiz = 2*EXP_MATCH_MAX;

static struct f {
	int valid;

	char *buffer;		/* buffer of matchable chars */
	char *buffer_end;	/* one beyond end of matchable chars */

	char *match_end;	/* one beyond end of matched string */
	int msize;		/* size of allocate space */
				/* actual size is one larger for null */
} *fs = 0;

static int fd_alloc_max = -1;	/* max fd allocated */

173
174
175
176
177
178
179

















180
181
182
183
184
185
186
187
188
189
190
191
192


193
194
195
196
197
198
199
200
201
202
203
204


205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238










239
240
241
242
243
244
245
246


247
248
249
250
251
252
253
		fp->valid = TRUE;
	}
	fp->buffer_end = fp->buffer;
	fp->match_end = fp->buffer;
	return fp;

}


















/* returns fd of master side of pty */
int
exp_spawnv(file,argv)
char *file;
char *argv[];	/* some compiler complains about **argv? */
{
	int cc;
	int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
	int ttyfd;
	int sync_fds[2];
	int sync2_fds[2];


	char sync_byte;
#ifdef PTYTRAP_DIES
	int slave_write_ioctls = 1;
		/* by default, slave will be write-ioctled this many times */
#endif

	static int first_time = TRUE;

	if (first_time) {
		first_time = FALSE;
		exp_init_pty();
		exp_init_tty();


	}

	if (!file || !argv) sysreturn(EINVAL);
	if (!argv[0] || strcmp(file,argv[0])) {
		debuglog("expect: warning: file (%s) != argv[0] (%s)\n",
			file,
			argv[0]?argv[0]:"");
	}

#ifdef PTYTRAP_DIES
/* any extraneous ioctl's that occur in slave must be accounted for
when trapping, see below in child half of fork */
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
	slave_write_ioctls++;
#endif
#endif /*PTYTRAP_DIES*/

	if (exp_autoallocpty) {
		if (0 > (exp_pty[0] = getptymaster())) sysreturn(ENODEV);
	}
	fcntl(exp_pty[0],F_SETFD,1);	/* close on exec */
#ifdef PTYTRAP_DIES
	exp_slave_control(exp_pty[0],1);*/
#endif

	if (!fd_new(exp_pty[0])) {
		errno = ENOMEM;
		return -1;
	}

	if (-1 == (pipe(sync_fds))) {
		return -1;
	}
	if (-1 == (pipe(sync2_fds))) {










		return -1;
	}

	if ((exp_pid = fork()) == -1) return(-1);
	if (exp_pid) {
		/* parent */
		close(sync_fds[1]);
		close(sync2_fds[0]);


		if (!exp_autoallocpty) close(exp_pty[1]);

#ifdef PTYTRAP_DIES
#ifdef HAVE_PTYTRAP
		if (exp_autoallocpty) {
			/* trap initial ioctls in a feeble attempt to not */
			/* block the initially.  If the process itself */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>












>
>




|













|















>
>
>
>
>
>
>
>
>
>








>
>







2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
		fp->valid = TRUE;
	}
	fp->buffer_end = fp->buffer;
	fp->match_end = fp->buffer;
	return fp;

}

static
void
exp_setpgrp()
{
#ifdef MIPS_BSD
    /* required on BSD side of MIPS OS <[email protected]> */
#   include <sysv/sys.s>
    syscall(SYS_setpgrp);
#endif

#ifdef SETPGRP_VOID
    (void) setpgrp();
#else
    (void) setpgrp(0,0);
#endif
}

/* returns fd of master side of pty */
int
exp_spawnv(file,argv)
char *file;
char *argv[];	/* some compiler complains about **argv? */
{
	int cc;
	int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
	int ttyfd;
	int sync_fds[2];
	int sync2_fds[2];
	int status_pipe[2];
	int child_errno;
	char sync_byte;
#ifdef PTYTRAP_DIES
	int slave_write_ioctls = 1;
		/* by default, slave will be write-ioctled this many times */
#endif

	static int first_time = TRUE;

	if (first_time) {
		first_time = FALSE;
		exp_init_pty();
		exp_init_tty();
		expDiagLogPtrSet(expDiagLogU);
		expErrnoMsgSet(Tcl_ErrnoMsg);
	}

	if (!file || !argv) sysreturn(EINVAL);
	if (!argv[0] || strcmp(file,argv[0])) {
		exp_debuglog("expect: warning: file (%s) != argv[0] (%s)\n",
			file,
			argv[0]?argv[0]:"");
	}

#ifdef PTYTRAP_DIES
/* any extraneous ioctl's that occur in slave must be accounted for
when trapping, see below in child half of fork */
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
	slave_write_ioctls++;
#endif
#endif /*PTYTRAP_DIES*/

	if (exp_autoallocpty) {
		if (0 > (exp_pty[0] = exp_getptymaster())) sysreturn(ENODEV);
	}
	fcntl(exp_pty[0],F_SETFD,1);	/* close on exec */
#ifdef PTYTRAP_DIES
	exp_slave_control(exp_pty[0],1);*/
#endif

	if (!fd_new(exp_pty[0])) {
		errno = ENOMEM;
		return -1;
	}

	if (-1 == (pipe(sync_fds))) {
		return -1;
	}
	if (-1 == (pipe(sync2_fds))) {
		close(sync_fds[0]);
		close(sync_fds[1]);
		return -1;
	}

	if (-1 == pipe(status_pipe)) {
		close(sync_fds[0]);
		close(sync_fds[1]);
		close(sync2_fds[0]);
		close(sync2_fds[1]);
		return -1;
	}

	if ((exp_pid = fork()) == -1) return(-1);
	if (exp_pid) {
		/* parent */
		close(sync_fds[1]);
		close(sync2_fds[0]);
		close(status_pipe[1]);

		if (!exp_autoallocpty) close(exp_pty[1]);

#ifdef PTYTRAP_DIES
#ifdef HAVE_PTYTRAP
		if (exp_autoallocpty) {
			/* trap initial ioctls in a feeble attempt to not */
			/* block the initially.  If the process itself */
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304





















305
306
307

308

309
310
311


312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
#endif /*PTYTRAP_DIES*/

		/*
		 * wait for slave to initialize pty before allowing
		 * user to send to it
		 */ 

		debuglog("parent: waiting for sync byte\r\n");
		cc = read(sync_fds[0],&sync_byte,1);
		if (cc == -1) {
			fprintf(stderr,"parent sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
			exit(-1);
		}

		/* turn on detection of eof */
		exp_slave_control(exp_pty[0],1);

		/*
		 * tell slave to go on now now that we have initialized pty
		 */

		debuglog("parent: telling child to go ahead\r\n");
		cc = write(sync2_fds[1]," ",1);
		if (cc == -1) {
			errorlog("parent sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
			exit(-1);
		}

		debuglog("parent: now unsynchronized from child\r\n");

		close(sync_fds[0]);
		close(sync2_fds[1]);






















		return(exp_pty[0]);
	}


	/* child process - do not return from here!  all errors must exit() */


	close(sync_fds[0]);
	close(sync2_fds[1]);



#ifdef CRAY
	(void) close(exp_pty[0]);
#endif

/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */
/* is called.  setpgrp works though.  */
#if defined(POSIX) && !defined(ultrix)
#define DO_SETSID
#endif
#ifdef __convex__
#define DO_SETSID
#endif

#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
#ifndef CRAY
	setpgrp();
#endif /* CRAY */
#else /* !SYSV3 */
#ifdef MIPS_BSD
	/* required on BSD side of MIPS OS <[email protected]> */
#	include <sysv/sys.s>
	syscall(SYS_setpgrp);
#endif
	setpgrp(0,0);
/*	setpgrp(0,getpid());*/	/* make a new pgrp leader */

#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
	}







|


|
|









|


|
|


|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
|
>



>
>



















|


<
<
<
<
<
|
<







2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480





2481

2482
2483
2484
2485
2486
2487
2488
#endif /*PTYTRAP_DIES*/

		/*
		 * wait for slave to initialize pty before allowing
		 * user to send to it
		 */ 

		exp_debuglog("parent: waiting for sync byte\r\n");
		cc = read(sync_fds[0],&sync_byte,1);
		if (cc == -1) {
		  exp_errorlog("parent sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
		  return -1;
		}

		/* turn on detection of eof */
		exp_slave_control(exp_pty[0],1);

		/*
		 * tell slave to go on now now that we have initialized pty
		 */

		exp_debuglog("parent: telling child to go ahead\r\n");
		cc = write(sync2_fds[1]," ",1);
		if (cc == -1) {
		  exp_errorlog("parent sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		  return -1;
		}

		exp_debuglog("parent: now unsynchronized from child\r\n");

		close(sync_fds[0]);
		close(sync2_fds[1]);

		/* see if child's exec worked */

	retry:
		switch (read(status_pipe[0],&child_errno,sizeof child_errno)) {
		case -1:
			if (errno == EINTR) goto retry;
			/* well it's not really the child's errno */
			/* but it can be treated that way */
			child_errno = errno;
			break;
		case 0:
			/* child's exec succeeded */
			child_errno = 0;
			break;
		default:
			/* child's exec failed; err contains exec's errno  */
			waitpid(exp_pid, NULL, 0);
			errno = child_errno;
			exp_pty[0] = -1;
		}
		close(status_pipe[0]);
		return(exp_pty[0]);
	}

	/*
	 * child process - do not return from here!  all errors must exit()
	 */

	close(sync_fds[0]);
	close(sync2_fds[1]);
	close(status_pipe[0]);
	fcntl(status_pipe[1],F_SETFD,1);	/* close on exec */

#ifdef CRAY
	(void) close(exp_pty[0]);
#endif

/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */
/* is called.  setpgrp works though.  */
#if defined(POSIX) && !defined(ultrix)
#define DO_SETSID
#endif
#ifdef __convex__
#define DO_SETSID
#endif

#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
#ifndef CRAY
	exp_setpgrp();
#endif /* CRAY */
#else /* !SYSV3 */





	exp_setpgrp();


#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
	}
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

	    close(0);
	    close(1);
	    close(2);

	    /* since we closed fd 0, open of pty slave must return fd 0 */

	    if (0 > (exp_pty[1] = getptyslave(exp_ttycopy,exp_ttyinit,
						exp_stty_init))) {
		restore_error_fd
		fprintf(stderr,"open(slave pty): %s\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	    }
	    /* sanity check */
	    if (exp_pty[1] != 0) {
		restore_error_fd
		fprintf(stderr,"getptyslave: slave = %d but expected 0\n",
								exp_pty[1]);
		exit(-1);
	    }
	} else {
		if (exp_pty[1] != 0) {
			close(0);	fcntl(exp_pty[1],F_DUPFD,0);
		}







|








|







2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523

	    close(0);
	    close(1);
	    close(2);

	    /* since we closed fd 0, open of pty slave must return fd 0 */

	    if (0 > (exp_pty[1] = exp_getptyslave(exp_ttycopy,exp_ttyinit,
						exp_stty_init))) {
		restore_error_fd
		fprintf(stderr,"open(slave pty): %s\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	    }
	    /* sanity check */
	    if (exp_pty[1] != 0) {
		restore_error_fd
		fprintf(stderr,"exp_getptyslave: slave = %d but expected 0\n",
								exp_pty[1]);
		exit(-1);
	    }
	} else {
		if (exp_pty[1] != 0) {
			close(0);	fcntl(exp_pty[1],F_DUPFD,0);
		}
392
393
394
395
396
397
398
399
400
401
402
403
404
405










406
407
408
409
410
411
412
/* is no documented define for the 720!) */

#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux)
	/* 4.3+BSD way to acquire controlling terminal */
	/* according to Stevens - Adv. Prog..., p 642 */
#ifdef __QNX__ /* posix in general */
	if (tcsetct(0, getpid()) == -1) {
#else
	if (ioctl(0,TIOCSCTTY,(char *)0) < 0) {
#endif
		restore_error_fd
		fprintf(stderr,"failed to get controlling terminal using TIOCSCTTY");
		exit(-1);
	}










#endif

#ifdef CRAY
 	(void) setsid();
 	(void) ioctl(0,TCSETCTTY,0);
 	(void) close(0);
 	if (open("/dev/tty", O_RDWR) < 0) {







<
<
<
|
|
|

>
>
>
>
>
>
>
>
>
>







2533
2534
2535
2536
2537
2538
2539



2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
/* is no documented define for the 720!) */

#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux)
	/* 4.3+BSD way to acquire controlling terminal */
	/* according to Stevens - Adv. Prog..., p 642 */
#ifdef __QNX__ /* posix in general */
	if (tcsetct(0, getpid()) == -1) {



	  restore_error_fd
	  expErrorLog("failed to get controlling terminal using TIOCSCTTY");
	  exit(-1);
	}
#else
	(void) ioctl(0,TIOCSCTTY,(char *)0);
	/* ignore return value - on some systems, it is defined but it
	 * fails and it doesn't seem to cause any problems.  Or maybe
	 * it works but returns a bogus code.  Noone seems to be able
	 * to explain this to me.  The systems are an assortment of
	 * different linux systems (and FreeBSD 2.5), RedHat 5.2 and
	 * Debian 2.0
	 */
#endif
#endif

#ifdef CRAY
 	(void) setsid();
 	(void) ioctl(0,TCSETCTTY,0);
 	(void) close(0);
 	if (open("/dev/tty", O_RDWR) < 0) {
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525

526
527
528
529
530
531
532

533
534
535
536
537
538
539
		}
#endif /* TIOCCONS */
	}

	/* tell parent that we are done setting up pty */
	/* The actual char sent back is irrelevant. */

	/* debuglog("child: telling parent that pty is initialized\r\n");*/
	cc = write(sync_fds[1]," ",1);
	if (cc == -1) {
		restore_error_fd
		fprintf(stderr,"child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync_fds[1]);

	/* wait for master to let us go on */
	/* debuglog("child: waiting for go ahead from parent\r\n"); */

/*	close(master);	/* force master-side close so we can read */
	cc = read(sync2_fds[0],&sync_byte,1);
	if (cc == -1) {
		restore_error_fd
		errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync2_fds[0]);

	/* debuglog("child: now unsynchronized from parent\r\n"); */

	/* (possibly multiple) masters are closed automatically due to */
	/* earlier fcntl(,,CLOSE_ON_EXEC); */

	/* just in case, allow user to explicitly close other files */
	if (exp_close_in_child) (*exp_close_in_child)();

	/* allow user to do anything else to child */
	if (exp_child_exec_prelude) (*exp_child_exec_prelude)();

        (void) execvp(file,argv);

	/* Unfortunately, by now we've closed fd's to stderr, logfile and
		debugfile.
	   The only reasonable thing to do is to send back the error as
	   part of the program output.  This will be picked up in an
	   expect or interact command.
	*/
	fprintf(stderr,"execvp(%s): %s\n",file,Tcl_ErrnoMsg(errno));

	exit(-1);
	/*NOTREACHED*/
}

/* returns fd of master side of pty */
/*VARARGS*/
int







|









<
<
<



|




|











>
|
<
|
|
|
|
|
>







2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650



2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
		}
#endif /* TIOCCONS */
	}

	/* tell parent that we are done setting up pty */
	/* The actual char sent back is irrelevant. */

	/* exp_debuglog("child: telling parent that pty is initialized\r\n");*/
	cc = write(sync_fds[1]," ",1);
	if (cc == -1) {
		restore_error_fd
		fprintf(stderr,"child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync_fds[1]);

	/* wait for master to let us go on */



	cc = read(sync2_fds[0],&sync_byte,1);
	if (cc == -1) {
		restore_error_fd
		exp_errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync2_fds[0]);

	/* exp_debuglog("child: now unsynchronized from parent\r\n"); */

	/* (possibly multiple) masters are closed automatically due to */
	/* earlier fcntl(,,CLOSE_ON_EXEC); */

	/* just in case, allow user to explicitly close other files */
	if (exp_close_in_child) (*exp_close_in_child)();

	/* allow user to do anything else to child */
	if (exp_child_exec_prelude) (*exp_child_exec_prelude)();

        (void) execvp(file,argv);

	/* Unfortunately, by now we've closed fd's to stderr, logfile

	 * and debugfile.  The only reasonable thing to do is to send
	 * *back the error as part of the program output.  This will
	 * be *picked up in an expect or interact command.
	 */

	write(status_pipe[1], &errno, sizeof errno);
	exit(-1);
	/*NOTREACHED*/
}

/* returns fd of master side of pty */
/*VARARGS*/
int
609
610
611
612
613
614
615



616

617
618
619
620
621
622
623
sigalarm_handler(n)
int n;			/* signal number, unused by us */
{
#ifdef REARM_SIG
	signal(SIGALRM,sigalarm_handler);
#endif




	longjmp(exp_readenv,1);

}

/* interruptable read */
static int
i_read(fd,fp,buffer,length,timeout)
int fd;
FILE *fp;







>
>
>

>







2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
sigalarm_handler(n)
int n;			/* signal number, unused by us */
{
#ifdef REARM_SIG
	signal(SIGALRM,sigalarm_handler);
#endif

#ifdef HAVE_SIGLONGJMP
	siglongjmp(exp_readenv,1);
#else
	longjmp(exp_readenv,1);
#endif /* HAVE_SIGLONGJMP */
}

/* interruptable read */
static int
i_read(fd,fp,buffer,length,timeout)
int fd;
FILE *fp;
633
634
635
636
637
638
639



640

641
642
643
644
645
646
647
	/* no need to set alarm if -1 (infinite) or 0 (poll with */
	/* guaranteed data) */

	if (timeout > 0) alarm(timeout);

	/* restart read if setjmp returns 0 (first time) or 2 (EXP_RESTART). */
	/* abort if setjmp returns 1 (EXP_ABORT). */



	if (EXP_ABORT != setjmp(exp_readenv)) {

		exp_reading = TRUE;
		if (fd == -1) {
			int c;
			c = getc(fp);
			if (c == EOF) {
/*fprintf(stderr,"<<EOF>>",c);fflush(stderr);*/
				if (feof(fp)) cc = 0;







>
>
>

>







2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
	/* no need to set alarm if -1 (infinite) or 0 (poll with */
	/* guaranteed data) */

	if (timeout > 0) alarm(timeout);

	/* restart read if setjmp returns 0 (first time) or 2 (EXP_RESTART). */
	/* abort if setjmp returns 1 (EXP_ABORT). */
#ifdef HAVE_SIGLONGJMP
        if (EXP_ABORT != sigsetjmp(exp_readenv,1)) {
#else
	if (EXP_ABORT != setjmp(exp_readenv)) {
#endif /* HAVE_SIGLONGJMP */
		exp_reading = TRUE;
		if (fd == -1) {
			int c;
			c = getc(fp);
			if (c == EOF) {
/*fprintf(stderr,"<<EOF>>",c);fflush(stderr);*/
				if (feof(fp)) cc = 0;
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
	for (;;) {
		/* when buffer fills, copy second half over first and */
		/* continue, so we can do matches over multiple buffers */
		if (buf_length == bufsiz) {
			int first_half, second_half;

			if (exp_full_buffer) {
				debuglog("expect: full buffer\r\n");
				exp_match = exp_buffer;
				exp_match_end = exp_buffer + buf_length;
				exp_buffer_end = exp_match_end;
				return_normally(EXP_FULLBUFFER);
			}
			first_half = bufsiz/2;
			second_half = bufsiz - first_half;







|







2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
	for (;;) {
		/* when buffer fills, copy second half over first and */
		/* continue, so we can do matches over multiple buffers */
		if (buf_length == bufsiz) {
			int first_half, second_half;

			if (exp_full_buffer) {
				exp_debuglog("expect: full buffer\r\n");
				exp_match = exp_buffer;
				exp_match_end = exp_buffer + buf_length;
				exp_buffer_end = exp_match_end;
				return_normally(EXP_FULLBUFFER);
			}
			first_half = bufsiz/2;
			second_half = bufsiz - first_half;
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
			goto after_read;
		}

		/*
		 * check for timeout
		 */
		if ((exp_timeout >= 0) && ((remtime < 0) || polled)) {
			debuglog("expect: timeout\r\n");
			exp_match_end = exp_buffer;
			return_normally(EXP_TIMEOUT);
		}

		/*
		 * if timeout == 0, indicate a poll has
		 * occurred so that next time through loop causes timeout
		 */
		if (exp_timeout == 0) {
			polled = 1;
		}

		cc = i_read(fd,fp,
				exp_buffer_end,
				bufsiz - buf_length,
				remtime);

		if (cc == 0) {
			debuglog("expect: eof\r\n");
			return_normally(EXP_EOF);	/* normal EOF */
		} else if (cc == -1) {			/* abnormal EOF */
			/* ptys produce EIO upon EOF - sigh */
			if (i_read_errno == EIO) {
				/* convert to EOF indication */
				debuglog("expect: eof\r\n");
				return_normally(EXP_EOF);
			}
			debuglog("expect: error (errno = %d)\r\n",i_read_errno);
			return_errno(i_read_errno);
		} else if (cc == -2) {
			debuglog("expect: timeout\r\n");
			exp_match_end = exp_buffer;
			return_normally(EXP_TIMEOUT);
		}

		old_length = buf_length;
		buf_length += cc;
		exp_buffer_end += buf_length;

		if (logfile_all || (loguser && logfile)) {
			fwrite(exp_buffer + old_length,1,cc,logfile);
		}
		if (loguser) fwrite(exp_buffer + old_length,1,cc,stdout);
		if (debugfile) fwrite(exp_buffer + old_length,1,cc,debugfile);

		/* if we wrote to any logs, flush them */
		if (debugfile) fflush(debugfile);
		if (loguser) {
			fflush(stdout);
			if (logfile) fflush(logfile);
		}

		/* remove nulls from input, so we can use C-style strings */
		/* doing it here lets them be sent to the screen, just */
		/*  in case they are involved in formatting operations */
		if (exp_remove_nulls) {
			buf_length -= rm_nulls(exp_buffer + old_length, cc);
		}
		/* cc should be decremented as well, but since it will not */
		/* be used before being set again, there is no need */
		exp_buffer_end = exp_buffer + buf_length;
		*exp_buffer_end = '\0';
                exp_match_end = exp_buffer;

	after_read:
		debuglog("expect: does {%s} match ",exp_printify(exp_buffer));
		/* pattern supplied */
		for (ec=ecases;ec->type != exp_end;ec++) {
			int matched = -1;

			debuglog("{%s}? ",exp_printify(ec->pattern));
			if (ec->type == exp_glob) {
				int offset;
				matched = Exp_StringMatch(exp_buffer,ec->pattern,&offset);
				if (matched >= 0) {
					exp_match = exp_buffer + offset;
					exp_match_end = exp_match + matched;
				}







|


















|





|


|


|








|
|

|
|


|
|

|















|




|







2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
			goto after_read;
		}

		/*
		 * check for timeout
		 */
		if ((exp_timeout >= 0) && ((remtime < 0) || polled)) {
			exp_debuglog("expect: timeout\r\n");
			exp_match_end = exp_buffer;
			return_normally(EXP_TIMEOUT);
		}

		/*
		 * if timeout == 0, indicate a poll has
		 * occurred so that next time through loop causes timeout
		 */
		if (exp_timeout == 0) {
			polled = 1;
		}

		cc = i_read(fd,fp,
				exp_buffer_end,
				bufsiz - buf_length,
				remtime);

		if (cc == 0) {
			exp_debuglog("expect: eof\r\n");
			return_normally(EXP_EOF);	/* normal EOF */
		} else if (cc == -1) {			/* abnormal EOF */
			/* ptys produce EIO upon EOF - sigh */
			if (i_read_errno == EIO) {
				/* convert to EOF indication */
				exp_debuglog("expect: eof\r\n");
				return_normally(EXP_EOF);
			}
			exp_debuglog("expect: error (errno = %d)\r\n",i_read_errno);
			return_errno(i_read_errno);
		} else if (cc == -2) {
			exp_debuglog("expect: timeout\r\n");
			exp_match_end = exp_buffer;
			return_normally(EXP_TIMEOUT);
		}

		old_length = buf_length;
		buf_length += cc;
		exp_buffer_end += buf_length;

		if (exp_logfile_all || (exp_loguser && exp_logfile)) {
			fwrite(exp_buffer + old_length,1,cc,exp_logfile);
		}
		if (exp_loguser) fwrite(exp_buffer + old_length,1,cc,stdout);
		if (exp_debugfile) fwrite(exp_buffer + old_length,1,cc,exp_debugfile);

		/* if we wrote to any logs, flush them */
		if (exp_debugfile) fflush(exp_debugfile);
		if (exp_loguser) {
			fflush(stdout);
			if (exp_logfile) fflush(exp_logfile);
		}

		/* remove nulls from input, so we can use C-style strings */
		/* doing it here lets them be sent to the screen, just */
		/*  in case they are involved in formatting operations */
		if (exp_remove_nulls) {
			buf_length -= rm_nulls(exp_buffer + old_length, cc);
		}
		/* cc should be decremented as well, but since it will not */
		/* be used before being set again, there is no need */
		exp_buffer_end = exp_buffer + buf_length;
		*exp_buffer_end = '\0';
                exp_match_end = exp_buffer;

	after_read:
		exp_debuglog("expect: does {%s} match ",exp_printify(exp_buffer));
		/* pattern supplied */
		for (ec=ecases;ec->type != exp_end;ec++) {
			int matched = -1;

			exp_debuglog("{%s}? ",exp_printify(ec->pattern));
			if (ec->type == exp_glob) {
				int offset;
				matched = Exp_StringMatch(exp_buffer,ec->pattern,&offset);
				if (matched >= 0) {
					exp_match = exp_buffer + offset;
					exp_match_end = exp_match + matched;
				}
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
					exp_match_end = ec->re->endp[0];
				} else if (TclGetRegError()) {
			    		fprintf(stderr,"r.e. match (pattern %s) failed: %s",ec->pattern,TclGetRegError());
				}
			}

			if (matched != -1) {
				debuglog("yes\nexp_buffer is {%s}\n",
						exp_printify(exp_buffer));
				return_normally(ec->value);
			} else debuglog("no\n");
		}

		/*
		 * Update current time and remaining time.
		 * Don't bother if we are waiting forever or polling.
		 */
		if (exp_timeout > 0) {







|


|







3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
					exp_match_end = ec->re->endp[0];
				} else if (TclGetRegError()) {
			    		fprintf(stderr,"r.e. match (pattern %s) failed: %s",ec->pattern,TclGetRegError());
				}
			}

			if (matched != -1) {
				exp_debuglog("yes\nexp_buffer is {%s}\n",
						exp_printify(exp_buffer));
				return_normally(ec->value);
			} else exp_debuglog("no\n");
		}

		/*
		 * Update current time and remaining time.
		 * Don't bother if we are waiting forever or polling.
		 */
		if (exp_timeout > 0) {
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198












































































	freopen("/dev/null","w",stderr);

#ifdef POSIX
	setsid();
#else
#ifdef SYSV3
	/* put process in our own pgrp, and lose controlling terminal */
	setpgrp();
	signal(SIGHUP,SIG_IGN);
	if (fork()) exit(0);	/* first child exits (as per Stevens, */
	/* UNIX Network Programming, p. 79-80) */
	/* second child process continues as daemon */
#else /* !SYSV3 */
#ifdef MIPS_BSD
	/* required on BSD side of MIPS OS <[email protected]> */
#	include <sysv/sys.s>
	syscall(SYS_setpgrp);
#endif
	setpgrp(0,getpid());	/* put process in our own pgrp */
/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		/* zap controlling terminal if we had one */
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
	}
#endif /* TIOCNOTTY */
#endif /* SYSV3 */
#endif /* POSIX */
	return(0);
}



















































































|





<
<
<
|
<
<













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333



3334


3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
	freopen("/dev/null","w",stderr);

#ifdef POSIX
	setsid();
#else
#ifdef SYSV3
	/* put process in our own pgrp, and lose controlling terminal */
	exp_setpgrp();
	signal(SIGHUP,SIG_IGN);
	if (fork()) exit(0);	/* first child exits (as per Stevens, */
	/* UNIX Network Programming, p. 79-80) */
	/* second child process continues as daemon */
#else /* !SYSV3 */



	exp_setpgrp();


/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		/* zap controlling terminal if we had one */
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
	}
#endif /* TIOCNOTTY */
#endif /* SYSV3 */
#endif /* POSIX */
	return(0);
}

/* send to log if open and debugging enabled */
/* send to stderr if debugging enabled */
/* use this function for recording unusual things in the log */
/*VARARGS*/
void
exp_debuglog TCL_VARARGS_DEF(char *,arg1)
{
    char *fmt;
    va_list args;

    fmt = TCL_VARARGS_START(char *,arg1,args);
    if (exp_debugfile) vfprintf(exp_debugfile,fmt,args);
    if (exp_is_debugging) {
	vfprintf(stderr,fmt,args);
	if (exp_logfile) vfprintf(exp_logfile,fmt,args);
    }

    va_end(args);
}


/* send to log if open */
/* send to stderr */
/* use this function for error conditions */
/*VARARGS*/
void
exp_errorlog TCL_VARARGS_DEF(char *,arg1)
{
    char *fmt;
    va_list args;
    
    fmt = TCL_VARARGS_START(char *,arg1,args);
    vfprintf(stderr,fmt,args);
    if (exp_debugfile) vfprintf(exp_debugfile,fmt,args);
    if (exp_logfile) vfprintf(exp_logfile,fmt,args);
    va_end(args);
}

#include <ctype.h>

char *
exp_printify(s)
char *s;
{
	static int destlen = 0;
	static char *dest = 0;
	char *d;		/* ptr into dest */
	unsigned int need;

	if (s == 0) return("<null>");

	/* worst case is every character takes 4 to printify */
	need = strlen(s)*4 + 1;
	if (need > destlen) {
		if (dest) ckfree(dest);
		dest = ckalloc(need);
		destlen = need;
	}

	for (d = dest;*s;s++) {
		if (*s == '\r') {
			strcpy(d,"\\r");		d += 2;
		} else if (*s == '\n') {
			strcpy(d,"\\n");		d += 2;
		} else if (*s == '\t') {
			strcpy(d,"\\t");		d += 2;
		} else if (isascii(*s) && isprint(*s)) {
			*d = *s;			d += 1;
		} else {
			sprintf(d,"\\x%02x",*s & 0xff);	d += 4;
		}
	}
	*d = '\0';
	return(dest);
}

Changes to exp_closetcl.c.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

/* exp_closetcl.c - close tcl files */

/* isolated in it's own file since it has hooks into Tcl and exp_clib user */
/* might like to avoid dragging it in */

#include "expect_cf.h"
#include "tclInt.h"

void (*exp_close_in_child)() = 0;

void
exp_close_tcl_files() {
	int i;

	/* So much for close-on-exec.  Tcl doesn't mark its files that way */
	/* everything has to be closed explicitly. */

#if 0
/* Not necessary with Tcl 7.5? */
	for (i=3; i<tclNumFiles;i++) close(i);
#endif
}
>






<





|
|
<
<
|
<
<
<
|
<
1
2
3
4
5
6
7

8
9
10
11
12
13
14


15



16

#if OBSOLETE
/* exp_closetcl.c - close tcl files */

/* isolated in it's own file since it has hooks into Tcl and exp_clib user */
/* might like to avoid dragging it in */

#include "expect_cf.h"


void (*exp_close_in_child)() = 0;

void
exp_close_tcl_files() {
    /* I don't believe this function is used any longer, at least in
       the Expect program.*/


}



#endif /* OBSOLETE */

Changes to exp_command.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#  include <sys/fcntl.h>
#else
#  include <fcntl.h>
#endif
#include <sys/file.h>
#include "exp_tty.h"

#ifdef HAVE_SYS_WAIT_H
  /* ISC doesn't def WNOHANG unless _POSIX_SOURCE is def'ed */
# ifdef WNOHANG_REQUIRES_POSIX_SOURCE
#  define _POSIX_SOURCE
# endif
# include <sys/wait.h>
# ifdef WNOHANG_REQUIRES_POSIX_SOURCE
#  undef _POSIX_SOURCE
# endif
#endif

#include <errno.h>
#include <signal.h>

#if defined(SIGCLD) && !defined(SIGCHLD)
#define SIGCHLD SIGCLD
#endif








<
<
<
<
<
<
<
<
<
<
<







27
28
29
30
31
32
33











34
35
36
37
38
39
40
#  include <sys/fcntl.h>
#else
#  include <fcntl.h>
#endif
#include <sys/file.h>
#include "exp_tty.h"












#include <errno.h>
#include <signal.h>

#if defined(SIGCLD) && !defined(SIGCHLD)
#define SIGCHLD SIGCLD
#endif

84
85
86
87
88
89
90







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137


















138
139
140
141
142
143
144
#include "exp_log.h"
#include "exp_event.h"
#include "exp_pty.h"
#ifdef TCL_DEBUGGER
#include "tcldbg.h"
#endif








#define SPAWN_ID_VARNAME "spawn_id"

int getptymaster();
int getptyslave();

int exp_forked = FALSE;		/* whether we are child process */

/* the following are just reserved addresses, to be used as ClientData */
/* args to be used to tell commands how they were called. */
/* The actual values won't be used, only the addresses, but I give them */
/* values out of my irrational fear the compiler might collapse them all. */
static int sendCD_error = 2;	/* called as send_error */
static int sendCD_user = 3;	/* called as send_user */
static int sendCD_proc = 4;	/* called as send or send_spawn */
static int sendCD_tty = 6;	/* called as send_tty */

struct exp_f *exp_fs = 0;		/* process array (indexed by spawn_id's) */
int exp_fd_max = -1;		/* highest fd */

/*
 * expect_key is just a source for generating a unique stamp.  As each
 * expect/interact command begins, it generates a new key and marks all
 * the spawn ids of interest with it.  Then, if someone comes along and
 * marks them with yet a newer key, the old command will recognize this
 * reexamine the state of the spawned process.
 */
int expect_key = 0;

/*
 * exp_configure_count is incremented whenever a spawned process is closed
 * or an indirect list is modified.  This forces any (stack of) expect or
 * interact commands to reexamine the state of the world and adjust
 * accordingly.
 */
int exp_configure_count = 0;

/* this message is required because fopen sometimes fails to set errno */
/* Apparently, it "does the user a favor" and doesn't even call open */
/* if the file name is bizarre enough.  This means we can't handle fopen */
/* with the obvious trivial logic. */
static char *open_failed = "could not open - odd file name?";

#ifdef HAVE_PTYTRAP
/* slaveNames provides a mapping from the pty slave names to our */
/* spawn id entry.  This is needed only on HPs for stty, sigh. */
static Tcl_HashTable slaveNames;
#endif /* HAVE_PTYTRAP */



















#ifdef FULLTRAPS
static void
init_traps(traps)
RETSIGTYPE (*traps[])();
{
	int i;







>
>
>
>
>
>
>


|
|



|








<
<
<

















<
<
<
<
<
<





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119






120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "exp_log.h"
#include "exp_event.h"
#include "exp_pty.h"
#ifdef TCL_DEBUGGER
#include "tcldbg.h"
#endif

/*
 * These constants refer to the UTF string that encodes a null character.
 */

#define NULL_STRING "\300\200" /* hex C080 */
#define NULL_LENGTH 2

#define SPAWN_ID_VARNAME "spawn_id"

int exp_getptymaster();
int exp_getptyslave();

int exp_forked = FALSE;		/* whether we are child process */

/* the following are use to create reserved addresses, to be used as ClientData */
/* args to be used to tell commands how they were called. */
/* The actual values won't be used, only the addresses, but I give them */
/* values out of my irrational fear the compiler might collapse them all. */
static int sendCD_error = 2;	/* called as send_error */
static int sendCD_user = 3;	/* called as send_user */
static int sendCD_proc = 4;	/* called as send or send_spawn */
static int sendCD_tty = 6;	/* called as send_tty */




/*
 * expect_key is just a source for generating a unique stamp.  As each
 * expect/interact command begins, it generates a new key and marks all
 * the spawn ids of interest with it.  Then, if someone comes along and
 * marks them with yet a newer key, the old command will recognize this
 * reexamine the state of the spawned process.
 */
int expect_key = 0;

/*
 * exp_configure_count is incremented whenever a spawned process is closed
 * or an indirect list is modified.  This forces any (stack of) expect or
 * interact commands to reexamine the state of the world and adjust
 * accordingly.
 */
int exp_configure_count = 0;







#ifdef HAVE_PTYTRAP
/* slaveNames provides a mapping from the pty slave names to our */
/* spawn id entry.  This is needed only on HPs for stty, sigh. */
static Tcl_HashTable slaveNames;
#endif /* HAVE_PTYTRAP */

typedef struct ThreadSpecificData {
    /*
     * List of all exp channels currently open.  This is per thread and is
     * used to match up fd's to channels, which rarely occurs.
     */
    
    ExpState *stdinout;
    ExpState *stderrX;   /* grr....stderr is a macro */
    ExpState *devtty;
    ExpState *any; /* for any_spawn_id */

    Tcl_Channel *diagChannel;
    Tcl_DString diagDString;
    int diagEnabled;
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

#ifdef FULLTRAPS
static void
init_traps(traps)
RETSIGTYPE (*traps[])();
{
	int i;
155
156
157
158
159
160
161

162
163
164
165
166
167

168
169
170
171
172
173
174


175













176
177
178
179
180



181

182
183











184
185
186

187
188
189
190


191



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

305
306
307
308
309

310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328



329

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

350
351
352


353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388
389
390


391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450


451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

474
475
476

477
478
479
480
481
482
483
484
485
486
487

488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514
515
516
517
518

519

520

521
522
523
524

525
526
527
528
529
530
531
532
533
534

535


536
537
538
539
540
541
542

543
544


545

546
547
548

549
550
551
552



553
554
555
556
557
558
559
560
561
562
563
564


565
566
567
568
569
570
571
exp_error TCL_VARARGS_DEF(Tcl_Interp *,arg1)
/*exp_error(va_alist)*/
/*va_dcl*/
{
	Tcl_Interp *interp;
	char *fmt;
	va_list args;


	interp = TCL_VARARGS_START(Tcl_Interp *,arg1,args);
	/*va_start(args);*/
	/*interp = va_arg(args,Tcl_Interp *);*/
	fmt = va_arg(args,char *);
	vsprintf(interp->result,fmt,args);

	va_end(args);
}

/* returns handle if fd is usable, 0 if not */
struct exp_f *
exp_fd2f(interp,fd,opened,adjust,msg)
Tcl_Interp *interp;


int fd;













int opened;		/* check not closed */
int adjust;		/* adjust buffer sizes */
char *msg;
{
	if (fd >= 0 && fd <= exp_fd_max && (exp_fs[fd].valid)) {



		struct exp_f *f = exp_fs + fd;


		/* following is a little tricky, do not be tempted do the */











		/* 'usual' boolean simplification */
		if ((!opened) || !f->user_closed) {
			if (adjust) exp_adjust(f);

			return f;
		}
	}



	exp_error(interp,"%s: invalid spawn id (%d)",msg,fd);



	return(0);
}

#if 0
/* following routine is not current used, but might be later */
/* returns fd or -1 if no such entry */
static int
pid_to_fd(pid)
int pid;
{
	int fd;

	for (fd=0;fd<=exp_fd_max;fd++) {
		if (exp_fs[fd].pid == pid) return(fd);
	}
	return 0;
}
#endif

/* Tcl needs commands in writable space */
static char close_cmd[] = "close";

/* zero out the wait status field */
static void
exp_wait_zero(status)
WAIT_STATUS_TYPE *status;
{
	int i;

	for (i=0;i<sizeof(WAIT_STATUS_TYPE);i++) {
		((char *)status)[i] = 0;
	}
}

/* prevent an fd from being allocated */
void
exp_busy(fd)
int fd;
{
	int x = open("/dev/null",0);
	if (x != fd) {
		fcntl(x,F_DUPFD,fd);
		close(x);
	}
	exp_close_on_exec(fd);
}

/* called just before an exp_f entry is about to be invalidated */
void
exp_f_prep_for_invalidation(interp,f)
Tcl_Interp *interp;
struct exp_f *f;
{
	int fd = f - exp_fs;

	exp_ecmd_remove_fd_direct_and_indirect(interp,fd);

	exp_configure_count++;

	if (f->buffer) {
		ckfree(f->buffer);
		f->buffer = 0;
		f->msize = 0;
		f->size = 0;
		f->printed = 0;
		f->echoed = 0;
		if (f->fg_armed) {
			exp_event_disarm(f-exp_fs);
			f->fg_armed = FALSE;
		}
		ckfree(f->lower);
	}
	f->fg_armed = FALSE;
}

/*ARGSUSED*/
void
exp_trap_on(master)
int master;
{
#ifdef HAVE_PTYTRAP
	if (master == -1) return;
	exp_slave_control(master,1);
#endif /* HAVE_PTYTRAP */
}

int
exp_trap_off(name)
char *name;
{
#ifdef HAVE_PTYTRAP
	int master;
	struct exp_f *f;
	int enable = 0;

	Tcl_HashEntry *entry = Tcl_FindHashEntry(&slaveNames,name);
	if (!entry) {
		debuglog("exp_trap_off: no entry found for %s\n",name);
		return -1;
	}

	f = (struct exp_f *)Tcl_GetHashValue(entry);
	master = f - exp_fs;

	exp_slave_control(master,0);

	return master;
#else
	return name[0];	/* pacify lint, use arg and return something */
#endif
}

/*ARGSUSED*/

void
sys_close(fd,f)
int fd;
struct exp_f *f;
{

	/* Ignore close errors.  Some systems are really odd and */
	/* return errors for no evident reason.  Anyway, receiving */
	/* an error upon pty-close doesn't mean anything anyway as */
	/* far as I know. */
	close(fd);
	f->sys_closed = TRUE;

#ifdef HAVE_PTYTRAP
	if (f->slave_name) {
		Tcl_HashEntry *entry;

		entry = Tcl_FindHashEntry(&slaveNames,f->slave_name);
		Tcl_DeleteHashEntry(entry);

		ckfree(f->slave_name);
		f->slave_name = 0;
	}
#endif
}





/* given a Tcl file identifier, close it */
static void
close_tcl_file(interp,file_id)
Tcl_Interp *interp;
char *file_id;
{
    Tcl_VarEval(interp,"close ",file_id,(char *)0);

#if 0  /* old Tcl 7.6 code */
    char *argv[3];
    Tcl_CmdInfo info;

    argv[0] = close_cmd;
    argv[1] = file_id;
    argv[2] = 0;

    Tcl_ResetResult(interp);
    Tcl_GetCommandInfo(interp,"close",&info);
    if (0 == Tcl_GetCommandInfo(interp,"close",&info)) {
        info.clientData = 0;

    }
    (void) Tcl_CloseCmd(info.clientData,interp,2,argv);
#endif


}			


/* close all connections
The kernel would actually do this by default, however Tcl is going to
come along later and try to reap its exec'd processes.  If we have
inherited any via spawn -open, Tcl can hang if we don't close the
connections first.

*/

void
exp_close_all(interp)
Tcl_Interp *interp;
{
	int fd;

	for (fd=0;fd<=exp_fd_max;fd++) {
		if (exp_fs[fd].valid) {
			exp_close(interp,fd);
		}
	}
}

int
exp_close(interp,fd)

Tcl_Interp *interp;
int fd;
{
	struct exp_f *f = exp_fd2f(interp,fd,1,0,"close");
	if (!f) return(TCL_ERROR);

	f->user_closed = TRUE;

	if (f->slave_fd != EXP_NOFD) close(f->slave_fd);
#if 0
	if (f->tcl_handle) {
		ckfree(f->tcl_handle);
		if ((f - exp_fs) != f->tcl_output) close(f->tcl_output);


	}
#endif
	sys_close(fd,f);

	if (f->tcl_handle) {
		if ((f - exp_fs) != f->tcl_output) close(f->tcl_output);

		if (!f->leaveopen) {
			/*
			 * Ignore errors from close; they report things like
			 * broken pipeline, etc, which don't affect our
			 * subsequent handling.
			 */

			close_tcl_file(interp,f->tcl_handle);

			ckfree(f->tcl_handle);
			f->tcl_handle = 0;
		}
	}

	exp_f_prep_for_invalidation(interp,f);

	if (f->user_waited) {
		f->valid = FALSE;
	} else {
		exp_busy(fd);
		f->sys_closed = FALSE;
	}

	return(TCL_OK);
}

static struct exp_f *
fd_new(fd,pid)
int fd;
int pid;

{
	int i, low;
	struct exp_f *newfs;	/* temporary, so we don't lose old exp_fs */

	/* resize table if nec */
	if (fd > exp_fd_max) {
		if (!exp_fs) {	/* no fd's yet allocated */
			newfs = (struct exp_f *)ckalloc(sizeof(struct exp_f)*(fd+1));
			low = 0;
		} else {		/* enlarge fd table */
			newfs = (struct exp_f *)ckrealloc((char *)exp_fs,sizeof(struct exp_f)*(fd+1));
			low = exp_fd_max+1;
		}
		exp_fs = newfs;
		exp_fd_max = fd;
		for (i = low; i <= exp_fd_max; i++) { /* init new fd entries */
			exp_fs[i].valid = FALSE;
			exp_fs[i].fd_ptr = (int *)ckalloc(sizeof(int));
			*exp_fs[i].fd_ptr = i;

/*			exp_fs[i].ptr = (struct exp_f **)ckalloc(sizeof(struct exp_fs *));*/

		}



#if 0
		for (i = 0; i <= exp_fd_max; i++) { /* update all indirect ptrs */
			*exp_fs[i].ptr = exp_fs + i;
		}
#endif
	}

	/* this could happen if user does "spawn -open stdin" I suppose */
	if (exp_fs[fd].valid) return exp_fs+fd;

	/* close down old table entry if nec */
	exp_fs[fd].pid = pid;
	exp_fs[fd].size = 0;
	exp_fs[fd].msize = 0;
	exp_fs[fd].buffer = 0;
	exp_fs[fd].printed = 0;
	exp_fs[fd].echoed = 0;
	exp_fs[fd].rm_nulls = exp_default_rm_nulls;
	exp_fs[fd].parity = exp_default_parity;
	exp_fs[fd].key = expect_key++;
	exp_fs[fd].force_read = FALSE;
	exp_fs[fd].fg_armed = FALSE;

#if TCL_MAJOR_VERSION < 8
	/* Master must be inited each time because Tcl could have alloc'd */
	/* this fd and shut it down (deallocating the FileHandle) behind */

	/* our backs */
	exp_fs[fd].Master = Tcl_GetFile((ClientData)fd,TCL_UNIX_FD);
	exp_fs[fd].MasterOutput = 0;
	exp_fs[fd].Slave = 0;
#endif /* TCL_MAJOR_VERSION < 8 */
	exp_fs[fd].tcl_handle = 0;
	exp_fs[fd].slave_fd = EXP_NOFD;
#ifdef HAVE_PTYTRAP
	exp_fs[fd].slave_name = 0;
#endif /* HAVE_PTYTRAP */
	exp_fs[fd].umsize = exp_default_match_max;

	exp_fs[fd].valid = TRUE;
	exp_fs[fd].user_closed = FALSE;
	exp_fs[fd].sys_closed = FALSE;
	exp_fs[fd].user_waited = FALSE;
	exp_fs[fd].sys_waited = FALSE;
	exp_fs[fd].bg_interp = 0;
	exp_fs[fd].bg_status = unarmed;
	exp_fs[fd].bg_ecount = 0;

	return exp_fs+fd;
}

#if 0
void
exp_global_init(eg,duration,location)
struct expect_global *eg;
int duration;
int location;
{

	eg->ecases = 0;
	eg->ecount = 0;
	eg->i_list = 0;
	eg->duration = duration;
	eg->location = location;
}
#endif

void
exp_init_spawn_id_vars(interp)
Tcl_Interp *interp;
{

	Tcl_SetVar(interp,"user_spawn_id",EXP_SPAWN_ID_USER_LIT,0);

	Tcl_SetVar(interp,"error_spawn_id",EXP_SPAWN_ID_ERROR_LIT,0);


	/* note that the user_spawn_id is NOT /dev/tty which could */
	/* (at least in theory anyway) be later re-opened on a different */
	/* fd, while stdin might have been redirected away from /dev/tty */


	if (exp_dev_tty != -1) {
		char dev_tty_str[10];
		sprintf(dev_tty_str,"%d",exp_dev_tty);
		Tcl_SetVar(interp,"tty_spawn_id",dev_tty_str,0);
	}
}

void
exp_init_spawn_ids()

{


	/* note whether 0,1,2 are connected to a terminal so that if we */
	/* disconnect, we can shut these down.  We would really like to */
	/* test if 0,1,2 are our controlling tty, but I don't know any */
	/* way to do that portably.  Anyway, the likelihood of anyone */
	/* disconnecting after redirecting to a non-controlling tty is */
	/* virtually zero. */


	fd_new(0,isatty(0)?exp_getpid:EXP_NOPID);
	fd_new(1,isatty(1)?exp_getpid:EXP_NOPID);


	fd_new(2,isatty(2)?exp_getpid:EXP_NOPID);


	if (exp_dev_tty != -1) {
		fd_new(exp_dev_tty,exp_getpid);

	}

	/* really should be in interpreter() but silly to do on every call */
	exp_adjust(&exp_fs[0]);



}

void
exp_close_on_exec(fd)
int fd;
{
	(void) fcntl(fd,F_SETFD,1);
}

#define STTY_INIT	"stty_init"

#if 0


static void
show_pgrp(fd,string)
int fd;
char *string;
{
	int pgrp;








>


<
<

|
>



|
|
|

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|

|
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
|
|

>
>
|
>
>
>

|

<
<
<
<
<
<
<
<
|
<
<
|
|

<
<
<
<













<
<
<
<
<
<
<
<
<
<
<
<
<
|

|

|

<
<
|

|

<
<
<
<
<
<
<
|
|
<
|
<
<
<


















|
<
|

|
|
|
|
|

|
<
|
|

|

|



<
>

|
<
|
|
>
|
|
<
<
|
<
|
<
<
<
|
|
<
|
<
<
|
|
<
>
>
>
|
>
|
<
<
<
<
|
<
|
<
<
<
|
|
<
<
|
<
<
<
<
>
|
<
|
>
>
|
|
|
|
<
<
|
<
>
|
|
<
<
<
<
<
|
<
<
<
|
|
<
|
<
<
>
|
<
|
<
<
|
<
|
<
<
<
<
|
>
>
|

<

<
|

|
<
<
<
<
<
|
|
|
<
<
<
<
|
<
|
<
<
|
|
<
|

|


|
|
|
|
>

<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
|
|
>
>
|
<
<
|
|
<
<
|
<
<
|
<
<
<
<
<
<
<
|
|
|
|
<
>
|
|
|
>
|
<
<
|
<
|
<
<
<
<
<
>
|
<
<
<
<
<
<
<

|


|
<
<
|
<
<

>
|
<
<
|
<

<





>
|
>
|
>

|
|
|
>

|
<
<
|
|



|
>

>
>
|
|
|
|
|
|

>
|
|
>
>
|
>

|
|
>
|

<
<
>
>
>



|


|





>
>







160
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235








236


237
238
239




240
241
242
243
244
245
246
247
248
249
250
251
252













253
254
255
256
257
258


259
260
261
262







263
264

265



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
301
302

303
304
305

306
307
308
309
310


311

312



313
314

315


316
317

318
319
320
321
322
323




324

325



326
327


328




329
330

331
332
333
334
335
336
337


338

339
340
341





342



343
344

345


346
347

348


349

350




351
352
353
354
355

356

357
358
359





360
361
362




363

364


365
366

367
368
369
370
371
372
373
374
375
376
377


378








379






380

381
382
383
384
385


386
387


388


389







390
391
392
393

394
395
396
397
398
399


400

401





402
403







404
405
406
407
408


409


410
411
412


413

414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431


432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461


462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
exp_error TCL_VARARGS_DEF(Tcl_Interp *,arg1)
/*exp_error(va_alist)*/
/*va_dcl*/
{
	Tcl_Interp *interp;
	char *fmt;
	va_list args;
	char buffer[2000];

	interp = TCL_VARARGS_START(Tcl_Interp *,arg1,args);


	fmt = va_arg(args,char *);
	vsprintf(buffer,fmt,args);
	Tcl_SetResult(interp,buffer,TCL_VOLATILE);
	va_end(args);
}

/* returns current ExpState or 0.  If 0, may be immediately followed by return TCL_ERROR. */
struct ExpState *
expStateCurrent(interp,opened,adjust,any)
Tcl_Interp *interp;
int opened;
int adjust;
int any;
{
    static char *user_spawn_id = "exp0";

    char *name = exp_get_var(interp,SPAWN_ID_VARNAME);
    if (!name) name = user_spawn_id;

    return expStateFromChannelName(interp,name,opened,adjust,any,SPAWN_ID_VARNAME);
}

ExpState *
expStateCheck(interp,esPtr,open,adjust,msg)
    Tcl_Interp *interp;
    ExpState *esPtr;
    int open;
    int adjust;
    char *msg;
{
    if (open && !esPtr->open) {
	exp_error(interp,"%s: spawn id %s not open",msg,esPtr->name);
	return(0);
    }
    if (adjust) expAdjust(esPtr);
    return esPtr;
}

ExpState *
expStateFromChannelName(interp,name,open,adjust,any,msg)
    Tcl_Interp *interp;
    char *name;
    int open;
    int adjust;
    char *msg;
{
    ExpState *esPtr;
    Tcl_Channel channel;
    char *chanName;

    if (any) {
	if (0 == strcmp(name,EXP_SPAWN_ID_ANY_LIT)) {
	    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	    return tsdPtr->any;
	}
    }

    channel = Tcl_GetChannel(interp,name,(int *)0);
    if (!channel) return(0);

    chanName = Tcl_GetChannelName(channel);
    if (!isExpChannelName(chanName)) {
	exp_error(interp,"%s: %s is not an expect channel - use spawn -open to convert",msg,chanName);
	return(0);
    }









    esPtr = (ExpState *)Tcl_GetChannelInstanceData(channel);



    return expStateCheck(interp,esPtr,open,adjust,msg);
}





/* zero out the wait status field */
static void
exp_wait_zero(status)
WAIT_STATUS_TYPE *status;
{
	int i;

	for (i=0;i<sizeof(WAIT_STATUS_TYPE);i++) {
		((char *)status)[i] = 0;
	}
}














/* called just before an ExpState entry is about to be invalidated */
void
exp_state_prep_for_invalidation(interp,esPtr)
Tcl_Interp *interp;
ExpState *esPtr;
{


    exp_ecmd_remove_state_direct_and_indirect(interp,esPtr);

    exp_configure_count++;








    if (esPtr->fg_armed) {
	exp_event_disarm_fg(esPtr);

    }



}

/*ARGSUSED*/
void
exp_trap_on(master)
int master;
{
#ifdef HAVE_PTYTRAP
	if (master == -1) return;
	exp_slave_control(master,1);
#endif /* HAVE_PTYTRAP */
}

int
exp_trap_off(name)
char *name;
{
#ifdef HAVE_PTYTRAP
    ExpState *esPtr;

    int enable = 0;

    Tcl_HashEntry *entry = Tcl_FindHashEntry(&slaveNames,name);
    if (!entry) {
	expDiagLog("exp_trap_off: no entry found for %s\n",name);
	return -1;
    }

    esPtr = (ExpState *)Tcl_GetHashValue(entry);

    
    exp_slave_control(esPtr->fdin,0);

    return esPtr->fdin;
#else
    return name[0];	/* pacify lint, use arg and return something */
#endif
}


static
void
expBusy(esPtr)

     ExpState *esPtr;
{     
  int x = open("/dev/null",0);
  if (x != esPtr->fdin) {
    fcntl(x,F_DUPFD,esPtr->fdin);


    close(x);

  }



  expCloseOnExec(esPtr->fdin);
  esPtr->fdBusy = TRUE;

}



int

exp_close(interp,esPtr)
Tcl_Interp *interp;
ExpState *esPtr;
{
    if (0 == expStateCheck(interp,esPtr,1,0,"close")) return TCL_ERROR;
    esPtr->open = FALSE;






    /*



     * Ignore close errors from ptys.  Ptys on some systems return errors for
     * no evident reason.  Anyway, receiving an error upon pty-close doesn't


     * mean anything anyway as far as I know.  




     */


    close(esPtr->fdin);
    if (esPtr->fd_slave != EXP_NOFD) close(esPtr->fd_slave);
    if (esPtr->fdin != esPtr->fdout) close(esPtr->fdout);

    if (esPtr->channel_orig && !esPtr->leaveopen) {
	/*
	 * Ignore close errors from Tcl channels.  They indicate things


	 * like broken pipelines, etc, which don't affect our

	 * subsequent handling.
	 */
	Tcl_VarEval(interp,"close ",Tcl_GetChannelName(esPtr->channel_orig),





		(char *)0);



    }


#ifdef HAVE_PTYTRAP


    if (esPtr->slave_name) {
	Tcl_HashEntry *entry;

	


	entry = Tcl_FindHashEntry(&slaveNames,esPtr->slave_name);

	Tcl_DeleteHashEntry(entry);





	ckfree(esPtr->slave_name);
	esPtr->slave_name = 0;
    }
#endif



    exp_state_prep_for_invalidation(interp,esPtr);

    if (esPtr->user_waited) {





	if (esPtr->registered) {
	    Tcl_UnregisterChannel(interp,esPtr->channel);
	    /* at this point esPtr may have been freed so don't touch it




               any longer */

	}


    } else {
      expBusy(esPtr);

    }

    return(TCL_OK);
}

/* report whether this ExpState represents special spawn_id_any */
/* we need a separate function because spawn_id_any is thread-specific */
/* and can't be seen outside this file */
expStateAnyIs(esPtr)
    ExpState *esPtr;
{


    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);















    return (esPtr == tsdPtr->any);

}

expDevttyIs(esPtr)
    ExpState *esPtr;
{


    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);



    return (esPtr == tsdPtr->devtty);


}








int
expStdinoutIs(esPtr)
ExpState *esPtr;

{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    return (tsdPtr->stdinout == esPtr);
}



ExpState *

expStdinoutGet()





{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);








    return tsdPtr->stdinout;
}

ExpState *


expDevttyGet()


{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);



    return tsdPtr->devtty;

}


void
exp_init_spawn_id_vars(interp)
Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_SetVar(interp, "user_spawn_id", tsdPtr->stdinout->name,0);
    Tcl_SetVar(interp,"error_spawn_id",  tsdPtr->stderrX->name,0);
    Tcl_SetVar(interp,  "any_spawn_id",   EXP_SPAWN_ID_ANY_LIT,0);

    /* user_spawn_id is NOT /dev/tty which could (at least in theory
     * anyway) be later re-opened on a different fd, while stdin might
     * have been redirected away from /dev/tty
     */

    if (exp_dev_tty != -1) {


	Tcl_SetVar(interp,"tty_spawn_id",tsdPtr->devtty->name,0);
    }
}

void
exp_init_spawn_ids(interp)
    Tcl_Interp *interp;
{
    static ExpState any_placeholder;  /* can be shared process-wide */
    
    /* note whether 0,1,2 are connected to a terminal so that if we */
    /* disconnect, we can shut these down.  We would really like to */
    /* test if 0,1,2 are our controlling tty, but I don't know any */
    /* way to do that portably.  Anyway, the likelihood of anyone */
    /* disconnecting after redirecting to a non-controlling tty is */
    /* virtually zero. */

    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tsdPtr->stdinout = expCreateChannel(interp,0,1,isatty(0)?exp_getpid:EXP_NOPID);
    tsdPtr->stdinout->keepForever = 1;
    /* hmm, now here's an example of a output-only descriptor!! */
    tsdPtr->stderrX = expCreateChannel(interp,2,2,isatty(2)?exp_getpid:EXP_NOPID);
    tsdPtr->stderrX->keepForever = 1;

    if (exp_dev_tty != -1) {
	tsdPtr->devtty = expCreateChannel(interp,exp_dev_tty,exp_dev_tty,exp_getpid);
	tsdPtr->devtty->keepForever = 1;
    }



    /* set up a dummy channel to give us something when we need to find out if
       people have passed us "any_spawn_id" */
    tsdPtr->any = &any_placeholder;
}

void
expCloseOnExec(fd)
int fd;
{
     (void) fcntl(fd,F_SETFD,1);
}

#define STTY_INIT	"stty_init"

#if 0
/*
 * DEBUGGING UTILITIES - DON'T DELETE */
static void
show_pgrp(fd,string)
int fd;
char *string;
{
	int pgrp;

584
585
586
587
588
589
590


















591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800

801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838




839
840
841
842
843




844

845

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116


1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
{
	int pgrp = getpgrp(0);
	if (-1 == ioctl(fd,TIOCSETPGRP,&pgrp)) perror("TIOCSETPGRP");
	if (-1 == ioctl(fd,TIOCSPGRP,&pgrp)) perror("TIOCSPGRP");
	if (-1 == tcsetpgrp(fd,pgrp)) perror("tcsetpgrp");
}
#endif



















/*ARGSUSED*/
static void
set_slave_name(f,name)
struct exp_f *f;
char *name;
{
#ifdef HAVE_PTYTRAP
	int newptr;
	Tcl_HashEntry *entry;

	/* save slave name */
	f->slave_name = ckalloc(strlen(exp_pty_slave_name)+1);
	strcpy(f->slave_name,exp_pty_slave_name);

	entry = Tcl_CreateHashEntry(&slaveNames,exp_pty_slave_name,&newptr);
	Tcl_SetHashValue(entry,(ClientData)f);
#endif /* HAVE_PTYTRAP */
}

/* arguments are passed verbatim to execvp() */
/*ARGSUSED*/
static int
Exp_SpawnCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{

	int slave;
	int pid;
	char **a;
	/* tell Saber to ignore non-use of ttyfd */
	/*SUPPRESS 591*/
	int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
	int ttyfd;
	int master;
	int write_master;	/* write fd of Tcl-opened files */
	int ttyinit = TRUE;
	int ttycopy = TRUE;
	int echo = TRUE;
	int console = FALSE;
	int pty_only = FALSE;

#ifdef FULLTRAPS
				/* Allow user to reset signals in child */
				/* The following array contains indicates */
				/* whether sig should be DFL or IGN */
				/* ERR is used to indicate no initialization */
	RETSIGTYPE (*traps[NSIG])();
#endif
	int ignore[NSIG];	/* if true, signal in child is ignored */
				/* if false, signal gets default behavior */
	int i;			/* trusty overused temporary */

	char *argv0 = argv[0];
	char *openarg = 0;
	int leaveopen = FALSE;
	FILE *readfilePtr;
	FILE *writefilePtr;
	int rc, wc;
	char *stty_init;
	int slave_write_ioctls = 1;
		/* by default, slave will be write-ioctled this many times */
	int slave_opens = 3;
		/* by default, slave will be opened this many times */
		/* first comes from initial allocation */
		/* second comes from stty */
		/* third is our own signal that stty is done */

	int sync_fds[2];
	int sync2_fds[2];
	int status_pipe[2];
	int child_errno;
	char sync_byte;

	char buf[4];		/* enough space for a string literal */
				/* representing a file descriptor */
	Tcl_DString dstring;
	Tcl_DStringInit(&dstring);

#ifdef FULLTRAPS
	init_traps(&traps);
#endif
	/* don't ignore any signals in child by default */
	for (i=1;i<NSIG;i++) {
		ignore[i] = FALSE;
	}

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-nottyinit")) {
			ttyinit = FALSE;
			slave_write_ioctls--;
			slave_opens--;
		} else if (streq(*argv,"-nottycopy")) {
			ttycopy = FALSE;
		} else if (streq(*argv,"-noecho")) {
			echo = FALSE;
		} else if (streq(*argv,"-console")) {
			console = TRUE;
		} else if (streq(*argv,"-pty")) {
			pty_only = TRUE;
		} else if (streq(*argv,"-open")) {
			if (argc < 2) {
				exp_error(interp,"usage: -open file-identifier");
				return TCL_ERROR;
			}
			openarg = argv[1];
			argc--; argv++;
		} else if (streq(*argv,"-leaveopen")) {
			if (argc < 2) {
				exp_error(interp,"usage: -open file-identifier");
				return TCL_ERROR;
			}
			openarg = argv[1];
			leaveopen = TRUE;
			argc--; argv++;
		} else if (streq(*argv,"-ignore")) {
			int sig;

			if (argc < 2) {
				exp_error(interp,"usage: -ignore signal");
				return TCL_ERROR;
			}
			sig = exp_string_to_signal(interp,argv[1]);
			if (sig == -1) {
				exp_error(interp,"usage: -ignore %s: unknown signal name",argv[1]);
				return TCL_ERROR;
			}
			ignore[sig] = TRUE;
			argc--; argv++;
#ifdef FULLTRAPS
		} else if (streq(*argv,"-trap")) {
			/* argv[1] is action */
			/* argv[2] is list of signals */

			RETSIGTYPE (*sig_handler)();
			int n;		/* number of signals in list */
			char **list;	/* list of signals */

			if (argc < 3) {
				exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN");
				return TCL_ERROR;
			}

			if (0 == strcmp(argv[2],"SIG_DFL")) {
				sig_handler = SIG_DFL;
			} else if (0 == strcmp(argv[2],"SIG_IGN")) {
				sig_handler = SIG_IGN;
			} else {
				exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN");
				return TCL_ERROR;
			}

			if (TCL_OK != Tcl_SplitList(interp,argv[1],&n,&list)) {
				errorlog("%s\r\n",interp->result);

				exp_error(interp,"usage: -trap {siglist} ...");
				return TCL_ERROR;
			}
			for (i=0;i<n;i++) {
				int sig = exp_string_to_signal(interp,list[i]);
				if (sig == -1) {
					ckfree((char *)&list);
					return TCL_ERROR;
				}
				traps[sig] = sig_handler;
			}
			ckfree((char *)&list);

			argc--; argv++;
			argc--; argv++;
#endif /*FULLTRAPS*/
		} else break;
	}

	if (openarg && (argc != 0)) {
		exp_error(interp,"usage: -[leave]open [fileXX]");
		return TCL_ERROR;
	}

	if (!pty_only && !openarg && (argc == 0)) {
		exp_error(interp,"usage: spawn [spawn-args] program [program-args]");
		return(TCL_ERROR);
	}

	stty_init = exp_get_var(interp,STTY_INIT);
	if (stty_init) {
		slave_write_ioctls++;
		slave_opens++;
	}

/* any extraneous ioctl's that occur in slave must be accounted for
when trapping, see below in child half of fork */
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
	slave_write_ioctls++;
	slave_opens++;
#endif

	exp_pty_slave_name = 0;

	Tcl_ReapDetachedProcs();

	if (!openarg) {
		if (echo) {
			exp_log(0,"%s ",argv0);
			for (a = argv;*a;a++) {
				exp_log(0,"%s ",*a);

			}
			exp_nflog("\r\n",0);
		}

		if (0 > (master = getptymaster())) {
			/*
			 * failed to allocate pty, try and figure out why
			 * so we can suggest to user what to do about it.
			 */

			int count;
			int testfd;

			if (exp_pty_error) {
				exp_error(interp,"%s",exp_pty_error);
				return TCL_ERROR;
			}

			count = 0;
			for (i=3;i<=exp_fd_max;i++) {
				count += exp_fs[i].valid;
			}
			if (count > 10) {
				exp_error(interp,"The system only has a finite number of ptys and you have many of them in use.  The usual reason for this is that you forgot (or didn't know) to call \"wait\" after closing each of them.");
				return TCL_ERROR;
			}

			testfd = open("/",0);
			close(testfd);

			if (testfd != -1) {
				exp_error(interp,"The system has no more ptys.  Ask your system administrator to create more.");
			} else {
				exp_error(interp,"- You have too many files are open.  Close some files or increase your per-process descriptor limit.");
			}
			return(TCL_ERROR);
		}
#ifdef PTYTRAP_DIES




		if (!pty_only) exp_slave_control(master,1);
#endif /* PTYTRAP_DIES */

#define SPAWN_OUT "spawn_out"
		Tcl_SetVar2(interp,SPAWN_OUT,"slave,name",exp_pty_slave_name,0);




	} else {

		Tcl_Channel chan;

		int mode;
#if TCL_MAJOR_VERSION < 8
		Tcl_File tclReadFile, tclWriteFile;
#endif /* TCL_MAJOR_VERSION < 8 */
		int rfd, wfd;

		if (echo) exp_log(0,"%s [open ...]\r\n",argv0);

#if TCL7_4
		rc = Tcl_GetOpenFile(interp,openarg,0,1,&readfilePtr);
		wc = Tcl_GetOpenFile(interp,openarg,1,1,&writefilePtr);

		/* fail only if both descriptors are bad */
		if (rc == TCL_ERROR && wc == TCL_ERROR) {
			return TCL_ERROR;		
		}

		master = fileno((rc == TCL_OK)?readfilePtr:writefilePtr);

		/* make a new copy of file descriptor */
		if (-1 == (write_master = master = dup(master))) {
			exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
			return TCL_ERROR;
		}

		/* if writefilePtr is different, dup that too */
		if ((rc == TCL_OK) && (wc == TCL_OK) && (fileno(writefilePtr) != fileno(readfilePtr))) {
			if (-1 == (write_master = dup(fileno(writefilePtr)))) {
				exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
				return TCL_ERROR;
			}
			exp_close_on_exec(write_master);
		}

#endif
		if (!(chan = Tcl_GetChannel(interp,openarg,&mode))) {
			return TCL_ERROR;
		}
		if (!mode) {
			exp_error(interp,"channel is neither readable nor writable");
			return TCL_ERROR;
		}
		if (mode & TCL_READABLE) {
#if TCL_MAJOR_VERSION < 8
			tclReadFile = Tcl_GetChannelFile(chan, TCL_READABLE);
			rfd = (int)Tcl_GetFileInfo(tclReadFile, (int *)0);
#else
			if (TCL_ERROR == Tcl_GetChannelHandle(chan, TCL_READABLE, (ClientData) &rfd)) {
				return TCL_ERROR;
			}
#endif
		}
		if (mode & TCL_WRITABLE) {
#if TCL_MAJOR_VERSION < 8
			tclWriteFile = Tcl_GetChannelFile(chan, TCL_WRITABLE);
			wfd = (int)Tcl_GetFileInfo(tclWriteFile, (int *)0);
#else
			if (TCL_ERROR == Tcl_GetChannelHandle(chan, TCL_WRITABLE, (ClientData) &wfd)) {
				return TCL_ERROR;
			}
#endif
		}

		master = ((mode & TCL_READABLE)?rfd:wfd);

		/* make a new copy of file descriptor */
		if (-1 == (write_master = master = dup(master))) {
			exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
			return TCL_ERROR;
		}

		/* if writefilePtr is different, dup that too */
		if ((mode & TCL_READABLE) && (mode & TCL_WRITABLE) && (wfd != rfd)) {
			if (-1 == (write_master = dup(wfd))) {
				exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
				return TCL_ERROR;
			}
			exp_close_on_exec(write_master);
		}

		/*
		 * It would be convenient now to tell Tcl to close its
		 * file descriptor.  Alas, if involved in a pipeline, Tcl
		 * will be unable to complete a wait on the process.
		 * So simply remember that we meant to close it.  We will
		 * do so later in our own close routine.
		 */
	}

	/* much easier to set this, than remember all masters */
	exp_close_on_exec(master);

	if (openarg || pty_only) {
		struct exp_f *f;

		f = fd_new(master,EXP_NOPID);

		if (openarg) {
			/* save file# handle */
			f->tcl_handle = ckalloc(strlen(openarg)+1);
			strcpy(f->tcl_handle,openarg);

			f->tcl_output = write_master;
#if 0
			/* save fd handle for output */
			if (wc == TCL_OK) {
/*				f->tcl_output = fileno(writefilePtr);*/
				f->tcl_output = write_master;
			} else {
				/* if we actually try to write to it at some */
				/* time in the future, then this will cause */
				/* an error */
				f->tcl_output = master;
			}
#endif

			f->leaveopen = leaveopen;
		}

		if (exp_pty_slave_name) set_slave_name(f,exp_pty_slave_name);

		/* make it appear as if process has been waited for */
		f->sys_waited = TRUE;
		exp_wait_zero(&f->wait);

		/* tell user id of new process */
		sprintf(buf,"%d",master);
		Tcl_SetVar(interp,SPAWN_ID_VARNAME,buf,0);

		if (!openarg) {
			char value[20];
			int dummyfd1, dummyfd2;

			/*
			 * open the slave side in the same process to support
			 * the -pty flag.
			 */

			/* Start by working around a bug in Tcl's exec.
			   It closes all the file descriptors from 3 to it's
			   own fd_max which inappropriately closes our slave
			   fd.  To avoid this, open several dummy fds.  Then
			   exec's fds will fall below ours.
			   Note that if you do something like pre-allocating
			   a bunch before using them or generating a pipeline,
			   then this code won't help.
			   Instead you'll need to add the right number of
			   explicit Tcl open's of /dev/null.
			   The right solution is fix Tcl's exec so it is not
			   so cavalier.
			 */

			dummyfd1 = open("/dev/null",0);
			dummyfd2 = open("/dev/null",0);

			if (0 > (f->slave_fd = getptyslave(ttycopy,ttyinit,
					stty_init))) {
				exp_error(interp,"open(slave pty): %s\r\n",Tcl_PosixError(interp));
				return TCL_ERROR;
			}

			close(dummyfd1);
			close(dummyfd2);

			exp_slave_control(master,1);

			sprintf(value,"%d",f->slave_fd);
			Tcl_SetVar2(interp,SPAWN_OUT,"slave,fd",value,0);
		}
		sprintf(interp->result,"%d",EXP_NOPID);
		debuglog("spawn: returns {%s}\r\n",interp->result);

		return TCL_OK;
	}

	if (NULL == (argv[0] = Tcl_TildeSubst(interp,argv[0],&dstring))) {
		goto parent_error;
	}

	if (-1 == pipe(sync_fds)) {
		exp_error(interp,"too many programs spawned?  could not create pipe: %s",Tcl_PosixError(interp));
		goto parent_error;
	}

	if (-1 == pipe(sync2_fds)) {
		close(sync_fds[0]);
		close(sync_fds[1]);
		exp_error(interp,"too many programs spawned?  could not create pipe: %s",Tcl_PosixError(interp));
		goto parent_error;
	}

	if (-1 == pipe(status_pipe)) {
		close(sync_fds[0]);
		close(sync_fds[1]);
		close(sync2_fds[0]);
		close(sync2_fds[1]);
	}

	if ((pid = fork()) == -1) {
		exp_error(interp,"fork: %s",Tcl_PosixError(interp));
		goto parent_error;
	}

	if (pid) { /* parent */
		struct exp_f *f;

		close(sync_fds[1]);
		close(sync2_fds[0]);
		close(status_pipe[1]);

		f = fd_new(master,pid);

		if (exp_pty_slave_name) set_slave_name(f,exp_pty_slave_name);

#ifdef CRAY
		setptypid(pid);
#endif


#if PTYTRAP_DIES
#ifdef HAVE_PTYTRAP

		while (slave_opens) {
			int cc;
			cc = exp_wait_for_slave_open(master);
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
			if (cc == TIOCSCTTY) slave_opens = 0;
#endif
			if (cc == TIOCOPEN) slave_opens--;
			if (cc == -1) {
				exp_error(interp,"failed to trap slave pty");
				goto parent_error;
			}
		}

#if 0
		/* trap initial ioctls in a feeble attempt to not block */
		/* the initially.  If the process itself ioctls */
		/* /dev/tty, such blocks will be trapped later */
		/* during normal event processing */

		/* initial slave ioctl */
		while (slave_write_ioctls) {
			int cc;

			cc = exp_wait_for_slave_open(master);
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
			if (cc == TIOCSCTTY) slave_write_ioctls = 0;
#endif
			if (cc & IOC_IN) slave_write_ioctls--;
			else if (cc == -1) {
				exp_error(interp,"failed to trap slave pty");
				goto parent_error;
			}
		}
#endif /*0*/

#endif /* HAVE_PTYTRAP */
#endif /* PTYTRAP_DIES */

		/*
		 * wait for slave to initialize pty before allowing
		 * user to send to it
		 */ 

		debuglog("parent: waiting for sync byte\r\n");
		while (((rc = read(sync_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) {
			/* empty */;
		}
		if (rc == -1) {
			errorlog("parent: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));


			exit(-1);
		}

		/* turn on detection of eof */
		exp_slave_control(master,1);

		/*
		 * tell slave to go on now now that we have initialized pty
		 */

		debuglog("parent: telling child to go ahead\r\n");
		wc = write(sync2_fds[1]," ",1);
		if (wc == -1) {
			errorlog("parent: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
			exit(-1);
		}

		debuglog("parent: now unsynchronized from child\r\n");
		close(sync_fds[0]);
		close(sync2_fds[1]);

		/* see if child's exec worked */
	retry:
		switch (read(status_pipe[0],&child_errno,sizeof child_errno)) {
		case -1:
			if (errno == EINTR) goto retry;
			/* well it's not really the child's errno */
			/* but it can be treated that way */
			child_errno = errno;
			break;
		case 0:
			/* child's exec succeeded */
			child_errno = 0;
			break;
		default:
			/* child's exec failed; err contains exec's errno  */
			waitpid(pid, NULL, 0);
			/* in order to get Tcl to set errorcode, we must */
			/* hand set errno */
			errno = child_errno;
			exp_error(interp, "couldn't execute \"%s\": %s",
				argv[0],Tcl_PosixError(interp));
			goto parent_error;
		}
		close(status_pipe[0]);


		/* tell user id of new process */
		sprintf(buf,"%d",master);
		Tcl_SetVar(interp,SPAWN_ID_VARNAME,buf,0);

		sprintf(interp->result,"%d",pid);
		debuglog("spawn: returns {%s}\r\n",interp->result);

		Tcl_DStringFree(&dstring);
		return(TCL_OK);
parent_error:
		Tcl_DStringFree(&dstring);
		return TCL_ERROR;
	}

	/* child process - do not return from here!  all errors must exit() */

	close(sync_fds[0]);
	close(sync2_fds[1]);
	close(status_pipe[0]);
	exp_close_on_exec(status_pipe[1]);

	if (exp_dev_tty != -1) {
		close(exp_dev_tty);
		exp_dev_tty = -1;
	}

#ifdef CRAY







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|







|
|


|












>
|
|
|
|
|
|

|
|
|
|
|
|
|
|






|

|

|

|
|
|
<
<
|
|
|

|





|
|
|
|
|

|
<
|
|


|

|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
>
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|

|
|
|
|

|
|
|
|

|
|
|
|
|




|
|


|
|
|

|
|
|
|
|
>
|
|
|

|
|
|
|
|

<
|
|
|
|
|
|

<
<
<
<
|
|
|
|

|
|

|
|
|
|
|
|
|
|
>
>
>
>
|
<


|
>
>
>
>
|
>
|
>
|
<
<
<
|
|
|
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
<
<
<
<
|
|
|
<
|
|
<
<
<
<
|
|
|
<
|
<
|

|
|
|
|
|

|
|
|
|
|
|
<
|

|
|
|
|
|
|
|
|
|
<
<
<
|
<
<
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|

|

|
|
|

|
<
|

|
|
<

|
|
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|

<
<
<
|
|
|
|
|
|
|

|
|

|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|

|
<
<
|
|
|

|

|


|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|

|
|
|
|
|
|
>
>
|
|

|
|

|
|
|

|
|
|
|
|
|

|
|
|

|

|

|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|

<
|
<
|

|
|

|
|
<
<
<







|







498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582


583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

743
744
745
746
747
748
749




750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778
779
780
781
782



783
784
785
786



787



788



















789
790
791
792
793
794
795
796




797
798
799

800
801




802
803
804

805

806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829
830



831


832
833




834













835
836
837
838
839
840
841
842
843
844
845

846
847
848
849

850
851
852
853
854
855

















856
857
858
859
860
861



862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901


902
903
904
905
906
907
908
909
910
911
912
913










































914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972

973

974
975
976
977
978
979
980



981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
{
	int pgrp = getpgrp(0);
	if (-1 == ioctl(fd,TIOCSETPGRP,&pgrp)) perror("TIOCSETPGRP");
	if (-1 == ioctl(fd,TIOCSPGRP,&pgrp)) perror("TIOCSPGRP");
	if (-1 == tcsetpgrp(fd,pgrp)) perror("tcsetpgrp");
}
#endif

static
void
expSetpgrp()
{
#ifdef MIPS_BSD
    /* required on BSD side of MIPS OS <[email protected]> */
#   include <sysv/sys.s>
    syscall(SYS_setpgrp);
#endif

#ifdef SETPGRP_VOID
    (void) setpgrp();
#else
    (void) setpgrp(0,0);
#endif
}


/*ARGSUSED*/
static void
set_slave_name(esPtr,name)
ExpState *esPtr;
char *name;
{
#ifdef HAVE_PTYTRAP
	int newptr;
	Tcl_HashEntry *entry;

	/* save slave name */
	esPtr->slave_name = ckalloc(strlen(exp_pty_slave_name)+1);
	strcpy(esPtr->slave_name,exp_pty_slave_name);

	entry = Tcl_CreateHashEntry(&slaveNames,exp_pty_slave_name,&newptr);
	Tcl_SetHashValue(entry,(ClientData)esPtr);
#endif /* HAVE_PTYTRAP */
}

/* arguments are passed verbatim to execvp() */
/*ARGSUSED*/
static int
Exp_SpawnCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    ExpState *esPtr = 0;
    int slave;
    int pid;
    char **a;
    /* tell Saber to ignore non-use of ttyfd */
    /*SUPPRESS 591*/
    int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
    int ttyfd;
    int master;
    int write_master;	/* write fd of Tcl-opened files */
    int ttyinit = TRUE;
    int ttycopy = TRUE;
    int echo = TRUE;
    int console = FALSE;
    int pty_only = FALSE;

#ifdef FULLTRAPS
				/* Allow user to reset signals in child */
				/* The following array contains indicates */
				/* whether sig should be DFL or IGN */
				/* ERR is used to indicate no initialization */
    RETSIGTYPE (*traps[NSIG])();
#endif
    int ignore[NSIG];		/* if true, signal in child is ignored */
				/* if false, signal gets default behavior */
    int i;			/* trusty overused temporary */

    char *argv0 = argv[0];
    char *chanName = 0;
    int leaveopen = FALSE;


    int rc, wc;
    char *stty_init;
    int slave_write_ioctls = 1;
		/* by default, slave will be write-ioctled this many times */
    int slave_opens = 3;
		/* by default, slave will be opened this many times */
		/* first comes from initial allocation */
		/* second comes from stty */
		/* third is our own signal that stty is done */

    int sync_fds[2];
    int sync2_fds[2];
    int status_pipe[2];
    int child_errno;
    char sync_byte;

    Tcl_Channel channel;

    Tcl_DString dstring;
    Tcl_DStringInit(&dstring);

#ifdef FULLTRAPS
    init_traps(&traps);
#endif
    /* don't ignore any signals in child by default */
    for (i=1;i<NSIG;i++) {
	ignore[i] = FALSE;
    }

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-nottyinit")) {
	    ttyinit = FALSE;
	    slave_write_ioctls--;
	    slave_opens--;
	} else if (streq(*argv,"-nottycopy")) {
	    ttycopy = FALSE;
	} else if (streq(*argv,"-noecho")) {
	    echo = FALSE;
	} else if (streq(*argv,"-console")) {
	    console = TRUE;
	} else if (streq(*argv,"-pty")) {
	    pty_only = TRUE;
	} else if (streq(*argv,"-open")) {
	    if (argc < 2) {
		exp_error(interp,"usage: -open file-identifier");
		return TCL_ERROR;
	    }
	    chanName = argv[1];
	    argc--; argv++;
	} else if (streq(*argv,"-leaveopen")) {
	    if (argc < 2) {
		exp_error(interp,"usage: -open file-identifier");
		return TCL_ERROR;
	    }
	    chanName = argv[1];
	    leaveopen = TRUE;
	    argc--; argv++;
	} else if (streq(*argv,"-ignore")) {
	    int sig;

	    if (argc < 2) {
		exp_error(interp,"usage: -ignore signal");
		return TCL_ERROR;
	    }
	    sig = exp_string_to_signal(interp,argv[1]);
	    if (sig == -1) {
		exp_error(interp,"usage: -ignore %s: unknown signal name",argv[1]);
		return TCL_ERROR;
	    }
	    ignore[sig] = TRUE;
	    argc--; argv++;
#ifdef FULLTRAPS
	} else if (streq(*argv,"-trap")) {
	    /* argv[1] is action */
	    /* argv[2] is list of signals */

	    RETSIGTYPE (*sig_handler)();
	    int n;		/* number of signals in list */
	    char **list;	/* list of signals */
	    
	    if (argc < 3) {
		exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN");
		return TCL_ERROR;
	    }

	    if (0 == strcmp(argv[2],"SIG_DFL")) {
		sig_handler = SIG_DFL;
	    } else if (0 == strcmp(argv[2],"SIG_IGN")) {
		sig_handler = SIG_IGN;
	    } else {
		exp_error(interp,"usage: -trap siglist SIG_DFL or SIG_IGN");
		return TCL_ERROR;
	    }

	    if (TCL_OK != Tcl_SplitList(interp,argv[1],&n,&list)) {
		expErrorLogU(interp->result);
		expErrorLogU("\r\n");
		exp_error(interp,"usage: -trap {siglist} ...");
		return TCL_ERROR;
	    }
	    for (i=0;i<n;i++) {
		int sig = exp_string_to_signal(interp,list[i]);
		if (sig == -1) {
		    ckfree((char *)&list);
		    return TCL_ERROR;
		}
		traps[sig] = sig_handler;
	    }
	    ckfree((char *)&list);

	    argc--; argv++;
	    argc--; argv++;
#endif /*FULLTRAPS*/
	} else break;
    }

    if (chanName && (argc != 0)) {
	exp_error(interp,"usage: -[leave]open [fileXX]");
	return TCL_ERROR;
    }

    if (!pty_only && !chanName && (argc == 0)) {
	exp_error(interp,"usage: spawn [spawn-args] program [program-args]");
	return(TCL_ERROR);
    }

    stty_init = exp_get_var(interp,STTY_INIT);
    if (stty_init) {
	slave_write_ioctls++;
	slave_opens++;
    }

/* any extraneous ioctl's that occur in slave must be accounted for
when trapping, see below in child half of fork */
#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
    slave_write_ioctls++;
    slave_opens++;
#endif

    exp_pty_slave_name = 0;
    
    Tcl_ReapDetachedProcs();

    if (!chanName) {
	if (echo) {
	    expStdoutLogU(argv0,0);
	    for (a = argv;*a;a++) {
		expStdoutLogU(" ",0);
		expStdoutLogU(*a,0);
	    }
	    expStdoutLogU("\r\n",0);
	}

	if (0 > (master = exp_getptymaster())) {
	    /*
	     * failed to allocate pty, try and figure out why
	     * so we can suggest to user what to do about it.
	     */


	    int testfd;
		
	    if (exp_pty_error) {
		exp_error(interp,"%s",exp_pty_error);
		return TCL_ERROR;
	    }





	    if (expChannelCountGet() > 10) {
		exp_error(interp,"The system only has a finite number of ptys and you have many of them in use.  The usual reason for this is that you forgot (or didn't know) to call \"wait\" after closing each of them.");
		return TCL_ERROR;
	    }

	    testfd = open("/",0);
	    close(testfd);

	    if (testfd != -1) {
		exp_error(interp,"The system has no more ptys.  Ask your system administrator to create more.");
	    } else {
		exp_error(interp,"- You have too many files are open.  Close some files or increase your per-process descriptor limit.");
	    }
	    return(TCL_ERROR);
	}

	/* ordinarily channel creation takes care of close-on-exec
	 * but because that will occur *after* fork, force close-on-exec
	 * now in this case.
	 */
	expCloseOnExec(master);


#define SPAWN_OUT "spawn_out"
	Tcl_SetVar2(interp,SPAWN_OUT,"slave,name",exp_pty_slave_name,0);

	if (pty_only) {
	  write_master = master;
	}
    } else {
	/*
	 * process "-open $channel"
	 */
	int mode;



	int rfd, wfd;
	
	if (echo) {
	    expStdoutLogU(argv0,0);



	    expStdoutLogU(" [open ...]\r\n",0);



	}



















	if (!(channel = Tcl_GetChannel(interp,chanName,&mode))) {
	    return TCL_ERROR;
	}
	if (!mode) {
	    exp_error(interp,"channel is neither readable nor writable");
	    return TCL_ERROR;
	}
	if (mode & TCL_READABLE) {




	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_READABLE, (ClientData) &rfd)) {
		return TCL_ERROR;
	    }

	}
	if (mode & TCL_WRITABLE) {




	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_WRITABLE, (ClientData) &wfd)) {
		return TCL_ERROR;
	    }    

	}

	master = ((mode & TCL_READABLE)?rfd:wfd);

	/* make a new copy of file descriptor */
	if (-1 == (write_master = master = dup(master))) {
	    exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
	    return TCL_ERROR;
	}

	/* if writefilePtr is different, dup that too */
	if ((mode & TCL_READABLE) && (mode & TCL_WRITABLE) && (wfd != rfd)) {
	    if (-1 == (write_master = dup(wfd))) {
		exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
		return TCL_ERROR;
	    }

	}

	/*
	 * It would be convenient now to tell Tcl to close its
	 * file descriptor.  Alas, if involved in a pipeline, Tcl
	 * will be unable to complete a wait on the process.
	 * So simply remember that we meant to close it.  We will
	 * do so later in our own close routine.
	 */
    }
	



    if (chanName || pty_only) {


	esPtr = expCreateChannel(interp,master,write_master,EXP_NOPID);
	    




	if (chanName) {













	    esPtr->channel_orig = channel;
	    esPtr->leaveopen = leaveopen;
	}

	if (exp_pty_slave_name) set_slave_name(esPtr,exp_pty_slave_name);

	/* make it appear as if process has been waited for */
	esPtr->sys_waited = TRUE;
	exp_wait_zero(&esPtr->wait);

	/* tell user of new spawn id */

	Tcl_SetVar(interp,SPAWN_ID_VARNAME,esPtr->name,0);

	if (!chanName) {
	    char value[20];


	    /*
	     * open the slave side in the same process to support
	     * the -pty flag.
	     */


















	    if (0 > (esPtr->fd_slave = exp_getptyslave(ttycopy,ttyinit,
		    stty_init))) {
		exp_error(interp,"open(slave pty): %s\r\n",Tcl_PosixError(interp));
		return TCL_ERROR;
	    }




	    exp_slave_control(master,1);
	    
	    sprintf(value,"%d",esPtr->fd_slave);
	    Tcl_SetVar2(interp,SPAWN_OUT,"slave,fd",value,0);
	}
	sprintf(interp->result,"%d",EXP_NOPID);
	expDiagLog("spawn: returns {%s}\r\n",interp->result);

	return TCL_OK;
    }

    if (NULL == (argv[0] = Tcl_TranslateFileName(interp,argv[0],&dstring))) {
	goto parent_error;
    }

    if (-1 == pipe(sync_fds)) {
	exp_error(interp,"too many programs spawned?  could not create pipe: %s",Tcl_PosixError(interp));
	goto parent_error;
    }

    if (-1 == pipe(sync2_fds)) {
	close(sync_fds[0]);
	close(sync_fds[1]);
	exp_error(interp,"too many programs spawned?  could not create pipe: %s",Tcl_PosixError(interp));
	goto parent_error;
    }

    if (-1 == pipe(status_pipe)) {
	close(sync_fds[0]);
	close(sync_fds[1]);
	close(sync2_fds[0]);
	close(sync2_fds[1]);
    }

    if ((pid = fork()) == -1) {
	exp_error(interp,"fork: %s",Tcl_PosixError(interp));
	goto parent_error;
    }

    if (pid) { /* parent */


	    close(sync_fds[1]);
	    close(sync2_fds[0]);
	    close(status_pipe[1]);

	    esPtr = expCreateChannel(interp,master,master,pid);

	    if (exp_pty_slave_name) set_slave_name(esPtr,exp_pty_slave_name);

#ifdef CRAY
	    setptypid(pid);
#endif











































	    /*
	     * wait for slave to initialize pty before allowing
	     * user to send to it
	     */ 

	    expDiagLog("parent: waiting for sync byte\r\n");
	    while (((rc = read(sync_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) {
		/* empty */;
	    }
	    if (rc == -1) {
		expErrorLogU("parent: sync byte read: ");
		expErrorLogU(Tcl_ErrnoMsg(errno));
		expErrorLogU("\r\n");
		exit(-1);
	    }

	    /* turn on detection of eof */
	    exp_slave_control(master,1);

	    /*
	     * tell slave to go on now now that we have initialized pty
	     */

	    expDiagLog("parent: telling child to go ahead\r\n");
	    wc = write(sync2_fds[1]," ",1);
	    if (wc == -1) {
		expErrorLog("parent: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	    }

	    expDiagLog("parent: now unsynchronized from child\r\n");
	    close(sync_fds[0]);
	    close(sync2_fds[1]);

	    /* see if child's exec worked */
	retry:
	    switch (read(status_pipe[0],&child_errno,sizeof child_errno)) {
		case -1:
		    if (errno == EINTR) goto retry;
		    /* well it's not really the child's errno */
		    /* but it can be treated that way */
		    child_errno = errno;
		    break;
		case 0:
		    /* child's exec succeeded */
		    child_errno = 0;
		    break;
		default:
		    /* child's exec failed; err contains exec's errno  */
		    waitpid(pid, NULL, 0);
		    /* in order to get Tcl to set errorcode, we must */
		    /* hand set errno */
		    errno = child_errno;
		    exp_error(interp, "couldn't execute \"%s\": %s",
			    argv[0],Tcl_PosixError(interp));
		    goto parent_error;
	    }
	    close(status_pipe[0]);


	    /* tell user of new spawn id */

	    Tcl_SetVar(interp,SPAWN_ID_VARNAME,esPtr->name,0);

	    sprintf(interp->result,"%d",pid);
	    expDiagLog("spawn: returns {%s}\r\n",interp->result);

	    Tcl_DStringFree(&dstring);
	    return(TCL_OK);



	}

	/* child process - do not return from here!  all errors must exit() */

	close(sync_fds[0]);
	close(sync2_fds[1]);
	close(status_pipe[0]);
	expCloseOnExec(status_pipe[1]);

	if (exp_dev_tty != -1) {
		close(exp_dev_tty);
		exp_dev_tty = -1;
	}

#ifdef CRAY
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
#endif

#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
#ifndef CRAY
	setpgrp();
#endif /* CRAY */
#else /* !SYSV3 */
#ifdef MIPS_BSD
	/* required on BSD side of MIPS OS <[email protected]> */
#	include <sysv/sys.s>
	syscall(SYS_setpgrp);
#endif
	setpgrp(0,0);
/*	setpgrp(0,getpid());*/	/* make a new pgrp leader */

/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);







|


<
<
<
<
<
|
<







1006
1007
1008
1009
1010
1011
1012
1013
1014
1015





1016

1017
1018
1019
1020
1021
1022
1023
#endif

#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
#ifndef CRAY
	expSetpgrp();
#endif /* CRAY */
#else /* !SYSV3 */





	expSetpgrp();


/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249




1250

1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278










1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314

	close(0);
	close(1);
	close(2);

	/* since we closed fd 0, open of pty slave must return fd 0 */

	/* since getptyslave may have to run stty, (some of which work on fd */
	/* 0 and some of which work on 1) do the dup's inside getptyslave. */

	if (0 > (slave = getptyslave(ttycopy,ttyinit,stty_init))) {
		restore_error_fd




		errorlog("open(slave pty): %s\r\n",Tcl_ErrnoMsg(errno));

		exit(-1);
	}
	/* sanity check */
	if (slave != 0) {
		restore_error_fd
		errorlog("getptyslave: slave = %d but expected 0\n",slave);
		exit(-1);
	}

/* The test for hpux may have to be more specific.  In particular, the */
/* code should be skipped on the hp9000s300 and hp9000s720 (but there */
/* is no documented define for the 720!) */

/*#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hpux)*/
#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux)
	/* 4.3+BSD way to acquire controlling terminal */
	/* according to Stevens - Adv. Prog..., p 642 */
	/* Oops, it appears that the CIBAUD is on Linux also */
	/* so let's try without... */
#ifdef __QNX__
	if (tcsetct(0, getpid()) == -1) {
#else
	if (ioctl(0,TIOCSCTTY,(char *)0) < 0) {
#endif
		restore_error_fd
		errorlog("failed to get controlling terminal using TIOCSCTTY");
		exit(-1);
	}










#endif

#ifdef CRAY
 	(void) setsid();
 	(void) ioctl(0,TCSETCTTY,0);
 	(void) close(0);
 	if (open("/dev/tty", O_RDWR) < 0) {
		restore_error_fd
 		errorlog("open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno));
 		exit(-1);
 	}
 	(void) close(1);
 	(void) close(2);
 	(void) dup(0);
 	(void) dup(0);
	setptyutmp();	/* create a utmp entry */

	/* _CRAY2 code from Hal Peterson <[email protected]>, Cray Research, Inc. */
#ifdef _CRAY2
	/*
	 * Interpose a process between expect and the spawned child to
	 * keep the slave side of the pty open to allow time for expect
	 * to read the last output.  This is a workaround for an apparent
	 * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at
	 * least).
	 */
	if ((pid = fork()) == -1) {
		restore_error_fd
		errorlog("second fork: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}

	if (pid) {
 		/* Intermediate process. */
		int status;
		int timeout;







|
|

|

>
>
>
>
|
>





|















<
<
<
|
|
|

>
>
>
>
>
>
>
>
>
>








|



















|







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075



1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

	close(0);
	close(1);
	close(2);

	/* since we closed fd 0, open of pty slave must return fd 0 */

	/* since exp_getptyslave may have to run stty, (some of which work on fd */
	/* 0 and some of which work on 1) do the dup's inside exp_getptyslave. */

	if (0 > (slave = exp_getptyslave(ttycopy,ttyinit,stty_init))) {
		restore_error_fd

		if (exp_pty_error) {
			expErrorLog("open(slave pty): %s\r\n",exp_pty_error);
		} else {
			expErrorLog("open(slave pty): %s\r\n",Tcl_ErrnoMsg(errno));
		}
		exit(-1);
	}
	/* sanity check */
	if (slave != 0) {
		restore_error_fd
		expErrorLog("exp_getptyslave: slave = %d but expected 0\n",slave);
		exit(-1);
	}

/* The test for hpux may have to be more specific.  In particular, the */
/* code should be skipped on the hp9000s300 and hp9000s720 (but there */
/* is no documented define for the 720!) */

/*#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hpux)*/
#if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux)
	/* 4.3+BSD way to acquire controlling terminal */
	/* according to Stevens - Adv. Prog..., p 642 */
	/* Oops, it appears that the CIBAUD is on Linux also */
	/* so let's try without... */
#ifdef __QNX__
	if (tcsetct(0, getpid()) == -1) {



	  restore_error_fd
	  expErrorLog("failed to get controlling terminal using TIOCSCTTY");
	  exit(-1);
	}
#else
	(void) ioctl(0,TIOCSCTTY,(char *)0);
	/* ignore return value - on some systems, it is defined but it
	 * fails and it doesn't seem to cause any problems.  Or maybe
	 * it works but returns a bogus code.  Noone seems to be able
	 * to explain this to me.  The systems are an assortment of
	 * different linux systems (and FreeBSD 2.5), RedHat 5.2 and
	 * Debian 2.0
	 */
#endif
#endif

#ifdef CRAY
 	(void) setsid();
 	(void) ioctl(0,TCSETCTTY,0);
 	(void) close(0);
 	if (open("/dev/tty", O_RDWR) < 0) {
		restore_error_fd
 		expErrorLog("open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno));
 		exit(-1);
 	}
 	(void) close(1);
 	(void) close(2);
 	(void) dup(0);
 	(void) dup(0);
	setptyutmp();	/* create a utmp entry */

	/* _CRAY2 code from Hal Peterson <[email protected]>, Cray Research, Inc. */
#ifdef _CRAY2
	/*
	 * Interpose a process between expect and the spawned child to
	 * keep the slave side of the pty open to allow time for expect
	 * to read the last output.  This is a workaround for an apparent
	 * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at
	 * least).
	 */
	if ((pid = fork()) == -1) {
		restore_error_fd
		expErrorLog("second fork: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}

	if (pid) {
 		/* Intermediate process. */
		int status;
		int timeout;
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359

1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414










1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
	}
#endif /* FULLTRAPS */

	for (i=1;i<NSIG;i++) {
		signal(i,ignore[i]?SIG_IGN:SIG_DFL);
	}

#if 0

	/* avoid fflush of cmdfile since this screws up the parents seek ptr */
	/* There is no portable way to fclose a shared read-stream!!!! */
	if (exp_cmdfile && (exp_cmdfile != stdin))

		(void) close(fileno(exp_cmdfile));
	if (logfile) (void) fclose(logfile);
	if (debugfile) (void) fclose(debugfile);
#endif
	/* (possibly multiple) masters are closed automatically due to */
	/* earlier fcntl(,,CLOSE_ON_EXEC); */

	/* tell parent that we are done setting up pty */
	/* The actual char sent back is irrelevant. */

	/* debuglog("child: telling parent that pty is initialized\r\n");*/
	wc = write(sync_fds[1]," ",1);
	if (wc == -1) {
		restore_error_fd
		errorlog("child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync_fds[1]);

	/* wait for master to let us go on */
	/* debuglog("child: waiting for go ahead from parent\r\n"); */

/*	close(master);	/* force master-side close so we can read */

	while (((rc = read(sync2_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) {
		/* empty */;
	}

	if (rc == -1) {
		restore_error_fd
		errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync2_fds[0]);

	/* debuglog("child: now unsynchronized from parent\r\n"); */

	/* So much for close-on-exec.  Tcl doesn't mark its files that way */
	/* everything has to be closed explicitly. */
	if (exp_close_in_child) (*exp_close_in_child)();

        (void) execvp(argv[0],argv);
#if 0
	/* Unfortunately, by now we've closed fd's to stderr, logfile and
		debugfile.
	   The only reasonable thing to do is to send back the error as
	   part of the program output.  This will be picked up in an
	   expect or interact command.
	*/
	errorlog("%s: %s\r\n",argv[0],Tcl_ErrnoMsg(errno));
#endif
	/* if exec failed, communicate the reason back to the parent */
	write(status_pipe[1], &errno, sizeof errno);
	exit(-1);
	/*NOTREACHED*/










}

/*ARGSUSED*/
static int
Exp_ExpPidCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	struct exp_f *f;
	int m = -1;

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-i")) {
			argc--; argv++;
			if (!*argv) goto usage;
			m = atoi(*argv);
		} else goto usage;
	}

	if (m == -1) {
		if (exp_update_master(interp,&m,0,0) == 0) return TCL_ERROR;
	}


	if (0 == (f = exp_fd2f(interp,m,1,0,"exp_pid"))) return TCL_ERROR;

	sprintf(interp->result,"%d",f->pid);
	return TCL_OK;
 usage:
	exp_error(interp,"usage: -i spawn_id");
	return TCL_ERROR;
}

/*ARGSUSED*/
static int
Exp_GetpidDeprecatedCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	debuglog("getpid is deprecated, use pid\r\n");
	sprintf(interp->result,"%d",getpid());
	return(TCL_OK);
}

/* returns current master (via out-parameter) */
/* returns f or 0, but note that since exp_fd2f calls tcl_error, this */
/* may be immediately followed by a "return(TCL_ERROR)"!!! */
struct exp_f *
exp_update_master(interp,m,opened,adjust)
Tcl_Interp *interp;
int *m;
int opened;
int adjust;
{
	char *s = exp_get_var(interp,SPAWN_ID_VARNAME);
	*m = (s?atoi(s):EXP_SPAWN_ID_USER);
	return(exp_fd2f(interp,*m,opened,adjust,(s?s:EXP_SPAWN_ID_USER_LIT)));
}

/*ARGSUSED*/
static int
Exp_SleepCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	argc--; argv++;

	if (argc != 1) {
		exp_error(interp,"must have one arg: seconds");
		return TCL_ERROR;
	}

	return(exp_dsleep(interp,(double)atof(*argv)));
}

/* write exactly this many bytes, i.e. retry partial writes */
/* returns 0 for success, -1 for failure */
static int
exact_write(fd,buffer,rembytes)
int fd;
char *buffer;
int rembytes;
{
	int cc;

	while (rembytes) {
		if (-1 == (cc = write(fd,buffer,rembytes))) return(-1);
		if (0 == cc) {
			/* This shouldn't happen but I'm told that it does */
			/* nonetheless (at least on SunOS 4.1.3).  Since */
			/* this is not a documented return value, the most */
			/* reasonable thing is to complain here and retry */
			/* in the hopes that is some transient condition. */
			sleep(1);
			exp_debuglog("write() failed to write anything but returned - sleeping and retrying...\n");
		}

		buffer += cc;
		rembytes -= cc;
	}
	return(0);
}

struct slow_arg {
	int size;
	double time;
};

/* returns 0 for success, -1 for failure */
static int
get_slow_args(interp,x)
Tcl_Interp *interp;
struct slow_arg *x;







<
>
|
|
|
>
|
<
<
<






|



|





<
<
<
<






|




|

<
<
<
<

|
|
<
|
|
|
|
|
<




>
>
>
>
>
>
>
>
>
>










|
|

|

|
|
|
|
|
|
|

|
|
|
>
|
<
|
|
|
|
|
|










|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















|
|

|
|



<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|



|
|







1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172



1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188




1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201




1202
1203
1204

1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272















1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298

1299















1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
	}
#endif /* FULLTRAPS */

	for (i=1;i<NSIG;i++) {
		signal(i,ignore[i]?SIG_IGN:SIG_DFL);
	}


	/*
	 * avoid fflush of cmdfile, logfile, & diagfile since this screws up
	 * the parents seek ptr.  There is no portable way to fclose a shared
	 * read-stream!!!!
	 */




	/* (possibly multiple) masters are closed automatically due to */
	/* earlier fcntl(,,CLOSE_ON_EXEC); */

	/* tell parent that we are done setting up pty */
	/* The actual char sent back is irrelevant. */

	/* expDiagLog("child: telling parent that pty is initialized\r\n");*/
	wc = write(sync_fds[1]," ",1);
	if (wc == -1) {
		restore_error_fd
		expErrorLog("child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync_fds[1]);

	/* wait for master to let us go on */




	while (((rc = read(sync2_fds[0],&sync_byte,1)) < 0) && (errno == EINTR)) {
		/* empty */;
	}

	if (rc == -1) {
		restore_error_fd
		expErrorLog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
		exit(-1);
	}
	close(sync2_fds[0]);

	/* expDiagLog("child: now unsynchronized from parent\r\n"); */





        (void) execvp(argv[0],argv);

	/* Alas, by now we've closed fd's to stderr, logfile and diagfile.

	 * The only reasonable thing to do is to send back the error as part of
	 * the program output.  This will be picked up in an expect or interact
	 * command.
	 */


	/* if exec failed, communicate the reason back to the parent */
	write(status_pipe[1], &errno, sizeof errno);
	exit(-1);
	/*NOTREACHED*/
parent_error:
    Tcl_DStringFree(&dstring);
    if (esPtr) {
        exp_close(interp,esPtr);
	waitpid(esPtr->pid,&esPtr->wait,0);
	if (esPtr->registered) {
	    Tcl_UnregisterChannel(interp,esPtr->channel);
	}
    }
    return TCL_ERROR;
}

/*ARGSUSED*/
static int
Exp_ExpPidCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    char *chanName = 0;
    ExpState *esPtr = 0;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-i")) {
	    argc--; argv++;
	    if (!*argv) goto usage;
	    chanName = *argv;
	} else goto usage;
    }

    if (chanName) {
	if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,0,"exp_pid"))) return TCL_ERROR;
    } else {
	if (!(esPtr = expStateCurrent(interp,0,0,0))) return TCL_ERROR;
    }

    
    sprintf(interp->result,"%d",esPtr->pid);
    return TCL_OK;
  usage:
    exp_error(interp,"usage: -i spawn_id");
    return TCL_ERROR;
}

/*ARGSUSED*/
static int
Exp_GetpidDeprecatedCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	expDiagLog("getpid is deprecated, use pid\r\n");
	sprintf(interp->result,"%d",getpid());
	return(TCL_OK);
}
















/*ARGSUSED*/
static int
Exp_SleepCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	argc--; argv++;

	if (argc != 1) {
		exp_error(interp,"must have one arg: seconds");
		return TCL_ERROR;
	}

	return(exp_dsleep(interp,(double)atof(*argv)));
}

/* if this works, exact_write should disappear and function should
   call Tcl_WriteChars directly */
static int
exact_write(esPtr,buffer,rembytes) /* INTL */
ExpState *esPtr;
char *buffer;
int rembytes;
{

    Tcl_WriteChars(esPtr->channel,buffer,rembytes);















    return(0);
}

struct slow_arg {
    int size;
    double time;
};

/* returns 0 for success, -1 for failure */
static int
get_slow_args(interp,x)
Tcl_Interp *interp;
struct slow_arg *x;
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
		return(-1);
	}
	return(0);
}

/* returns 0 for success, -1 for failure, pos. for Tcl return value */
static int
slow_write(interp,fd,buffer,rembytes,arg)
Tcl_Interp *interp;
int fd;
char *buffer;
int rembytes;
struct slow_arg *arg;
{
	int rc;

	while (rembytes > 0) {
		int len;

		len = (arg->size<rembytes?arg->size:rembytes);
		if (0 > exact_write(fd,buffer,len)) return(-1);
		rembytes -= arg->size;
		buffer += arg->size;

		/* skip sleep after last write */
		if (rembytes > 0) {
			rc = exp_dsleep(interp,arg->time);
			if (rc>0) return rc;







|

|








|

|







1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
		return(-1);
	}
	return(0);
}

/* returns 0 for success, -1 for failure, pos. for Tcl return value */
static int
slow_write(interp,esPtr,buffer,rembytes,arg) /* INTL */
Tcl_Interp *interp;
ExpState *esPtr;
char *buffer;
int rembytes;
struct slow_arg *arg;
{
	int rc;

	while (rembytes > 0) {
		int len;
		
		len = (arg->size<rembytes?arg->size:rembytes);
		if (0 > exact_write(esPtr,buffer,len)) return(-1);
		rembytes -= arg->size;
		buffer += arg->size;

		/* skip sleep after last write */
		if (rembytes > 0) {
			rc = exp_dsleep(interp,arg->time);
			if (rc>0) return rc;
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664

1665
1666
1667
1668

1669
1670
1671
1672
1673

1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707

/* This function is my implementation of the Weibull distribution. */
/* I've added a max time and an "alpha_eow" that captures the slight */
/* but noticable change in human typists when hitting end-of-word */
/* transitions. */
/* returns 0 for success, -1 for failure, pos. for Tcl return value */
static int
human_write(interp,fd,buffer,arg)
Tcl_Interp *interp;
int fd;
char *buffer;
struct human_arg *arg;
{
	char *sp;

	float t;
	float alpha;
	int wc;
	int in_word = TRUE;


	debuglog("human_write: avg_arr=%f/%f  1/shape=%f  min=%f  max=%f\r\n",
		arg->alpha,arg->alpha_eow,arg->c,arg->min,arg->max);

	for (sp = buffer;*sp;sp++) {

		/* use the end-of-word alpha at eow transitions */
		if (in_word && (ispunct(*sp) || isspace(*sp)))
			alpha = arg->alpha_eow;
		else alpha = arg->alpha;
		in_word = !(ispunct(*sp) || isspace(*sp));

		t = alpha * pow(-log((double)unit_random()),arg->c);

		/* enforce min and max times */
		if (t<arg->min) t = arg->min;
		else if (t>arg->max) t = arg->max;

/*fprintf(stderr,"\nwriting <%c> but first sleep %f seconds\n",*sp,t);*/
		/* skip sleep before writing first character */
		if (sp != buffer) {
			wc = exp_dsleep(interp,(double)t);
			if (wc > 0) return wc;
		}

		wc = write(fd,sp,1);
		if (0 > wc) return(wc);
	}
	return(0);
}

struct exp_i *exp_i_pool = 0;
struct exp_fd_list *exp_fd_list_pool = 0;

#define EXP_I_INIT_COUNT	10
#define EXP_FD_INIT_COUNT	10

struct exp_i *
exp_new_i()
{







|

|



|
>
|
|
|
|
>

|
|

|
>
|
|
|
|
|

|

|
|
|

<

|
|
|
|

|
|
|
|



|







1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466

1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487

/* This function is my implementation of the Weibull distribution. */
/* I've added a max time and an "alpha_eow" that captures the slight */
/* but noticable change in human typists when hitting end-of-word */
/* transitions. */
/* returns 0 for success, -1 for failure, pos. for Tcl return value */
static int
human_write(interp,esPtr,buffer,arg) /* INTL */
Tcl_Interp *interp;
ExpState *esPtr;
char *buffer;
struct human_arg *arg;
{
    char *sp;
    int size;
    float t;
    float alpha;
    int wc;
    int in_word = TRUE;
    Tcl_UniChar ch;

    expDiagLog("human_write: avg_arr=%f/%f  1/shape=%f  min=%f  max=%f\r\n",
	    arg->alpha,arg->alpha_eow,arg->c,arg->min,arg->max);

    for (sp = buffer;*sp;sp += size) {
	size = Tcl_UtfToUniChar(sp, &ch);
	/* use the end-of-word alpha at eow transitions */
	if (in_word && (Tcl_UniCharIsPunct(ch) || Tcl_UniCharIsSpace(ch)))
	    alpha = arg->alpha_eow;
	else alpha = arg->alpha;
	in_word = !(Tcl_UniCharIsPunct(ch) || Tcl_UniCharIsSpace(ch));

	t = alpha * pow(-log((double)unit_random()),arg->c);

	/* enforce min and max times */
	if (t<arg->min) t = arg->min;
	else if (t>arg->max) t = arg->max;


		/* skip sleep before writing first character */
	if (sp != buffer) {
	    wc = exp_dsleep(interp,(double)t);
	    if (wc > 0) return wc;
	}

	wc = Tcl_WriteChars(esPtr->channel, sp, size);
	if (0 > wc) return(wc);
    }
    return(0);
}

struct exp_i *exp_i_pool = 0;
struct exp_state_list *exp_state_list_pool = 0;

#define EXP_I_INIT_COUNT	10
#define EXP_FD_INIT_COUNT	10

struct exp_i *
exp_new_i()
{
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802

	/* now that we've made some, unlink one and give to user */

	i = exp_i_pool;
	exp_i_pool = exp_i_pool->next;
	i->value = 0;
	i->variable = 0;
	i->fd_list = 0;
	i->ecount = 0;
	i->next = 0;
	return i;
}

struct exp_fd_list *
exp_new_fd(val)
int val;
{
	int n;
	struct exp_fd_list *fd;

	if (!exp_fd_list_pool) {
		/* none avail, generate some new ones */
		exp_fd_list_pool = fd = (struct exp_fd_list *)ckalloc(
			EXP_FD_INIT_COUNT * sizeof(struct exp_fd_list));
		for (n=0;n<EXP_FD_INIT_COUNT-1;n++,fd++) {
			fd->next = fd+1;
		}
		fd->next = 0;
	}

	/* now that we've made some, unlink one and give to user */

	fd = exp_fd_list_pool;
	exp_fd_list_pool = exp_fd_list_pool->next;
	fd->fd = val;
	/* fd->next is assumed to be changed by caller */
	return fd;
}

void
exp_free_fd(fd_first)
struct exp_fd_list *fd_first;
{
	struct exp_fd_list *fd, *penultimate;

	if (!fd_first) return;

	/* link entire chain back in at once by first finding last pointer */
	/* making that point back to pool, and then resetting pool to this */

	/* run to end */
	for (fd = fd_first;fd;fd=fd->next) {
		penultimate = fd;
	}
	penultimate->next = exp_fd_list_pool;
	exp_fd_list_pool = fd_first;
}

/* free a single fd */
void
exp_free_fd_single(fd)
struct exp_fd_list *fd;
{
	fd->next = exp_fd_list_pool;
	exp_fd_list_pool = fd;
}

void
exp_free_i(interp,i,updateproc)
Tcl_Interp *interp;
struct exp_i *i;
Tcl_VarTraceProc *updateproc;	/* proc to invoke if indirect is written */
{
	if (i->next) exp_free_i(interp,i->next,updateproc);

	exp_free_fd(i->fd_list);

	if (i->direct == EXP_INDIRECT) {
		Tcl_UntraceVar(interp,i->variable,
			TCL_GLOBAL_ONLY|TCL_TRACE_WRITES,
			updateproc,(ClientData)i);
	}








|





|
|
|

|
|

|
|
|
|
|
|
|
|
|

|

|
|
|
|
|



|
|

|










|
|




|
|

|
|










|







1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582

	/* now that we've made some, unlink one and give to user */

	i = exp_i_pool;
	exp_i_pool = exp_i_pool->next;
	i->value = 0;
	i->variable = 0;
	i->state_list = 0;
	i->ecount = 0;
	i->next = 0;
	return i;
}

struct exp_state_list *
exp_new_state(esPtr)
ExpState *esPtr;
{
    int n;
    struct exp_state_list *fd;

    if (!exp_state_list_pool) {
	/* none avail, generate some new ones */
	exp_state_list_pool = fd = (struct exp_state_list *)ckalloc(
	    EXP_FD_INIT_COUNT * sizeof(struct exp_state_list));
	for (n=0;n<EXP_FD_INIT_COUNT-1;n++,fd++) {
	    fd->next = fd+1;
	}
	fd->next = 0;
    }

    /* now that we've made some, unlink one and give to user */

    fd = exp_state_list_pool;
    exp_state_list_pool = exp_state_list_pool->next;
    fd->esPtr = esPtr;
    /* fd->next is assumed to be changed by caller */
    return fd;
}

void
exp_free_state(fd_first)
struct exp_state_list *fd_first;
{
	struct exp_state_list *fd, *penultimate;

	if (!fd_first) return;

	/* link entire chain back in at once by first finding last pointer */
	/* making that point back to pool, and then resetting pool to this */

	/* run to end */
	for (fd = fd_first;fd;fd=fd->next) {
		penultimate = fd;
	}
	penultimate->next = exp_state_list_pool;
	exp_state_list_pool = fd_first;
}

/* free a single fd */
void
exp_free_state_single(fd)
struct exp_state_list *fd;
{
	fd->next = exp_state_list_pool;
	exp_state_list_pool = fd;
}

void
exp_free_i(interp,i,updateproc)
Tcl_Interp *interp;
struct exp_i *i;
Tcl_VarTraceProc *updateproc;	/* proc to invoke if indirect is written */
{
	if (i->next) exp_free_i(interp,i->next,updateproc);

	exp_free_state(i->state_list);

	if (i->direct == EXP_INDIRECT) {
		Tcl_UntraceVar(interp,i->variable,
			TCL_GLOBAL_ONLY|TCL_TRACE_WRITES,
			updateproc,(ClientData)i);
	}

1822
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842


1843

1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859



1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884


1885
1886

1887
1888

1889
1890
1891
1892
1893

1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913

1914
1915






1916
1917
1918


1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929

1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016

2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035











2036

2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048


2049
2050
2051
2052

2053
2054

2055
2056

2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069




2070
2071



2072
2073


2074
2075

2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098

2099
2100
2101
2102

2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120

2121
2122
2123
2124
2125
2126
2127
2128
2129
2130


2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173



2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261




2262




2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308

2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340

2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357

2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373

2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483

2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499

2500
2501
2502


2503
2504
2505
2506

2507
2508
2509
2510
2511
2512

2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
	}

	i->next = exp_i_pool;
	exp_i_pool = i;
}

/* generate a descriptor for a "-i" flag */
/* cannot fail */

struct exp_i *
exp_new_i_complex(interp,arg,duration,updateproc)
Tcl_Interp *interp;
char *arg;		/* spawn id list or a variable containing a list */
int duration;		/* if we have to copy the args */
			/* should only need do this in expect_before/after */
Tcl_VarTraceProc *updateproc;	/* proc to invoke if indirect is written */
{
	struct exp_i *i;
	char **stringp;

	i = exp_new_i();



	i->direct = (isdigit(arg[0]) || (arg[0] == '-'))?EXP_DIRECT:EXP_INDIRECT;

	if (i->direct == EXP_DIRECT) {
		stringp = &i->value;
	} else {
		stringp = &i->variable;
	}

	i->duration = duration;
	if (duration == EXP_PERMANENT) {
		*stringp = ckalloc(strlen(arg)+1);
		strcpy(*stringp,arg);
	} else {
		*stringp = arg;
	}

	i->fd_list = 0;
	exp_i_update(interp,i);




	/* if indirect, ask Tcl to tell us when variable is modified */

	if (i->direct == EXP_INDIRECT) {
		Tcl_TraceVar(interp, i->variable,
			TCL_GLOBAL_ONLY|TCL_TRACE_WRITES,
			updateproc, (ClientData) i);
	}

	return i;
}

void
exp_i_add_fd(i,fd)
struct exp_i *i;
int fd;
{
	struct exp_fd_list *new_fd;

	new_fd = exp_new_fd(fd);
	new_fd->next = i->fd_list;
	i->fd_list = new_fd;
}

/* this routine assumes i->fd is meaningful */


void
exp_i_parse_fds(i)

struct exp_i *i;
{

	char *p = i->value;

	/* reparse it */
	while (1) {
		int m;

		int negative = 0;
		int valid_spawn_id = 0;

		m = 0;
		while (isspace(*p)) p++;
		for (;;p++) {
			if (*p == '-') negative = 1;
			else if (isdigit(*p)) {
				m = m*10 + (*p-'0');
				valid_spawn_id = 1;
			} else if (*p == '\0' || isspace(*p)) break;
		}

		/* we either have a spawn_id or whitespace at end of string */

		/* skip whitespace end-of-string */
		if (!valid_spawn_id) break;

		if (negative) m = -m;


		exp_i_add_fd(i,m);
	}






}
	
/* updates a single exp_i struct */


void
exp_i_update(interp,i)
Tcl_Interp *interp;
struct exp_i *i;
{
	char *p;	/* string representation of list of spawn ids */

	if (i->direct == EXP_INDIRECT) {
		p = Tcl_GetVar(interp,i->variable,TCL_GLOBAL_ONLY);
		if (!p) {
			p = "";

			exp_debuglog("warning: indirect variable %s undefined",i->variable);
		}

		if (i->value) {
			if (streq(p,i->value)) return;

			/* replace new value with old */
			ckfree(i->value);
		}
		i->value = ckalloc(strlen(p)+1);
		strcpy(i->value,p);

		exp_free_fd(i->fd_list);
		i->fd_list = 0;
	} else {
		/* no free, because this should only be called on */
		/* "direct" i's once */
		i->fd_list = 0;
	}
	exp_i_parse_fds(i);
}

struct exp_i *
exp_new_i_simple(fd,duration)
int fd;
int duration;		/* if we have to copy the args */
			/* should only need do this in expect_before/after */
{
	struct exp_i *i;

	i = exp_new_i();

	i->direct = EXP_DIRECT;
	i->duration = duration;

	exp_i_add_fd(i,fd);

	return i;
}

/*ARGSUSED*/
static int
Exp_SendLogCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	char *string;
	int len;

	argv++;
	argc--;

	if (argc) {
		if (streq(*argv,"--")) {
			argc--; argv++;
		}
	}

	if (argc != 1) {
		exp_error(interp,"usage: send [args] string");
		return TCL_ERROR;
	}

	string = *argv;

	len = strlen(string);

	if (debugfile) fwrite(string,1,len,debugfile);
	if (logfile) fwrite(string,1,len,logfile);

	return(TCL_OK);
}


/* I've rewritten this to be unbuffered.  I did this so you could shove */
/* large files through "send".  If you are concerned about efficiency */
/* you should quote all your send args to make them one single argument. */
/*ARGSUSED*/
static int
Exp_SendCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{

	int m = -1;	/* spawn id (master) */
	int rc; 	/* final result of this procedure */
	struct human_arg human_args;
	struct slow_arg slow_args;
#define SEND_STYLE_STRING_MASK	0x07	/* mask to detect a real string arg */
#define SEND_STYLE_PLAIN	0x01
#define SEND_STYLE_HUMAN	0x02
#define SEND_STYLE_SLOW		0x04
#define SEND_STYLE_ZERO		0x10
#define SEND_STYLE_BREAK	0x20
	int send_style = SEND_STYLE_PLAIN;
	int want_cooked = TRUE;
	char *string;		/* string to send */
	int len;		/* length of string to send */
	int zeros;		/* count of how many ascii zeros to send */

	char *i_masters = 0;
	struct exp_fd_list *fd;
	struct exp_i *i;











	char *arg;


	argv++;
	argc--;
	while (argc) {
		arg = *argv;
		if (arg[0] != '-') break;
		arg++;
		if (exp_flageq1('-',arg)) {			/* "--" */
			argc--; argv++;
			break;
		} else if (exp_flageq1('i',arg)) {		/* "-i" */
			argc--; argv++;


			if (argc==0) {
				exp_error(interp,"usage: -i spawn_id");
				return(TCL_ERROR);
			}

			i_masters = *argv;
			argc--; argv++;

			continue;
		} else if (exp_flageq1('h',arg)) {		/* "-h" */

			argc--; argv++;
			if (-1 == get_human_args(interp,&human_args))
				return(TCL_ERROR);
			send_style = SEND_STYLE_HUMAN;
			continue;
		} else if (exp_flageq1('s',arg)) {		/* "-s" */
			argc--; argv++;
			if (-1 == get_slow_args(interp,&slow_args))
				return(TCL_ERROR);
			send_style = SEND_STYLE_SLOW;
			continue;
		} else if (exp_flageq("null",arg,1) || exp_flageq1('0',arg)) {
			argc--; argv++;				/* "-null" */




			if (!*argv) zeros = 1;
			else {



				zeros = atoi(*argv);
				argc--; argv++;


				if (zeros < 1) return TCL_OK;
			}

			send_style = SEND_STYLE_ZERO;
			string = "<zero(s)>";
			continue;
		} else if (exp_flageq("raw",arg,1)) {		/* "-raw" */
			argc--; argv++;
			want_cooked = FALSE;
			continue;
		} else if (exp_flageq("break",arg,1)) {		/* "-break" */
			argc--; argv++;
			send_style = SEND_STYLE_BREAK;
			string = "<break>";
			continue;
		} else {
			exp_error(interp,"usage: unrecognized flag <-%.80s>",arg);
			return TCL_ERROR;
		}
	}

	if (send_style & SEND_STYLE_STRING_MASK) {
		if (argc != 1) {
			exp_error(interp,"usage: send [args] string");
			return TCL_ERROR;
		}

		string = *argv;
	}
	len = strlen(string);


	if (clientData == &sendCD_user) m = 1;
	else if (clientData == &sendCD_error) m = 2;
	else if (clientData == &sendCD_tty) m = exp_dev_tty;
	else if (!i_masters) {
		/* we really do want to check if it is open */
		/* but since stdin could be closed, we have to first */
		/* get the fd and then convert it from 0 to 1 if necessary */
		if (0 == exp_update_master(interp,&m,0,0))
			return(TCL_ERROR);
	}

	/* if master != -1, then it holds desired master */
	/* else i_masters does */

	if (m != -1) {
		i = exp_new_i_simple(m,EXP_TEMPORARY);
	} else {
		i = exp_new_i_complex(interp,i_masters,FALSE,(Tcl_VarTraceProc *)0);

	}

#define send_to_stderr	(clientData == &sendCD_error)
#define send_to_proc	(clientData == &sendCD_proc)
#define send_to_user	((clientData == &sendCD_user) || \
			 (clientData == &sendCD_tty))

	if (send_to_proc) {
		want_cooked = FALSE;
		debuglog("send: sending \"%s\" to {",dprintify(string));


		/* if closing brace doesn't appear, that's because an error */
		/* was encountered before we could send it */
	} else {
		if (debugfile)
			fwrite(string,1,len,debugfile);
		if ((send_to_user && logfile_all) || logfile)
			fwrite(string,1,len,logfile);
	}

	for (fd=i->fd_list;fd;fd=fd->next) {
		m = fd->fd;

		if (send_to_proc) {
			debuglog(" %d ",m);
		}

		/* true if called as Send with user_spawn_id */
		if (exp_is_stdinfd(m)) m = 1;

		/* check validity of each - i.e., are they open */
		if (0 == exp_fd2f(interp,m,1,0,"send")) {
			rc = TCL_ERROR;
			goto finish;
		}
		/* Check if Tcl is using a different fd for output */
		if (exp_fs[m].tcl_handle) {
			m = exp_fs[m].tcl_output;
		}

		if (want_cooked) string = exp_cook(string,&len);

		switch (send_style) {
		case SEND_STYLE_PLAIN:
			rc = exact_write(m,string,len);
			break;
		case SEND_STYLE_SLOW:
			rc = slow_write(interp,m,string,len,&slow_args);
			break;
		case SEND_STYLE_HUMAN:
			rc = human_write(interp,m,string,&human_args);
			break;
		case SEND_STYLE_ZERO:
			for (;zeros>0;zeros--) rc = write(m,"",1);



			/* catching error on last write is sufficient */
			rc = ((rc==1) ? 0 : -1);   /* normal is 1 not 0 */
			break;
		case SEND_STYLE_BREAK:
			exp_tty_break(interp,m);
			rc = 0;
			break;
		}

		if (rc != 0) {
			if (rc == -1) {
				exp_error(interp,"write(spawn_id=%d): %s",m,Tcl_PosixError(interp));
				rc = TCL_ERROR;
			}
			goto finish;
		}
	}
	if (send_to_proc) debuglog("}\r\n");

	rc = TCL_OK;
 finish:
	exp_free_i(interp,i,(Tcl_VarTraceProc *)0);
	return rc;
}

/*ARGSUSED*/
static int
Exp_LogFileCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	static Tcl_DString dstring;
	static int first_time = TRUE;
	static int current_append;	/* true if currently appending */
	static char *openarg = 0;	/* Tcl file identifier from -open */
	static int leaveopen = FALSE;	/* true if -leaveopen was used */

	int old_logfile_all = logfile_all;
	FILE *old_logfile = logfile;
	char *old_openarg = openarg;
	int old_leaveopen = leaveopen;

	int aflag = FALSE;
	int append = TRUE;
	char *filename = 0;
	char *type;
	FILE *writefilePtr;
	int usage_error_occurred = FALSE;

	openarg = 0;
	leaveopen = FALSE;

	if (first_time) {
		Tcl_DStringInit(&dstring);
		first_time = FALSE;
	}


#define usage_error	if (0) ; else {\
				 usage_error_occurred = TRUE;\
				 goto error;\
			}

	/* when this function returns, we guarantee that if logfile_all */
	/* is TRUE, then logfile is non-zero */

	argv++;
	argc--;
	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-open")) {
			if (!argv[1]) usage_error;
			openarg = ckalloc(strlen(argv[1])+1);
			strcpy(openarg,argv[1]);
			argc--; argv++;
		} else if (streq(*argv,"-leaveopen")) {
			if (!argv[1]) usage_error;
			openarg = ckalloc(strlen(argv[1])+1);
			strcpy(openarg,argv[1]);
			leaveopen = TRUE;
			argc--; argv++;
		} else if (streq(*argv,"-a")) {
			aflag = TRUE;
		} else if (streq(*argv,"-info")) {

			if (logfile) {
				if (logfile_all) strcat(interp->result,"-a ");
				if (!current_append) strcat(interp->result,"-noappend ");




				strcat(interp->result,Tcl_DStringValue(&dstring));




			}
			return TCL_OK;
		} else if (streq(*argv,"-noappend")) {
			append = FALSE;
		} else break;
	}

	if (argc == 1) {
		filename = argv[0];
	} else if (argc > 1) {
		/* too many arguments */
		usage_error
	} 

	if (openarg && filename) {
		usage_error
	}
	if (aflag && !(openarg || filename)) {
		usage_error
	}

	logfile = 0;
	logfile_all = aflag;

	current_append = append;

	type = (append?"a":"w");

	if (filename) {
		filename = Tcl_TildeSubst(interp,filename,&dstring);
		if (filename == NULL) {
			goto error;
		} else {
			/* Tcl_TildeSubst doesn't store into dstring */
			/* if no ~, so force string into dstring */
			/* this is only needed so that next time around */
			/* we can get dstring for -info if necessary */
			if (Tcl_DStringValue(&dstring)[0] == '\0') {
				Tcl_DStringAppend(&dstring,filename,-1);
			}
		}

		errno = 0;
		if (NULL == (logfile = fopen(filename,type))) {
			char *msg;


			if (errno == 0) {
				msg = open_failed;
			} else {
				msg = Tcl_PosixError(interp);
			}
			exp_error(interp,"%s: %s",filename,msg);
			Tcl_DStringFree(&dstring);
			goto error;
		}
	} else if (openarg) {
		int cc;
		int fd;
		Tcl_Channel chan;
		int mode;
#if TCL_MAJOR_VERSION < 8
		Tcl_File tclWriteFile;
#endif /* TCL_MAJOR_VERSION < 8 */

		Tcl_DStringTrunc(&dstring,0);

#if TCL7_4
		cc = Tcl_GetOpenFile(interp,openarg,1,1,&writefilePtr);
		if (cc == TCL_ERROR) goto error;

		if (-1 == (fd = dup(fileno(writefilePtr)))) {
			exp_error(interp,"dup: %s",Tcl_PosixError(interp));
			goto error;
		}
#endif
		if (!(chan = Tcl_GetChannel(interp,openarg,&mode))) {
			return TCL_ERROR;
		}

		if (!(mode & TCL_WRITABLE)) {
			exp_error(interp,"channel is not writable");
		}
#if TCL_MAJOR_VERSION < 8
		tclWriteFile = Tcl_GetChannelFile(chan, TCL_WRITABLE);
		fd = dup((int)Tcl_GetFileInfo(tclWriteFile, (int *)0));
#else
		if (TCL_ERROR == Tcl_GetChannelHandle(chan, TCL_WRITABLE, (ClientData) &fd)) {
			goto error;
		}
		fd = dup(fd);
#endif
	
		if (!(logfile = fdopen(fd,type))) {
			exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
			close(fd);
			goto error;

		}

		if (leaveopen) {
			Tcl_DStringAppend(&dstring,"-leaveopen ",-1);
		} else {
			Tcl_DStringAppend(&dstring,"-open ",-1);
		}
		Tcl_DStringAppend(&dstring,openarg,-1);

		/*
		 * It would be convenient now to tell Tcl to close its

		 * file descriptor.  Alas, if involved in a pipeline, Tcl
		 * will be unable to complete a wait on the process.
		 * So simply remember that we meant to close it.  We will
		 * do so later in our own close routine.
		 */

	}
	if (logfile) {
		setbuf(logfile,(char *)0);
		exp_close_on_exec(fileno(logfile));
	}

	if (old_logfile) {
		fclose(old_logfile);
	}

	if (old_openarg) {
		if (!old_leaveopen) {
			close_tcl_file(interp,old_openarg);
		}
		ckfree((char *)old_openarg);
	}

	return TCL_OK;

 error:
	if (old_logfile) {
		logfile = old_logfile;
		logfile_all = old_logfile_all;
	}

	if (openarg) ckfree(openarg);
	openarg = old_openarg;
	leaveopen = old_leaveopen;

	if (usage_error_occurred) {
		exp_error(interp,"usage: log_file [-info] [-noappend] [[-a] file] [-[leave]open [open ...]]");
	}

	return TCL_ERROR;
}

/*ARGSUSED*/
static int
Exp_LogUserCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int old_loguser = loguser;

	if (argc == 0 || (argc == 2 && streq(argv[1],"-info"))) {
		/* do nothing */
	} else if (argc == 2) {
		if (0 == atoi(argv[1])) loguser = FALSE;
		else loguser = TRUE;
	} else {
		exp_error(interp,"usage: [-info|1|0]");
	}

	sprintf(interp->result,"%d",old_loguser);

	return(TCL_OK);
}

#ifdef TCL_DEBUGGER
/*ARGSUSED*/
static int
Exp_DebugCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int now = FALSE;	/* soon if FALSE, now if TRUE */
	int exp_tcl_debugger_was_available = exp_tcl_debugger_available;

	if (argc > 3) goto usage;

	if (argc == 1) {
		sprintf(interp->result,"%d",exp_tcl_debugger_available);
		return TCL_OK;
	}

	argv++;

	while (*argv) {
		if (streq(*argv,"-now")) {
			now = TRUE;
			argv++;
		}
		else break;
	}

	if (!*argv) {
		if (now) {
			Dbg_On(interp,1);
			exp_tcl_debugger_available = 1;
		} else {
			goto usage;
		}
	} else if (streq(*argv,"0")) {
		Dbg_Off(interp);
		exp_tcl_debugger_available = 0;
	} else {
		Dbg_On(interp,now);
		exp_tcl_debugger_available = 1;
	}
	sprintf(interp->result,"%d",exp_tcl_debugger_was_available);
	return(TCL_OK);
 usage:
	exp_error(interp,"usage: [[-now] 1|0]");
	return TCL_ERROR;
}
#endif


/*ARGSUSED*/
static int
Exp_ExpInternalCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	static Tcl_DString dstring;
	static int first_time = TRUE;
	int fopened = FALSE;

	if (first_time) {
		Tcl_DStringInit(&dstring);
		first_time = FALSE;

	}

	if (argc > 1 && streq(argv[1],"-info")) {


		if (debugfile) {
			sprintf(interp->result,"-f %s ",
				Tcl_DStringValue(&dstring));
		}

		strcat(interp->result,((exp_is_debugging==0)?"0":"1"));
		return TCL_OK;
	}

	argv++;
	argc--;

	while (argc) {
		if (!streq(*argv,"-f")) break;
		argc--;argv++;
		if (argc < 1) goto usage;
		if (debugfile) fclose(debugfile);
		argv[0] = Tcl_TildeSubst(interp, argv[0],&dstring);
		if (argv[0] == NULL) goto error;
		else {
			/* Tcl_TildeSubst doesn't store into dstring */
			/* if no ~, so force string into dstring */
			/* this is only needed so that next time around */
			/* we can get dstring for -info if necessary */
			if (Tcl_DStringValue(&dstring)[0] == '\0') {
				Tcl_DStringAppend(&dstring,argv[0],-1);
			}
		}

		errno = 0;
		if (NULL == (debugfile = fopen(*argv,"a"))) {
			char *msg;

			if (errno == 0) {
				msg = open_failed;
			} else {
				msg = Tcl_PosixError(interp);
			}

			exp_error(interp,"%s: %s",*argv,msg);
			goto error;
		}
		setbuf(debugfile,(char *)0);
		exp_close_on_exec(fileno(debugfile));
		fopened = TRUE;
		argc--;argv++;
	}

	if (argc != 1) goto usage;

	/* if no -f given, close file */
	if (fopened == FALSE && debugfile) {
		fclose(debugfile);
		debugfile = 0;
		Tcl_DStringFree(&dstring);
	}

	exp_is_debugging = atoi(*argv);
	return(TCL_OK);
 usage:
	exp_error(interp,"usage: [-f file] expr");
 error:
	Tcl_DStringFree(&dstring);
	return TCL_ERROR;
}

char *exp_onexit_action = 0;

/*ARGSUSED*/
static int
Exp_ExitCmd(clientData, interp, argc, argv)







|
>













>
>

>














|
|
>
>
>













|

|

|

|
|
|


|
>
>
|
|
>


>
|
<
<
<
|
>
|
<

<
<
<
<
<
<
<
<
<
|
<

<
<
|
<
|
>
|
|
>
>
>
>
>
>



>
>
|




|

|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|



|
|










|












<
<
<


<











<
|
<
<
<
<
<









|


|
|

>
|
|
|
|






|
|
|
|
|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
|
>

<
<
<
|
|
<
<
<
|
<
<
>
>
|
<
|
|
>
|
|
>
|
|
>
|
|
|
|
<
<
<
|
|
|
|
|
|
>
>
>
>
|
|
>
>
>
|
<
>
>
|
|
>
|
|
|
|
|
|
|
|
|
|
|
<
<
<
|
|
|

|
|
|
|
|
>
|
|

|
>
|
|
|
|
|
|
|
<
|
|

<
<
|
<
|
|
|
>
|






|
|
|
>
>
|
|
|
<
<
<
|
|

|
|

|
|
|

<
<
<
|
|
|
|
|
<
<
<
<
<
|

|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|

|
|





|
|
|
|

<
<
<
|
<
|
<
<
<
<
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|
|
|
|
<
|
|
|
|
<
|
|
|
|
|
|
>
|
|
|
>
>
>
>
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
|
|
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
<
|
|
<
<
|
<
|
<
<
<
<
|
|
>
<
<
|
|
|
<
<
|
<
|
<
|
|
<
<
<
<
>
|
<
<
<
|
<
<
<
|
<
<
>
|
<
<
<
<
>

<
<
<
|
|
<
<
<
|
<
<
<
|
<
<
<
|

|
<
<
<
<
<
<
<
<
<
<
|
<
<
|










|

|
|
|
|
<
|
|
|

|

|











|
|

|

|
|
|
|

|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|


>









<
<
|
|
<
<
<
>
|
<
|
>
>
|
|
<
|
>
|
|
|

|
|
>
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
|
|
|

|
|
|
|
|
<
<
|
|
<
|

|
<
<
|







1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680



1681
1682
1683

1684









1685

1686


1687

1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762



1763
1764

1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775

1776





1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825



1826
1827



1828


1829
1830
1831

1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844



1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860

1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876



1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898

1899
1900
1901


1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921



1922
1923
1924
1925
1926
1927
1928
1929
1930
1931



1932
1933
1934
1935
1936





1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986



1987

1988




1989
1990
1991
1992




















1993
1994
1995
1996
1997
1998

1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038




























2039
2040
2041
2042



2043








2044


2045

2046
2047


2048

2049




2050
2051
2052


2053
2054
2055


2056

2057

2058
2059




2060
2061



2062



2063


2064
2065




2066
2067



2068
2069



2070



2071



2072
2073
2074










2075


2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092

2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161


2162
2163



2164
2165

2166
2167
2168
2169
2170

2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183












2184



2185





2186


2187


2188
2189
2190
2191
2192
2193
2194
2195
2196


2197
2198

2199
2200
2201


2202
2203
2204
2205
2206
2207
2208
2209
	}

	i->next = exp_i_pool;
	exp_i_pool = i;
}

/* generate a descriptor for a "-i" flag */
/* can only fail on bad direct descriptors */
/* indirect descriptors always succeed */
struct exp_i *
exp_new_i_complex(interp,arg,duration,updateproc)
Tcl_Interp *interp;
char *arg;		/* spawn id list or a variable containing a list */
int duration;		/* if we have to copy the args */
			/* should only need do this in expect_before/after */
Tcl_VarTraceProc *updateproc;	/* proc to invoke if indirect is written */
{
	struct exp_i *i;
	char **stringp;

	i = exp_new_i();

	i->direct = (isExpChannelName(arg)?EXP_DIRECT:EXP_INDIRECT);
#if OBSOLETE
	i->direct = (isdigit(arg[0]) || (arg[0] == '-'))?EXP_DIRECT:EXP_INDIRECT;
#endif
	if (i->direct == EXP_DIRECT) {
		stringp = &i->value;
	} else {
		stringp = &i->variable;
	}

	i->duration = duration;
	if (duration == EXP_PERMANENT) {
		*stringp = ckalloc(strlen(arg)+1);
		strcpy(*stringp,arg);
	} else {
		*stringp = arg;
	}

	i->state_list = 0;
	if (TCL_ERROR == exp_i_update(interp,i)) {
	  exp_free_i(interp,i,(Tcl_VarTraceProc *)0);
	  return 0;
	}

	/* if indirect, ask Tcl to tell us when variable is modified */

	if (i->direct == EXP_INDIRECT) {
		Tcl_TraceVar(interp, i->variable,
			TCL_GLOBAL_ONLY|TCL_TRACE_WRITES,
			updateproc, (ClientData) i);
	}

	return i;
}

void
exp_i_add_state(i,esPtr)
struct exp_i *i;
ExpState *esPtr;
{
	struct exp_state_list *new_state;

	new_state = exp_new_state(esPtr);
	new_state->next = i->state_list;
	i->state_list = new_state;
}

/* this routine assumes i->esPtr is meaningful */
/* returns TCL_ERROR only on direct */
/* indirects always succeed */
static int
exp_i_parse_states(interp,i) /* INTL */
Tcl_Interp *interp;
struct exp_i *i;
{
    struct ExpState *esPtr;
    char *p = i->value;



    int argc;
    char **argv;
    int j;











    if (Tcl_SplitList(NULL, p, &argc, &argv) != TCL_OK) goto error;




    for (j = 0; j < argc; j++) {

        esPtr = expStateFromChannelName(interp,argv[j],1,0,0,"");
	if (!esPtr) goto error;
	exp_i_add_state(i,esPtr);
    }
    ckfree((char*)argv);
    return TCL_OK;
error:
    expDiagLogU("exp_i_parse_states: ");
    expDiagLogU(Tcl_GetStringResult(interp));
    return TCL_ERROR;
}
	
/* updates a single exp_i struct */
/* return TCL_ERROR only on direct variables */
/* indirect variables always succeed */
int
exp_i_update(interp,i)
Tcl_Interp *interp;
struct exp_i *i;
{
  char *p;	/* string representation of list of spawn ids */

  if (i->direct == EXP_INDIRECT) {
    p = Tcl_GetVar(interp,i->variable,TCL_GLOBAL_ONLY);
    if (!p) {
      p = "";
      /* *really* big variable names could blow up expDiagLog! */
      expDiagLog("warning: indirect variable %s undefined",i->variable);
    }
    
    if (i->value) {
      if (streq(p,i->value)) return TCL_OK;
      
      /* replace new value with old */
      ckfree(i->value);
    }
    i->value = ckalloc(strlen(p)+1);
    strcpy(i->value,p);

    exp_free_state(i->state_list);
    i->state_list = 0;
  } else {
    /* no free, because this should only be called on */
    /* "direct" i's once */
    i->state_list = 0;
  }
  return exp_i_parse_states(interp, i);
}

struct exp_i *
exp_new_i_simple(esPtr,duration)
ExpState *esPtr;
int duration;		/* if we have to copy the args */
			/* should only need do this in expect_before/after */
{
	struct exp_i *i;

	i = exp_new_i();

	i->direct = EXP_DIRECT;
	i->duration = duration;

	exp_i_add_state(i,esPtr);

	return i;
}

/*ARGSUSED*/
static int
Exp_SendLogCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{



	argv++;
	argc--;

	if (argc) {
		if (streq(*argv,"--")) {
			argc--; argv++;
		}
	}

	if (argc != 1) {
		exp_error(interp,"usage: send [args] string");
		return TCL_ERROR;
	}


	expLogDiagU(*argv);





	return(TCL_OK);
}


/* I've rewritten this to be unbuffered.  I did this so you could shove */
/* large files through "send".  If you are concerned about efficiency */
/* you should quote all your send args to make them one single argument. */
/*ARGSUSED*/
static int
Exp_SendObjCmd(clientData, interp, objc, objv) /* INTL */
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ExpState *esPtr = 0;
    int rc; 	/* final result of this procedure */
    struct human_arg human_args;
    struct slow_arg slow_args;
#define SEND_STYLE_STRING_MASK	0x07	/* mask to detect a real string arg */
#define SEND_STYLE_PLAIN	0x01
#define SEND_STYLE_HUMAN	0x02
#define SEND_STYLE_SLOW		0x04
#define SEND_STYLE_ZERO		0x10
#define SEND_STYLE_BREAK	0x20
    int send_style = SEND_STYLE_PLAIN;
    int want_cooked = TRUE;
    char *string;		/* string to send */
    int len = -1;		/* length of string to send */
    int zeros;		/* count of how many ascii zeros to send */

    char *chanName = 0;
    struct exp_state_list *state_list;
    struct exp_i *i;
    int j;

    static char *options[] = {
	"-i", "-h", "-s", "-null", "-0", "-raw", "-break", "--", (char *)0
    };
    enum options {
	SEND_SPAWNID, SEND_HUMAN, SEND_SLOW, SEND_NULL, SEND_ZERO,
	SEND_RAW, SEND_BREAK, SEND_LAST
    };

    for (j = 1; j < objc; j++) {
	char *name;
	int index;




	name = Tcl_GetString(objv[j]);
	if (name[0] != '-') {



	    break;


	}
	if (Tcl_GetIndexFromObj(interp, objv[j], options, "flag", 0,
		&index) != TCL_OK) {

	    return TCL_ERROR;
	}
	switch ((enum options) index) {
	    case SEND_SPAWNID:
		j++;
		chanName = Tcl_GetString(objv[j]);
		break;

	    case SEND_LAST:
		j++;
		goto getString;

	    case SEND_HUMAN:



		if (-1 == get_human_args(interp,&human_args))
		    return(TCL_ERROR);
		send_style = SEND_STYLE_HUMAN;
		break;

	    case SEND_SLOW:
		if (-1 == get_slow_args(interp,&slow_args))
		    return(TCL_ERROR);
		send_style = SEND_STYLE_SLOW;
		break;

	    case SEND_NULL:
	    case SEND_ZERO:
		j++;
		if (j >= objc) {
		    zeros = 1;

		} else if (Tcl_GetIntFromObj(interp, objv[j], &zeros)
			!= TCL_OK) {
		    return TCL_ERROR;
		}
		if (zeros < 1) return TCL_OK;
		send_style = SEND_STYLE_ZERO;
		string = "<zero(s)>";
		break;

	    case SEND_RAW:
		want_cooked = FALSE;
		break;

	    case SEND_BREAK:
		send_style = SEND_STYLE_BREAK;
		string = "<break>";



		break;
	}
    }

    if (send_style & SEND_STYLE_STRING_MASK) {
	if (j != objc-1) {
	    exp_error(interp,"usage: send [args] string");
	    return TCL_ERROR;
	}
getString:
	string = Tcl_GetStringFromObj(objv[j], &len);
    } else {
	len = strlen(string);
    }

    if (clientData == &sendCD_user) esPtr = tsdPtr->stdinout;
    else if (clientData == &sendCD_error) esPtr = tsdPtr->stderrX;
    else if (clientData == &sendCD_tty) esPtr = tsdPtr->devtty;
    else if (!chanName) {
	/* we want to check if it is open */
	/* but since stdin could be closed, we have to first */
	/* get the fd and then convert it from 0 to 1 if necessary */

	if (!(esPtr = expStateCurrent(interp,0,0,0))) return(TCL_ERROR);
    }



    if (esPtr) {

	i = exp_new_i_simple(esPtr,EXP_TEMPORARY);
    } else {
	i = exp_new_i_complex(interp,chanName,FALSE,(Tcl_VarTraceProc *)0);
	if (!i) return TCL_ERROR;
    }

#define send_to_stderr	(clientData == &sendCD_error)
#define send_to_proc	(clientData == &sendCD_proc)
#define send_to_user	((clientData == &sendCD_user) || \
			 (clientData == &sendCD_tty))

    if (send_to_proc) {
	want_cooked = FALSE;
	expDiagLogU("send: sending \"");
	expDiagLogU(expPrintify(string));
	expDiagLogU("\" to {");
	/* if closing brace doesn't appear, that's because an error */
	/* was encountered before we could send it */
    } else {



	expLogDiagU(string);
    }

    for (state_list=i->state_list;state_list;state_list=state_list->next) {
	esPtr = state_list->esPtr;

	if (send_to_proc) {
	    expDiagLog(" %s ",esPtr->name);
	}




	/* check validity of each - i.e., are they open */
	if (0 == expStateCheck(interp,esPtr,1,0,"send")) {
	    rc = TCL_ERROR;
	    goto finish;
	}





	if (want_cooked) string = exp_cook(string,&len);

	switch (send_style) {
	    case SEND_STYLE_PLAIN:
		rc = exact_write(esPtr,string,len);
		break;
	    case SEND_STYLE_SLOW:
		rc = slow_write(interp,esPtr,string,len,&slow_args);
		break;
	    case SEND_STYLE_HUMAN:
		rc = human_write(interp,esPtr,string,&human_args);
		break;
	    case SEND_STYLE_ZERO:
		for (;zeros>0;zeros--) {
		    rc = Tcl_WriteChars(esPtr->channel,
			    NULL_STRING, NULL_LENGTH);
		}
		/* catching error on last write is sufficient */
		rc = ((rc==1) ? 0 : -1);   /* normal is 1 not 0 */
		break;
	    case SEND_STYLE_BREAK:
		exp_tty_break(interp,esPtr->fdout);
		rc = 0;
		break;
	}

	if (rc != 0) {
	    if (rc == -1) {
		exp_error(interp,"write(spawn_id=%d): %s",esPtr->fdout,Tcl_PosixError(interp));
		rc = TCL_ERROR;
	    }
	    goto finish;
	}
    }
    if (send_to_proc) expDiagLogU("}\r\n");

    rc = TCL_OK;
 finish:
    exp_free_i(interp,i,(Tcl_VarTraceProc *)0);
    return rc;
}

/*ARGSUSED*/
static int
Exp_LogFileCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    char **argv;
{



    static char resultbuf[1000];

    char *chanName = 0;




    int leaveOpen = FALSE;
    int logAll = FALSE;
    int append = TRUE;
    char *filename = 0;





















    argv++;
    argc--;
    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-open")) {
	    if (!argv[1]) goto usage_error;

	    chanName = argv[1];
	    argc--; argv++;
	} else if (streq(*argv,"-leaveopen")) {
	    if (!argv[1]) goto usage_error;

	    chanName = argv[1];
	    leaveOpen = TRUE;
	    argc--; argv++;
	} else if (streq(*argv,"-a")) {
	    logAll = TRUE;
	} else if (streq(*argv,"-info")) {
	    resultbuf[0] = '\0';
	    if (expLogChannelGet()) {
		if (expLogAllGet()) strcat(resultbuf,"-a ");
		if (!expLogAppendGet()) strcat(resultbuf,"-noappend ");
		if (expLogFilenameGet()) {
		    strcat(resultbuf,expLogFilenameGet());
		} else {
		    if (expLogLeaveOpenGet()) {
			strcat(resultbuf,"-leaveopen ");
		    }
		    strcat(resultbuf,Tcl_GetChannelName(expLogChannelGet()));
		}
		Tcl_SetResult(interp,resultbuf,TCL_STATIC);
	    }
	    return TCL_OK;
	} else if (streq(*argv,"-noappend")) {
	    append = FALSE;
	} else break;
    }
    
    if (argc == 1) {
	filename = argv[0];
    } else if (argc > 1) {
	/* too many arguments */
	goto usage_error;
    } 
    
    if (chanName && filename) {
	goto usage_error;
    }





























    /* check if user merely wants to change logAll (-a) */
    if (expLogChannelGet() && (chanName || filename)) {
	if (filename && (0 == strcmp(filename,expLogFilenameGet()))) {



	    expLogAllSet(logAll);








	    return TCL_OK;


	} else if (chanName && (0 == strcmp(filename,Tcl_GetChannelName(expLogChannelGet())))) {

	    expLogAllSet(logAll);
	    return TCL_OK;


	} else {

	    exp_error(interp,"cannot start logging without first stopping logging");




	    return TCL_ERROR;
	}
    }



    if (filename) {
	if (TCL_ERROR == expLogChannelOpen(interp,filename,append)) {


	    return TCL_ERROR;

	}

    } else if (chanName) {
	if (TCL_ERROR == expLogChannelSet(interp,chanName)) {




	    return TCL_ERROR;
	}



    } else {



	expLogChannelClose(interp);


	if (logAll) {
	    exp_error(interp,"cannot use -a without a file or channel");




	    return TCL_ERROR;
	}



    }
    expLogAllSet(logAll);



    expLogLeaveOpenSet(leaveOpen);







    return TCL_OK;

 usage_error:










    exp_error(interp,"usage: log_file [-info] [-noappend] [[-a] file] [-[leave]open [open ...]]");


    return TCL_ERROR;
}

/*ARGSUSED*/
static int
Exp_LogUserCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    int old_loguser = expLogUserGet();

    if (argc == 0 || (argc == 2 && streq(argv[1],"-info"))) {
	/* do nothing */
    } else if (argc == 2) {
	expLogUserSet(atoi(argv[1]));

    } else {
	exp_error(interp,"usage: [-info|1|0]");
    }

    sprintf(interp->result,"%d",old_loguser);

    return(TCL_OK);
}

#ifdef TCL_DEBUGGER
/*ARGSUSED*/
static int
Exp_DebugCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    int now = FALSE;	/* soon if FALSE, now if TRUE */
    int exp_tcl_debugger_was_available = exp_tcl_debugger_available;

    if (argc > 3) goto usage;

    if (argc == 1) {
	sprintf(interp->result,"%d",exp_tcl_debugger_available);
	return TCL_OK;
    }

    argv++;

    while (*argv) {
	if (streq(*argv,"-now")) {
	    now = TRUE;
	    argv++;
	}
	else break;
    }

    if (!*argv) {
	if (now) {
	    Dbg_On(interp,1);
	    exp_tcl_debugger_available = 1;
	} else {
	    goto usage;
	}
    } else if (streq(*argv,"0")) {
	Dbg_Off(interp);
	exp_tcl_debugger_available = 0;
    } else {
	Dbg_On(interp,now);
	exp_tcl_debugger_available = 1;
    }
    sprintf(interp->result,"%d",exp_tcl_debugger_was_available);
    return(TCL_OK);
 usage:
    exp_error(interp,"usage: [[-now] 1|0]");
    return TCL_ERROR;
}
#endif


/*ARGSUSED*/
static int
Exp_ExpInternalCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{


    int newChannel = FALSE;
    Tcl_Channel oldChannel;



    static char resultbuf[1000];


    if ((argc > 1) && streq(argv[1],"-info")) {
	resultbuf[0] = '\0';
	oldChannel = expDiagChannelGet();
	if (oldChannel) {
	    sprintf(resultbuf,"-f %s ",expDiagFilename());

	}
	strcat(resultbuf,expDiagToStderrGet()?"1":"0");
	Tcl_SetResult(interp,resultbuf,TCL_STATIC);
	return TCL_OK;
    }

    argv++;
    argc--;

    while (argc) {
	if (!streq(*argv,"-f")) break;
	argc--;argv++;
	if (argc < 1) goto usage;












	expDiagChannelClose(interp);



	if (TCL_OK != expDiagChannelOpen(interp,argv[0])) {





	    return TCL_ERROR;


	}


	newChannel = TRUE;
	argc--;argv++;
    }

    if (argc != 1) goto usage;
    
    /* if no -f given, close file */
    if (!newChannel) {
	expDiagChannelClose(interp);


    }
    expDiagToStderrSet(atoi(*argv));

    return(TCL_OK);
 usage:
    exp_error(interp,"usage: [-f file] 0|1");


    return TCL_ERROR;
}

char *exp_onexit_action = 0;

/*ARGSUSED*/
static int
Exp_ExitCmd(clientData, interp, argc, argv)
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636

2637


2638



2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685


2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733

2734
2735
2736
2737
2738
2739
2740

	if (*argv) {
		if (Tcl_GetInt(interp, *argv, &value) != TCL_OK) {
			return TCL_ERROR;
		}
	}

	exp_exit(interp,value);
	/*NOTREACHED*/
}

/* so cmd table later is more intuitive */
#define Exp_CloseObjCmd Exp_CloseCmd

/*ARGSUSED*/
static int
Exp_CloseCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
#if TCL_MAJOR_VERSION < 8
char **argv;
#else
Tcl_Obj *CONST argv[];	/* Argument objects. */
#endif
{
	int onexec_flag = FALSE;	/* true if -onexec seen */
	int close_onexec;
	int slave_flag = FALSE;
	int m = -1;


	int argc_orig = argc;
#if TCL_MAJOR_VERSION < 8
	char **argv_orig = argv;
#else
	Tcl_Obj *CONST *argv_orig = argv;
#endif




	argc--; argv++;




#if TCL_MAJOR_VERSION < 8
#define STARARGV *argv
#else
#define STARARGV Tcl_GetStringFromObj(*argv,(int *)0)
#endif

	for (;argc>0;argc--,argv++) {
		if (streq("-i",STARARGV)) {
			argc--; argv++;
			if (argc == 0) {
				exp_error(interp,"usage: -i spawn_id");
				return(TCL_ERROR);
			}
			m = atoi(STARARGV);
		} else if (streq(STARARGV,"-slave")) {
			slave_flag = TRUE;
		} else if (streq(STARARGV,"-onexec")) {
			argc--; argv++;
			if (argc == 0) {
				exp_error(interp,"usage: -onexec 0|1");
				return(TCL_ERROR);
			}
			onexec_flag = TRUE;
			close_onexec = atoi(STARARGV);
		} else break;
	}

	if (argc) {
		/* doesn't look like our format, it must be a Tcl-style file */
		/* handle.  Lucky that formats are easily distinguishable. */
		/* Historical note: we used "close"  long before there was a */
		/* Tcl builtin by the same name. */

		Tcl_CmdInfo info;
		Tcl_ResetResult(interp);
		if (0 == Tcl_GetCommandInfo(interp,"close",&info)) {
			info.clientData = 0;
		}
#if TCL_MAJOR_VERSION < 8
		return(Tcl_CloseCmd(info.clientData,interp,argc_orig,argv_orig));
#else
		return(Tcl_CloseObjCmd(info.clientData,interp,argc_orig,argv_orig));
#endif
	}

	if (m == -1) {


		if (exp_update_master(interp,&m,1,0) == 0) return(TCL_ERROR);
	}

	if (slave_flag) {
		struct exp_f *f = exp_fd2f(interp,m,1,0,"-slave");
		if (!f) return TCL_ERROR;

		if (f->slave_fd) {
			close(f->slave_fd);
			f->slave_fd = EXP_NOFD;

			exp_slave_control(m,1);

			return TCL_OK;
		} else {
			exp_error(interp,"no such slave");
			return TCL_ERROR;
		}
	}

	if (onexec_flag) {
		/* heck, don't even bother to check if fd is open or a real */
		/* spawn id, nothing else depends on it */
		fcntl(m,F_SETFD,close_onexec);
		return TCL_OK;
	}

	return(exp_close(interp,m));
}

/*ARGSUSED*/
static void
tcl_tracer(clientData,interp,level,command,cmdProc,cmdClientData,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int level;
char *command;
int (*cmdProc)();
ClientData cmdClientData;
int argc;
char *argv[];
{
	int i;

	/* come out on stderr, by using errorlog */
	errorlog("%2d",level);
	for (i = 0;i<level;i++) exp_nferrorlog("  ",0/*ignored - satisfy lint*/);
	errorlog("%s\r\n",command);

}

/*ARGSUSED*/
static int
Exp_StraceCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;







|



<
<
<


|


|
<
<
<
|
<

|
|
|
|
>

|
<
<
<
|
|
>

>
>
|
>
>
>
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
<
<
<
|
<
|

|
>
>
|
|

|
<
<
|
<
|
|

|

|
|
|
|
|
|

|
|
|
|
|
|

|
















|
|
|
|
>







2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248



2249
2250
2251
2252
2253
2254



2255

2256
2257
2258
2259
2260
2261
2262
2263



2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274





2275








2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299



2300

2301
2302
2303
2304
2305
2306
2307
2308
2309


2310

2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358

	if (*argv) {
		if (Tcl_GetInt(interp, *argv, &value) != TCL_OK) {
			return TCL_ERROR;
		}
	}

	Tcl_Exit(value);
	/*NOTREACHED*/
}




/*ARGSUSED*/
static int
Exp_CloseObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;



Tcl_Obj *CONST objv[];	/* Argument objects. */

{
    int onexec_flag = FALSE;	/* true if -onexec seen */
    int close_onexec;
    int slave_flag = FALSE;
    ExpState *esPtr = 0;
    char *chanName = 0;

    int objc_orig = objc;



    Tcl_Obj *CONST *objv_orig = objv;

    objc--; objv++;

    for (;objc>0;objc--,objv++) {
	if (streq("-i",Tcl_GetString(*objv))) {
	    objc--; objv++;
	    if (objc == 0) {
		exp_error(interp,"usage: -i spawn_id");
		return(TCL_ERROR);
	    }





	    chanName = Tcl_GetString(*objv);








	} else if (streq(Tcl_GetString(*objv),"-slave")) {
	    slave_flag = TRUE;
	} else if (streq(Tcl_GetString(*objv),"-onexec")) {
	    objc--; objv++;
	    if (objc == 0) {
		exp_error(interp,"usage: -onexec 0|1");
		return(TCL_ERROR);
	    }
	    onexec_flag = TRUE;
	    close_onexec = atoi(Tcl_GetString(*objv));
	} else break;
    }

    if (objc) {
	/* doesn't look like our format, it must be a Tcl-style file */
	/* handle.  Lucky that formats are easily distinguishable. */
	/* Historical note: we used "close"  long before there was a */
	/* Tcl builtin by the same name. */

	Tcl_CmdInfo info;
	Tcl_ResetResult(interp);
	if (0 == Tcl_GetCommandInfo(interp,"close",&info)) {
	    info.clientData = 0;
	}



	return(Tcl_CloseObjCmd(info.clientData,interp,objc_orig,objv_orig));

    }

    if (chanName) {
	if (!(esPtr = expStateFromChannelName(interp,chanName,1,0,0,"close"))) return TCL_ERROR;
    } else {
	if (!(esPtr = expStateCurrent(interp,1,0,0))) return TCL_ERROR;
    }

    if (slave_flag) {


	if (esPtr->fd_slave != EXP_NOFD) {

	    close(esPtr->fd_slave);
	    esPtr->fd_slave = EXP_NOFD;

	    exp_slave_control(esPtr->fdin,1);

	    return TCL_OK;
	} else {
	    exp_error(interp,"no such slave");
	    return TCL_ERROR;
	}
    }

    if (onexec_flag) {
	/* heck, don't even bother to check if fd is open or a real */
	/* spawn id, nothing else depends on it */
	fcntl(esPtr->fdin,F_SETFD,close_onexec);
	return TCL_OK;
    }

    return(exp_close(interp,esPtr));
}

/*ARGSUSED*/
static void
tcl_tracer(clientData,interp,level,command,cmdProc,cmdClientData,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int level;
char *command;
int (*cmdProc)();
ClientData cmdClientData;
int argc;
char *argv[];
{
	int i;

	/* come out on stderr, by using expErrorLog */
	expErrorLog("%2d",level);
	for (i = 0;i<level;i++) expErrorLogU("  ");
	expErrorLogU(command);
	expErrorLogU("\r\n");
}

/*ARGSUSED*/
static int
Exp_StraceCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899

2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975


2976
2977
2978
2979
2980
2981

2982
2983
2984
2985


2986
2987
2988
2989
2990



2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007



3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020

3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065

3066
3067
3068

3069
3070
3071
3072
3073
3074
3075
3076
static int
Exp_WaitCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int master_supplied = FALSE;
	int m;			/* master waited for */
	struct exp_f *f;	/* ditto */
	struct forked_proc *fp = 0;	/* handle to a pure forked proc */

	struct exp_f ftmp;	/* temporary memory for either f or fp */


	int nowait = FALSE;
	int result = 0;		/* 0 means child was successfully waited on */
				/* -1 means an error occurred */
				/* -2 means no eligible children to wait on */
#define NO_CHILD -2

	argv++;
	argc--;
	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-i")) {
			argc--; argv++;
			if (argc==0) {
				exp_error(interp,"usage: -i spawn_id");
				return(TCL_ERROR);
			}
			master_supplied = TRUE;
			m = atoi(*argv);
		} else if (streq(*argv,"-nowait")) {
			nowait = TRUE;
		}
	}

	if (!master_supplied) {
		if (0 == exp_update_master(interp,&m,0,0))
			return TCL_ERROR;
	}

	if (m != EXP_SPAWN_ID_ANY) {
		if (0 == exp_fd2f(interp,m,0,0,"wait")) {
			return TCL_ERROR;
		}

		f = exp_fs + m;

		/* check if waited on already */
		/* things opened by "open" or set with -nowait */
		/* are marked sys_waited already */
		if (!f->sys_waited) {
			if (nowait) {
				/* should probably generate an error */
				/* if SIGCHLD is trapped. */

				/* pass to Tcl, so it can do wait */
				/* in background */
#if TCL_MAJOR_VERSION < 8
				Tcl_DetachPids(1,&f->pid);
#else
				Tcl_DetachPids(1,(Tcl_Pid *)&f->pid);
#endif
				exp_wait_zero(&f->wait);
			} else {
				while (1) {
					if (Tcl_AsyncReady()) {
						int rc = Tcl_AsyncInvoke(interp,TCL_OK);
						if (rc != TCL_OK) return(rc);
					}

					result = waitpid(f->pid,&f->wait,0);
					if (result == f->pid) break;
					if (result == -1) {
						if (errno == EINTR) continue;
						else break;
					}
				}
			}
		}

		/*
		 * Now have Tcl reap anything we just detached. 
		 * This also allows procs user has created with "exec &"
		 * and and associated with an "exec &" process to be reaped.
		 */

		Tcl_ReapDetachedProcs();
		exp_rearm_sigchld(interp); /* new */


	} else {
		/* wait for any of our own spawned processes */
		/* we call waitpid rather than wait to avoid running into */
		/* someone else's processes.  Yes, according to Ousterhout */
		/* this is the best way to do it. */


		for (m=0;m<=exp_fd_max;m++) {
			f = exp_fs + m;
			if (!f->valid) continue;
			if (f->pid == exp_getpid) continue; /* skip ourself */


			if (f->user_waited) continue;	/* one wait only! */
			if (f->sys_waited) break;
		   restart:
			result = waitpid(f->pid,&f->wait,WNOHANG);
			if (result == f->pid) break;



			if (result == 0) continue;	/* busy, try next */
			if (result == -1) {
				if (errno == EINTR) goto restart;
				else break;
			}
		}

		/* if it's not a spawned process, maybe its a forked process */
		for (fp=forked_proc_base;fp;fp=fp->next) {
			if (fp->link_status == not_in_use) continue;
		restart2:
			result = waitpid(fp->pid,&fp->wait_status,WNOHANG);
			if (result == fp->pid) {
				m = -1; /* DOCUMENT THIS! */
				break;
			}
			if (result == 0) continue;	/* busy, try next */



			if (result == -1) {
				if (errno == EINTR) goto restart2;
				else break;
			}
		}

		if (m > exp_fd_max) {
			result = NO_CHILD;	/* no children */
			Tcl_ReapDetachedProcs();
		}
		exp_rearm_sigchld(interp);
	}


	/*  sigh, wedge forked_proc into an exp_f structure so we don't
	 *  have to rewrite remaining code (too much)
	 */
	if (fp) {
		f = &ftmp;
		f->pid = fp->pid;
		f->wait = fp->wait_status;
	}

	/* non-portable assumption that pid_t can be printed with %d */

	if (result == -1) {
		sprintf(interp->result,"%d %d -1 %d POSIX %s %s",
			f->pid,m,errno,Tcl_ErrnoId(),Tcl_ErrnoMsg(errno));
		result = TCL_OK;
	} else if (result == NO_CHILD) {
		interp->result = "no children";
		return TCL_ERROR;
	} else {
		sprintf(interp->result,"%d %d 0 %d",
					f->pid,m,WEXITSTATUS(f->wait));
		if (WIFSIGNALED(f->wait)) {
			Tcl_AppendElement(interp,"CHILDKILLED");
			Tcl_AppendElement(interp,Tcl_SignalId((int)(WTERMSIG(f->wait))));
			Tcl_AppendElement(interp,Tcl_SignalMsg((int) (WTERMSIG(f->wait))));
		} else if (WIFSTOPPED(f->wait)) {
			Tcl_AppendElement(interp,"CHILDSUSP");
			Tcl_AppendElement(interp,Tcl_SignalId((int) (WSTOPSIG(f->wait))));
			Tcl_AppendElement(interp,Tcl_SignalMsg((int) (WSTOPSIG(f->wait))));
		}
	}
			
	if (fp) {
		fp->link_status = not_in_use;
		return ((result == -1)?TCL_ERROR:TCL_OK);		
	}

	f->sys_waited = TRUE;
	f->user_waited = TRUE;

	/* if user has already called close, make sure fd really is closed */
	/* and forget about this entry entirely */
	if (f->user_closed) {
		if (!f->sys_closed) {
			sys_close(m,f);

		}
		f->valid = FALSE;
	}

	return ((result == -1)?TCL_ERROR:TCL_OK);
}

/*ARGSUSED*/
static int
Exp_ForkCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;







|
<
|
|
<
|
>

|
|




|
|
|
|
|
|
|
|
|
<
|
|
|
|
|

|
<
|
|
|
<
<
|
|

<
|
|
|
|
|
|
|
|

|
|
<
<
<
|
<
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
>
>
|
|
|
|
|

>
|
|
|
<
>
>
|
<
|
|
|
>
>
>
|
|
|
|
|
|

<
|
<
<
<
<
|
<
<
<
>
>
>
|
<
|
<
<
<
<
|
|
|
|

|
>
|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|
|

|
<
|
|
<
>
|
<
|
>
|







2505
2506
2507
2508
2509
2510
2511
2512

2513
2514

2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532

2533
2534
2535
2536
2537
2538
2539

2540
2541
2542


2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556



2557

2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595

2596
2597
2598

2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611

2612




2613



2614
2615
2616
2617

2618




2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666

2667
2668

2669
2670

2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
static int
Exp_WaitCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    char *chanName = 0;

    struct ExpState *esPtr;
    struct forked_proc *fp = 0;	/* handle to a pure forked proc */

    struct ExpState esTmp;	/* temporary memory for either f or fp */
    char spawn_id[20];

    int nowait = FALSE;
    int result = 0;		/* 0 means child was successfully waited on */
				/* -1 means an error occurred */
				/* -2 means no eligible children to wait on */
#define NO_CHILD -2

    argv++;
    argc--;
    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-i")) {
	    argc--; argv++;
	    if (argc==0) {
		exp_error(interp,"usage: -i spawn_id");
		return(TCL_ERROR);
	    }

	    chanName = *argv;
	} else if (streq(*argv,"-nowait")) {
	    nowait = TRUE;
	}
    }

    if (!chanName) {

	if (!(esPtr = expStateCurrent(interp,0,0,1))) return TCL_ERROR;
    } else {
	if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,1,"wait")))


	    return TCL_ERROR;
    }


    if (!expStateAnyIs(esPtr)) {
	/* check if waited on already */
	/* things opened by "open" or set with -nowait */
	/* are marked sys_waited already */
	if (!esPtr->sys_waited) {
	    if (nowait) {
		/* should probably generate an error */
		/* if SIGCHLD is trapped. */

		/* pass to Tcl, so it can do wait */
		/* in background */



		Tcl_DetachPids(1,(Tcl_Pid *)&esPtr->pid);

		exp_wait_zero(&esPtr->wait);
	    } else {
		while (1) {
		    if (Tcl_AsyncReady()) {
			int rc = Tcl_AsyncInvoke(interp,TCL_OK);
			if (rc != TCL_OK) return(rc);
		    }

		    result = waitpid(esPtr->pid,&esPtr->wait,0);
		    if (result == esPtr->pid) break;
		    if (result == -1) {
			if (errno == EINTR) continue;
			else break;
		    }
		}
	    }
	}

	/*
	 * Now have Tcl reap anything we just detached. 
	 * This also allows procs user has created with "exec &"
	 * and and associated with an "exec &" process to be reaped.
	 */
	
	Tcl_ReapDetachedProcs();
	exp_rearm_sigchld(interp); /* new */

	strcpy(spawn_id,esPtr->name);
    } else {
	/* wait for any of our own spawned processes */
	/* we call waitpid rather than wait to avoid running into */
	/* someone else's processes.  Yes, according to Ousterhout */
	/* this is the best way to do it. */

	int waited_on_forked_process = 0;

	esPtr = expWaitOnAny();
	if (!esPtr) {

	    /* if it's not a spawned process, maybe its a forked process */
	    for (fp=forked_proc_base;fp;fp=fp->next) {
		if (fp->link_status == not_in_use) continue;

	restart:
		result = waitpid(fp->pid,&fp->wait_status,WNOHANG);
		if (result == fp->pid) {
		    waited_on_forked_process = 1;
		    break;
		}
		if (result == 0) continue;	/* busy, try next */
		if (result == -1) {
		    if (errno == EINTR) goto restart;
		    else break;
		}
	    }


	    if (waited_on_forked_process) {




		/*



		 * The literal spawn id in the return value from wait appears
		 * as a -1 to indicate a forked process was waited on.  
		 */
		strcpy(spawn_id,"-1");

	    } else {




		result = NO_CHILD;	/* no children */
		Tcl_ReapDetachedProcs();
	    }
	    exp_rearm_sigchld(interp);
	}
    }

    /*  sigh, wedge forked_proc into an ExpState structure so we don't
     *  have to rewrite remaining code (too much)
     */
    if (fp) {
	esPtr = &esTmp;
	esPtr->pid = fp->pid;
	esPtr->wait = fp->wait_status;
    }

    /* non-portable assumption that pid_t can be printed with %d */

    if (result == -1) {
	sprintf(interp->result,"%d %s -1 %d POSIX %s %s",
		esPtr->pid,spawn_id,errno,Tcl_ErrnoId(),Tcl_ErrnoMsg(errno));
	result = TCL_OK;
    } else if (result == NO_CHILD) {
	exp_error(interp,"no children");
	return TCL_ERROR;
    } else {
	sprintf(interp->result,"%d %s 0 %d",
		esPtr->pid,spawn_id,WEXITSTATUS(esPtr->wait));
	if (WIFSIGNALED(esPtr->wait)) {
	    Tcl_AppendElement(interp,"CHILDKILLED");
	    Tcl_AppendElement(interp,Tcl_SignalId((int)(WTERMSIG(esPtr->wait))));
	    Tcl_AppendElement(interp,Tcl_SignalMsg((int) (WTERMSIG(esPtr->wait))));
	} else if (WIFSTOPPED(esPtr->wait)) {
	    Tcl_AppendElement(interp,"CHILDSUSP");
	    Tcl_AppendElement(interp,Tcl_SignalId((int) (WSTOPSIG(esPtr->wait))));
	    Tcl_AppendElement(interp,Tcl_SignalMsg((int) (WSTOPSIG(esPtr->wait))));
	}
    }
			
    if (fp) {
	fp->link_status = not_in_use;
	return ((result == -1)?TCL_ERROR:TCL_OK);		
    }

    esPtr->sys_waited = TRUE;
    esPtr->user_waited = TRUE;

    /* if user has already called close, forget about this entry entirely */

    if (!esPtr->open) {
      if (esPtr->registered) {

	Tcl_UnregisterChannel(interp,esPtr->channel);
      }

    }

    return ((result == -1)?TCL_ERROR:TCL_OK);
}

/*ARGSUSED*/
static int
Exp_ForkCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113



3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139

3140
3141

3142

3143
3144


3145





3146
3147

3148


3149
3150

3151




3152
3153

3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
	} else {
		/* parent */
		fork_add(rc);
	}

	/* both child and parent follow remainder of code */
	sprintf(interp->result,"%d",rc);
	debuglog("fork: returns {%s}\r\n",interp->result);
	return(TCL_OK);
}

/*ARGSUSED*/
static int
Exp_DisconnectCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{



	/* tell Saber to ignore non-use of ttyfd */
	/*SUPPRESS 591*/
	int ttyfd;

	if (argc > 1) {
		exp_error(interp,"usage: disconnect");
		return(TCL_ERROR);
	}

	if (exp_disconnected) {
		exp_error(interp,"already disconnected");
		return(TCL_ERROR);
	}
	if (!exp_forked) {
		exp_error(interp,"can only disconnect child process");
		return(TCL_ERROR);
	}
	exp_disconnected = TRUE;

	/* ignore hangup signals generated by testing ptys in getptymaster */
	/* and other places */
	signal(SIGHUP,SIG_IGN);

	/* reopen prevents confusion between send/expect_user */
	/* accidentally mapping to a real spawned process after a disconnect */
	if (exp_fs[0].pid != EXP_NOPID) {

		exp_close(interp,0);
		open("/dev/null",0);

		fd_new(0, EXP_NOPID);

	}
	if (exp_fs[1].pid != EXP_NOPID) {


		exp_close(interp,1);





		open("/dev/null",1);
		fd_new(1, EXP_NOPID);

	}


	if (exp_fs[2].pid != EXP_NOPID) {
		/* reopen stderr saves error checking in error/log routines. */

		exp_close(interp,2);




		open("/dev/null",1);
		fd_new(2, EXP_NOPID);

	}

	Tcl_UnsetVar(interp,"tty_spawn_id",TCL_GLOBAL_ONLY);

#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
	/* put process in our own pgrp, and lose controlling terminal */
#ifdef sysV88
	/* With setpgrp first, child ends up with closed stdio */
	/* according to Dave Schmitt <[email protected]> */
	if (fork()) exit(0);
	setpgrp();
#else
	setpgrp();
	/*signal(SIGHUP,SIG_IGN); moved out to above */
	if (fork()) exit(0);	/* first child exits (as per Stevens, */
	/* UNIX Network Programming, p. 79-80) */
	/* second child process continues as daemon */
#endif
#else /* !SYSV3 */
#ifdef MIPS_BSD
	/* required on BSD side of MIPS OS <[email protected]> */
#	include <sysv/sys.s>
	syscall(SYS_setpgrp);
#endif
	setpgrp(0,0);
/*	setpgrp(0,getpid());*/	/* put process in our own pgrp */

/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
	ttyfd = open("/dev/tty", O_RDWR);
	if (ttyfd >= 0) {
		/* zap controlling terminal if we had one */
		(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
		(void) close(ttyfd);
	}
#endif /* TIOCNOTTY */

#endif /* SYSV3 */
#endif /* DO_SETSID */
	return(TCL_OK);
}

/*ARGSUSED*/
static int
Exp_OverlayCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;







|











>
>
>
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
>
|
|
>
|
>
|
|
>
>
|
>
>
>
>
>
|
|
>

>
>
|
|
>
|
>
>
>
>
|
|
>
|

|


|


|

|
|
|
|

|
|
|
|
|


<
<
<
<
<
|
<



|
|
|
|
|
|




|







2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801





2802

2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
	} else {
		/* parent */
		fork_add(rc);
	}

	/* both child and parent follow remainder of code */
	sprintf(interp->result,"%d",rc);
	expDiagLog("fork: returns {%s}\r\n",interp->result);
	return(TCL_OK);
}

/*ARGSUSED*/
static int
Exp_DisconnectCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    

    /* tell CenterLine to ignore non-use of ttyfd */
    /*SUPPRESS 591*/
    int ttyfd;

    if (argc > 1) {
	exp_error(interp,"usage: disconnect");
	return(TCL_ERROR);
    }

    if (exp_disconnected) {
	exp_error(interp,"already disconnected");
	return(TCL_ERROR);
    }
    if (!exp_forked) {
	exp_error(interp,"can only disconnect child process");
	return(TCL_ERROR);
    }
    exp_disconnected = TRUE;

    /* ignore hangup signals generated by testing ptys in getptymaster */
    /* and other places */
    signal(SIGHUP,SIG_IGN);

    /* reopen prevents confusion between send/expect_user */
    /* accidentally mapping to a real spawned process after a disconnect */

    /* if we're in a child that's about to be disconnected from the
       controlling tty, close and reopen 0, 1, and 2 but associated
       with /dev/null.  This prevents send and expect_user doing
       special things if newly spawned processes accidentally
       get allocated 0, 1, and 2.
    */
	   
    if (isatty(0)) {
	ExpState *stdinout = tsdPtr->stdinout;
	if (stdinout->valid) {
	    exp_close(interp,stdinout);
	    if (stdinout->registered) {
		Tcl_UnregisterChannel(interp,stdinout->channel);
	    }
	}
	open("/dev/null",0);
	open("/dev/null",1);
	/* tsdPtr->stdinout = expCreateChannel(interp,0,1,EXP_NOPID);*/
	/* tsdPtr->stdinout->keepForever = 1;*/
	}
    if (isatty(2)) {
	ExpState *devtty = tsdPtr->devtty;
	
	/* reopen stderr saves error checking in error/log routines. */
	if (devtty->valid) {
	    exp_close(interp,devtty);
	    if (devtty->registered) {
		Tcl_UnregisterChannel(interp,devtty->channel);
	    }
	}
	open("/dev/null",1);
	/* tsdPtr->devtty = expCreateChannel(interp,2,2,EXP_NOPID);*/
	/* tsdPtr->devtty->keepForever = 1;*/
    }

    Tcl_UnsetVar(interp,"tty_spawn_id",TCL_GLOBAL_ONLY);

#ifdef DO_SETSID
    setsid();
#else
#ifdef SYSV3
    /* put process in our own pgrp, and lose controlling terminal */
#ifdef sysV88
    /* With setpgrp first, child ends up with closed stdio */
    /* according to Dave Schmitt <[email protected]> */
    if (fork()) exit(0);
    expSetpgrp();
#else
    expSetpgrp();
    /*signal(SIGHUP,SIG_IGN); moved out to above */
    if (fork()) exit(0);	/* first child exits (as per Stevens, */
    /* UNIX Network Programming, p. 79-80) */
    /* second child process continues as daemon */
#endif
#else /* !SYSV3 */





    expSetpgrp();


/* Pyramid lacks this defn */
#ifdef TIOCNOTTY
    ttyfd = open("/dev/tty", O_RDWR);
    if (ttyfd >= 0) {
	/* zap controlling terminal if we had one */
	(void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
	(void) close(ttyfd);
    }
#endif /* TIOCNOTTY */

#endif /* SYSV3 */
#endif /* DO_SETSID */
    return(TCL_OK);
}

/*ARGSUSED*/
static int
Exp_OverlayCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255

3256
3257
3258

3259
3260
3261
3262

3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287



3288
3289




3290
3291
3292


3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310



3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402



3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427

3428



3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
		argc--; argv++;
		if (argc == 0) {
			exp_error(interp,"overlay -# requires additional argument");
			return(TCL_ERROR);
		}
		oldfd = atoi(argv[0]);
		argc--; argv++;
		debuglog("overlay: mapping fd %d to %d\r\n",oldfd,newfd);
		if (oldfd != newfd) (void) dup2(oldfd,newfd);
		else debuglog("warning: overlay: old fd == new fd (%d)\r\n",oldfd);
	}
	if (argc == 0) {
		exp_error(interp,"need program name");
		return(TCL_ERROR);
	}
	command = argv[0];
	if (dash_name) {
		argv[0] = ckalloc(1+strlen(command));
		sprintf(argv[0],"-%s",command);
	}

	signal(SIGINT, SIG_DFL);
	signal(SIGQUIT, SIG_DFL);
        (void) execvp(command,argv);
	exp_error(interp,"execvp(%s): %s\r\n",argv[0],Tcl_PosixError(interp));
	return(TCL_ERROR);
}

#if 0
/*ARGSUSED*/
int
cmdReady(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;

{
	char num[4];	/* can hold up to "999 " */
	char buf[1024];	/* can easily hold 256 spawn_ids! */

	int i, j;
	int *masters, *masters2;
	int timeout = get_timeout();


	if (argc < 2) {
		exp_error(interp,"usage: ready spawn_id1 [spawn_id2 ...]");
		return(TCL_ERROR);
	}

	masters = (int *)ckalloc((argc-1)*sizeof(int));
	masters2 = (int *)ckalloc((argc-1)*sizeof(int));

	for (i=1;i<argc;i++) {
		j = atoi(argv[i]);
		if (!exp_fd2f(interp,j,1,"ready")) {
			ckfree(masters);
			return(TCL_ERROR);
		}
		masters[i-1] = j;
	}
	j = i-1;
	if (TCL_ERROR == ready(masters,i-1,masters2,&j,&timeout))
		return(TCL_ERROR);

	/* pack result back into out-array */
	buf[0] = '\0';
	for (i=0;i<j;i++) {
		sprintf(num,"%d ",masters2[i]); /* note extra blank */
		strcat(buf,num);



	}
	ckfree(masters); ckfree(masters2);




	Tcl_Return(interp,buf,TCL_VOLATILE);
	return(TCL_OK);
}


#endif

/*ARGSUSED*/
int
Exp_InterpreterCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	if (argc != 1) {
		exp_error(interp,"no arguments allowed");
		return(TCL_ERROR);
	}

	return(exp_interpreter(interp));
	/* errors and ok, are caught by exp_interpreter() and discarded */
	/* to return TCL_OK, type "return" */



}

/* this command supercede's Tcl's builtin CONTINUE command */
/*ARGSUSED*/
int
Exp_ExpContinueCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	if (argc == 1) {
		return EXP_CONTINUE;
	} else if ((argc == 2) && (0 == strcmp(argv[1],"-continue_timer"))) {
		return EXP_CONTINUE_TIMER;
	}

	exp_error(interp,"usage: exp_continue [-continue_timer]\n");
	return(TCL_ERROR);
}

#if TCL_MAJOR_VERSION < 8
/* most of this is directly from Tcl's definition for return */
/*ARGSUSED*/
int
Exp_InterReturnCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	/* let Tcl's return command worry about args */
	/* if successful (i.e., TCL_RETURN is returned) */
	/* modify the result, so that we will handle it specially */

	int result = Tcl_ReturnCmd(clientData,interp,argc,argv);
	if (result == TCL_RETURN)
		result = EXP_TCL_RETURN;
	return result;
}
#else
/* most of this is directly from Tcl's definition for return */
/*ARGSUSED*/
int
Exp_InterReturnObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
    /* let Tcl's return command worry about args */
    /* if successful (i.e., TCL_RETURN is returned) */
    /* modify the result, so that we will handle it specially */

    int result = Tcl_ReturnObjCmd(clientData,interp,objc,objv);
    if (result == TCL_RETURN)
        result = EXP_TCL_RETURN;
    return result;
}
#endif

/*ARGSUSED*/
int
Exp_OpenCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	struct exp_f *f;
	int m = -1;
	int m2;
	int leaveopen = FALSE;
	Tcl_Channel chan;

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-i")) {
			argc--; argv++;
			if (!*argv) {
				exp_error(interp,"usage: -i spawn_id");
				return TCL_ERROR;
			}
			m = atoi(*argv);
		} else if (streq(*argv,"-leaveopen")) {
			leaveopen = TRUE;
			argc--; argv++;
		} else break;
	}

	if (m == -1) {



		if (exp_update_master(interp,&m,0,0) == 0) return TCL_ERROR;
	}

	if (0 == (f = exp_fd2f(interp,m,1,0,"exp_open"))) return TCL_ERROR;

	/* make a new copy of file descriptor */
	if (-1 == (m2 = dup(m))) {
		exp_error(interp,"fdopen: %s",Tcl_PosixError(interp));
		return TCL_ERROR;
	}

	if (!leaveopen) {
		/* remove from Expect's memory in anticipation of passing to Tcl */
		if (f->pid != EXP_NOPID) {
#if TCL_MAJOR_VERSION < 8
			Tcl_DetachPids(1,&f->pid);
#else
			Tcl_DetachPids(1,(Tcl_Pid *)&f->pid);
#endif
			f->pid = EXP_NOPID;
			f->sys_waited = f->user_waited = TRUE;
		}
		exp_close(interp,m);
	}


	chan = Tcl_MakeFileChannel(



#if TCL_MAJOR_VERSION < 8
			    (ClientData)m2,
#endif
			    (ClientData)m2,

			    TCL_READABLE|TCL_WRITABLE);
	Tcl_RegisterChannel(interp, chan);
	Tcl_AppendResult(interp, Tcl_GetChannelName(chan), (char *) NULL);
	return TCL_OK;
}

/* return 1 if a string is substring of a flag */
/* this version is the code used by the macro that everyone calls */
int
exp_flageq_code(flag,string,minlen)
char *flag;







|

|


















<


|


|
<
>

<
<
>
|
|
|

>
|
<
<
|
|
<
<
|
<
<
<
<
<
|
<
<
<
<
<

<
<
|
<
<
>
>
>

<
>
>
>
>
|
|
|
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
|

<
|
|
>
>
>











|
|
|
|
|

|
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


















<









|
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
>
>
>
|
|

<
<
|
|
|
|
|

|
|
|
<
<
<
|
<
|
|
|
|
|

>
|
>
>
>
|
|
|
<
>
|
|
|
|







2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867

2868
2869
2870
2871
2872
2873

2874
2875


2876
2877
2878
2879
2880
2881
2882


2883
2884


2885





2886





2887


2888


2889
2890
2891
2892

2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903











2904
2905

2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931




















2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949

2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987


2988
2989
2990
2991
2992
2993
2994
2995
2996



2997

2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011

3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
		argc--; argv++;
		if (argc == 0) {
			exp_error(interp,"overlay -# requires additional argument");
			return(TCL_ERROR);
		}
		oldfd = atoi(argv[0]);
		argc--; argv++;
		expDiagLog("overlay: mapping fd %d to %d\r\n",oldfd,newfd);
		if (oldfd != newfd) (void) dup2(oldfd,newfd);
		else expDiagLog("warning: overlay: old fd == new fd (%d)\r\n",oldfd);
	}
	if (argc == 0) {
		exp_error(interp,"need program name");
		return(TCL_ERROR);
	}
	command = argv[0];
	if (dash_name) {
		argv[0] = ckalloc(1+strlen(command));
		sprintf(argv[0],"-%s",command);
	}

	signal(SIGINT, SIG_DFL);
	signal(SIGQUIT, SIG_DFL);
        (void) execvp(command,argv);
	exp_error(interp,"execvp(%s): %s\r\n",argv[0],Tcl_PosixError(interp));
	return(TCL_ERROR);
}


/*ARGSUSED*/
int
Exp_InterpreterObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;

Tcl_Obj *CONST objv[];		/* Argument objects. */
{


    Tcl_Obj *eofObj = 0;
    int i;
    int index;
    int rc;

    static char *options[] = {
	"-eof", (char *)0


    };
    enum options {


	FLAG_EOF





    };








    for (i = 1; i < objc; i++) {


	if (Tcl_GetIndexFromObj(interp, objv[i], options, "flag", 0,
				&index) != TCL_OK) {
	    return TCL_ERROR;
	}

	switch ((enum options) index) {
	case FLAG_EOF:
	    i++;
	    if (i >= objc) {
		Tcl_WrongNumArgs(interp, 1, objv,"-eof cmd");
		return TCL_ERROR;
	    }
	    eofObj = objv[i];
	    Tcl_IncrRefCount(eofObj);
	    break;
	}











    }


    /* errors and ok, are caught by exp_interpreter() and discarded */
    /* to return TCL_OK, type "return" */
    rc = exp_interpreter(interp,eofObj);
    if (eofObj) Tcl_DecrRefCount(eofObj);
    return rc;
}

/* this command supercede's Tcl's builtin CONTINUE command */
/*ARGSUSED*/
int
Exp_ExpContinueCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    if (argc == 1) {
	return EXP_CONTINUE;
    } else if ((argc == 2) && (0 == strcmp(argv[1],"-continue_timer"))) {
	return EXP_CONTINUE_TIMER;
    }

    exp_error(interp,"usage: exp_continue [-continue_timer]\n");
    return(TCL_ERROR);
}





















/* most of this is directly from Tcl's definition for return */
/*ARGSUSED*/
int
Exp_InterReturnObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
    /* let Tcl's return command worry about args */
    /* if successful (i.e., TCL_RETURN is returned) */
    /* modify the result, so that we will handle it specially */

    int result = Tcl_ReturnObjCmd(clientData,interp,objc,objv);
    if (result == TCL_RETURN)
        result = EXP_TCL_RETURN;
    return result;
}


/*ARGSUSED*/
int
Exp_OpenCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    ExpState *esPtr;
    char *chanName = 0;
    int newfd;
    int leaveopen = FALSE;
    Tcl_Channel channel;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-i")) {
	    argc--; argv++;
	    if (!*argv) {
		exp_error(interp,"usage: -i spawn_id");
		return TCL_ERROR;
	    }
	    chanName = *argv;
	} else if (streq(*argv,"-leaveopen")) {
	    leaveopen = TRUE;
	    argc--; argv++;
	} else break;
    }

    if (!chanName) {
	if (!(esPtr = expStateCurrent(interp,1,0,0))) return TCL_ERROR;
    } else {
	if (!(esPtr = expStateFromChannelName(interp,chanName,1,0,0,"exp_open")))
return TCL_ERROR;
    }



    /* make a new copy of file descriptor */
    if (-1 == (newfd = dup(esPtr->fdin))) {
	exp_error(interp,"dup: %s",Tcl_PosixError(interp));
	return TCL_ERROR;
    }

    if (!leaveopen) {
	/* remove from Expect's memory in anticipation of passing to Tcl */
	if (esPtr->pid != EXP_NOPID) {



	    Tcl_DetachPids(1,(Tcl_Pid *)&esPtr->pid);

	    esPtr->pid = EXP_NOPID;
	    esPtr->sys_waited = esPtr->user_waited = TRUE;
	}
	exp_close(interp,esPtr);
    }

    /*
     * Tcl's MakeFileChannel only allows us to pass a single file descriptor
     * but that shouldn't be a problem in practice since all of the channels
     * that Expect generates only have one fd.  Of course, this code won't
     * work if someone creates a pipeline, then passes it to spawn, and then
     * again to exp_open.  For that to work, Tcl would need a new API.
     * Oh, and we're also being rather cavalier with the permissions here,
     * but they're likely to be right for the same reasons.

     */
    channel = Tcl_MakeFileChannel((ClientData)newfd,TCL_READABLE|TCL_WRITABLE);
    Tcl_RegisterChannel(interp, channel);
    Tcl_AppendResult(interp, Tcl_GetChannelName(channel), (char *) NULL);
    return TCL_OK;
}

/* return 1 if a string is substring of a flag */
/* this version is the code used by the macro that everyone calls */
int
exp_flageq_code(flag,string,minlen)
char *flag;
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
}

void
exp_create_commands(interp,c)
Tcl_Interp *interp;
struct exp_cmd_data *c;
{
#if TCL_MAJOR_VERSION < 8
	Interp *iPtr = (Interp *) interp;
#else
	Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
	Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);
#endif
	char cmdnamebuf[80];

	for (;c->name;c++) {
#if TCL_MAJOR_VERSION < 8
		int create = FALSE;
		/* if already defined, don't redefine */
		if (c->flags & EXP_REDEFINE) create = TRUE;
		else if (!Tcl_FindHashEntry(&iPtr->commandTable,c->name)) {
			create = TRUE;
		}
		if (create) {
			Tcl_CreateCommand(interp,c->name,c->proc,
				c->data,exp_deleteProc);
		}
#else
		/* if already defined, don't redefine */
		if ((c->flags & EXP_REDEFINE) ||
		    !(Tcl_FindHashEntry(&globalNsPtr->cmdTable,c->name) ||
		      Tcl_FindHashEntry(&currNsPtr->cmdTable,c->name))) {
			if (c->objproc)
				Tcl_CreateObjCommand(interp,c->name,
						     c->objproc,c->data,exp_deleteObjProc);
			else
				Tcl_CreateCommand(interp,c->name,c->proc,
						  c->data,exp_deleteProc);
		}
#endif
		if (!(c->name[0] == 'e' &&
		      c->name[1] == 'x' &&
		      c->name[2] == 'p')
		    && !(c->flags & EXP_NOPREFIX)) {
			sprintf(cmdnamebuf,"exp_%s",c->name);
#if TCL_MAJOR_VERSION < 8
			Tcl_CreateCommand(interp,cmdnamebuf,c->proc,
				c->data,exp_deleteProc);
#else
			if (c->objproc)
				Tcl_CreateObjCommand(interp,cmdnamebuf,c->objproc,c->data,
						     exp_deleteObjProc);
			else
				Tcl_CreateCommand(interp,cmdnamebuf,c->proc,
						  c->data,exp_deleteProc);
#endif
		}
	}
}

static struct exp_cmd_data cmd_data[]  = {
#if TCL_MAJOR_VERSION < 8
{"close",	Exp_CloseCmd,	0,	EXP_REDEFINE},
#else
{"close",	Exp_CloseObjCmd,	0,	0,	EXP_REDEFINE},
#endif
#ifdef TCL_DEBUGGER
{"debug",	exp_proc(Exp_DebugCmd),	0,	0},
#endif
{"exp_internal",exp_proc(Exp_ExpInternalCmd),	0,	0},
{"disconnect",	exp_proc(Exp_DisconnectCmd),	0,	0},
{"exit",	exp_proc(Exp_ExitCmd),	0,	EXP_REDEFINE},
{"exp_continue",exp_proc(Exp_ExpContinueCmd),0,	0},
{"fork",	exp_proc(Exp_ForkCmd),	0,	0},
{"exp_pid",	exp_proc(Exp_ExpPidCmd),	0,	0},
{"getpid",	exp_proc(Exp_GetpidDeprecatedCmd),0,	0},
{"interpreter",	exp_proc(Exp_InterpreterCmd),	0,	0},
{"log_file",	exp_proc(Exp_LogFileCmd),	0,	0},
{"log_user",	exp_proc(Exp_LogUserCmd),	0,	0},
{"exp_open",	exp_proc(Exp_OpenCmd),	0,	0},
{"overlay",	exp_proc(Exp_OverlayCmd),	0,	0},
#if TCL_MAJOR_VERSION < 8
{"inter_return",Exp_InterReturnCmd,	0,	0},
#else
{"inter_return",Exp_InterReturnObjCmd,	0,	0,	0},
#endif
{"send",	exp_proc(Exp_SendCmd),	(ClientData)&sendCD_proc,	0},
{"send_error",	exp_proc(Exp_SendCmd),	(ClientData)&sendCD_error,	0},
{"send_log",	exp_proc(Exp_SendLogCmd),	0,	0},
{"send_tty",	exp_proc(Exp_SendCmd),	(ClientData)&sendCD_tty,	0},
{"send_user",	exp_proc(Exp_SendCmd),	(ClientData)&sendCD_user,	0},
{"sleep",	exp_proc(Exp_SleepCmd),	0,	0},
{"spawn",	exp_proc(Exp_SpawnCmd),	0,	0},
{"strace",	exp_proc(Exp_StraceCmd),	0,	0},
{"wait",	exp_proc(Exp_WaitCmd),	0,	0},
{0}};

void
exp_init_most_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);

#ifdef HAVE_PTYTRAP
	Tcl_InitHashTable(&slaveNames,TCL_STRING_KEYS);
#endif /* HAVE_PTYTRAP */

	exp_close_in_child = exp_close_tcl_files;
}







<
<
<


<



<
<
<
<
<
<
<
<
<
<
<
<











<





<
<
<
<






<





<
<
<

<










|




<
<
<

<
|
|

|
|










|


|

|
<
<
3033
3034
3035
3036
3037
3038
3039



3040
3041

3042
3043
3044












3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055

3056
3057
3058
3059
3060




3061
3062
3063
3064
3065
3066

3067
3068
3069
3070
3071



3072

3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087



3088

3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109


}

void
exp_create_commands(interp,c)
Tcl_Interp *interp;
struct exp_cmd_data *c;
{



	Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp);
	Namespace *currNsPtr   = (Namespace *) Tcl_GetCurrentNamespace(interp);

	char cmdnamebuf[80];

	for (;c->name;c++) {












		/* if already defined, don't redefine */
		if ((c->flags & EXP_REDEFINE) ||
		    !(Tcl_FindHashEntry(&globalNsPtr->cmdTable,c->name) ||
		      Tcl_FindHashEntry(&currNsPtr->cmdTable,c->name))) {
			if (c->objproc)
				Tcl_CreateObjCommand(interp,c->name,
						     c->objproc,c->data,exp_deleteObjProc);
			else
				Tcl_CreateCommand(interp,c->name,c->proc,
						  c->data,exp_deleteProc);
		}

		if (!(c->name[0] == 'e' &&
		      c->name[1] == 'x' &&
		      c->name[2] == 'p')
		    && !(c->flags & EXP_NOPREFIX)) {
			sprintf(cmdnamebuf,"exp_%s",c->name);




			if (c->objproc)
				Tcl_CreateObjCommand(interp,cmdnamebuf,c->objproc,c->data,
						     exp_deleteObjProc);
			else
				Tcl_CreateCommand(interp,cmdnamebuf,c->proc,
						  c->data,exp_deleteProc);

		}
	}
}

static struct exp_cmd_data cmd_data[]  = {



{"close",	Exp_CloseObjCmd,	0,	0,	EXP_REDEFINE},

#ifdef TCL_DEBUGGER
{"debug",	exp_proc(Exp_DebugCmd),	0,	0},
#endif
{"exp_internal",exp_proc(Exp_ExpInternalCmd),	0,	0},
{"disconnect",	exp_proc(Exp_DisconnectCmd),	0,	0},
{"exit",	exp_proc(Exp_ExitCmd),	0,	EXP_REDEFINE},
{"exp_continue",exp_proc(Exp_ExpContinueCmd),0,	0},
{"fork",	exp_proc(Exp_ForkCmd),	0,	0},
{"exp_pid",	exp_proc(Exp_ExpPidCmd),	0,	0},
{"getpid",	exp_proc(Exp_GetpidDeprecatedCmd),0,	0},
{"interpreter",	Exp_InterpreterObjCmd,	0,	0,	0},
{"log_file",	exp_proc(Exp_LogFileCmd),	0,	0},
{"log_user",	exp_proc(Exp_LogUserCmd),	0,	0},
{"exp_open",	exp_proc(Exp_OpenCmd),	0,	0},
{"overlay",	exp_proc(Exp_OverlayCmd),	0,	0},



{"inter_return",Exp_InterReturnObjCmd,	0,	0,	0},

{"send",	Exp_SendObjCmd,		0,	(ClientData)&sendCD_proc,0},
{"send_error",	Exp_SendObjCmd,		0,	(ClientData)&sendCD_error,0},
{"send_log",	exp_proc(Exp_SendLogCmd),	0,	0},
{"send_tty",	Exp_SendObjCmd,		0,	(ClientData)&sendCD_tty,0},
{"send_user",	Exp_SendObjCmd,		0,	(ClientData)&sendCD_user,0},
{"sleep",	exp_proc(Exp_SleepCmd),	0,	0},
{"spawn",	exp_proc(Exp_SpawnCmd),	0,	0},
{"strace",	exp_proc(Exp_StraceCmd),	0,	0},
{"wait",	exp_proc(Exp_WaitCmd),	0,	0},
{0}};

void
exp_init_most_cmds(interp)
Tcl_Interp *interp;
{
    exp_create_commands(interp,cmd_data);

#ifdef HAVE_PTYTRAP
    Tcl_InitHashTable(&slaveNames,TCL_STRING_KEYS);
#endif /* HAVE_PTYTRAP */
}


Changes to exp_command.h.

1
2
3
4
5
6
7
8
9










10

11


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
/* command.h - definitions for expect commands

Written by: Don Libes, NIST, 2/6/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/











EXTERN struct exp_f *	exp_update_master

				_ANSI_ARGS_((Tcl_Interp *,int *,int,int));


EXTERN char *		exp_get_var _ANSI_ARGS_((Tcl_Interp *,char *));

EXTERN int exp_default_match_max;
EXTERN int exp_default_parity;
EXTERN int exp_default_rm_nulls;

EXTERN int		exp_one_arg_braced _ANSI_ARGS_((char *));
EXTERN int		exp_eval_with_one_arg _ANSI_ARGS_((ClientData,
				Tcl_Interp *,char **));
EXTERN void		exp_lowmemcpy _ANSI_ARGS_((char *,char *,int));

EXTERN int exp_flageq_code _ANSI_ARGS_((char *,char *,int));

#define exp_flageq(flag,string,minlen) \
(((string)[0] == (flag)[0]) && (exp_flageq_code(((flag)+1),((string)+1),((minlen)-1))))

/* exp_flageq for single char flags */
#define exp_flageq1(flag,string) \
	((string[0] == flag) && (string[1] == '\0'))

/*
 * The type of the status returned by wait varies from UNIX system
 * to UNIX system.  The macro below defines it:
 * (stolen from tclUnix.h)
 */

#define WAIT_STATUS_TYPE int
#if 0
#ifdef AIX
#   define WAIT_STATUS_TYPE pid_t
#else
#ifndef NO_UNION_WAIT
#   define WAIT_STATUS_TYPE union wait
#else
#   define WAIT_STATUS_TYPE int
#endif
#endif /* AIX */

/* These macros are taken from tclUnix.h */

#undef WIFEXITED
#ifndef WIFEXITED
#   define WIFEXITED(stat)  (((*((int *) &(stat))) & 0xff) == 0)
#endif

#undef WEXITSTATUS
#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
#endif

#undef WIFSIGNALED
#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff)))
#endif

#undef WTERMSIG
#ifndef WTERMSIG
#   define WTERMSIG(stat)    ((*((int *) &(stat))) & 0x7f)
#endif

#undef WIFSTOPPED
#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)  (((*((int *) &(stat))) & 0xff) == 0177)
#endif

#undef WSTOPSIG
#ifndef WSTOPSIG
#   define WSTOPSIG(stat)    (((*((int *) &(stat))) >> 8) & 0xff)
#endif

#endif /* 0 */

/* These macros are suggested by the autoconf documentation. */

#undef WIFEXITED
#ifndef WIFEXITED
#   define WIFEXITED(stat)  (((stat) & 0xff) == 0)
#endif

#undef WEXITSTATUS
#ifndef WEXITSTATUS
#   define WEXITSTATUS(stat) (((stat) >> 8) & 0xff)
#endif

#undef WIFSIGNALED
#ifndef WIFSIGNALED
#   define WIFSIGNALED(stat) ((stat) && ((stat) == ((stat) & 0x00ff)))
#endif

#undef WTERMSIG
#ifndef WTERMSIG
#   define WTERMSIG(stat)    ((stat) & 0x7f)
#endif

#undef WIFSTOPPED
#ifndef WIFSTOPPED
#   define WIFSTOPPED(stat)  (((stat) & 0xff) == 0177)
#endif

#undef WSTOPSIG
#ifndef WSTOPSIG
#   define WSTOPSIG(stat)    (((stat) >> 8) & 0xff)
#endif



#define EXP_SPAWN_ID_ANY_VARNAME	"any_spawn_id"
#define EXP_SPAWN_ID_ANY_LIT		"-1"
#define EXP_SPAWN_ID_ANY		-1

#define EXP_SPAWN_ID_ERROR_LIT		"2"
#define EXP_SPAWN_ID_USER_LIT		"0"
#define EXP_SPAWN_ID_USER		0


#define exp_is_stdinfd(x)	((x) == 0)
#define exp_is_devttyfd(x)	((x) == exp_dev_tty)

#define EXP_NOPID	0	/* Used when there is no associated pid to */
				/* wait for.  For example: */
				/* 1) When fd opened by someone else, e.g., */









>
>
>
>
>
>
>
>
>
>
|
>
|
>
>






|

|











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<

|
|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44






















































































45
46

47
48
49
50
51
52
53
54
55
56
57
58
/* command.h - definitions for expect commands

Written by: Don Libes, NIST, 2/6/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#ifdef HAVE_SYS_WAIT_H
  /* ISC doesn't def WNOHANG unless _POSIX_SOURCE is def'ed */
# ifdef WNOHANG_REQUIRES_POSIX_SOURCE
#  define _POSIX_SOURCE
# endif
# include <sys/wait.h>
# ifdef WNOHANG_REQUIRES_POSIX_SOURCE
#  undef _POSIX_SOURCE
# endif
#endif

#include <tclPort.h>

#define EXP_CHANNELNAMELEN (16 + TCL_INTEGER_SPACE)

EXTERN char *		exp_get_var _ANSI_ARGS_((Tcl_Interp *,char *));

EXTERN int exp_default_match_max;
EXTERN int exp_default_parity;
EXTERN int exp_default_rm_nulls;

EXTERN int		exp_one_arg_braced _ANSI_ARGS_((Tcl_Obj *));
EXTERN int		exp_eval_with_one_arg _ANSI_ARGS_((ClientData,
				Tcl_Interp *, struct Tcl_Obj * CONST objv[]));
EXTERN void		exp_lowmemcpy _ANSI_ARGS_((char *,char *,int));

EXTERN int exp_flageq_code _ANSI_ARGS_((char *,char *,int));

#define exp_flageq(flag,string,minlen) \
(((string)[0] == (flag)[0]) && (exp_flageq_code(((flag)+1),((string)+1),((minlen)-1))))

/* exp_flageq for single char flags */
#define exp_flageq1(flag,string) \
	((string[0] == flag) && (string[1] == '\0'))























































































#define EXP_SPAWN_ID_USER		0
#define EXP_SPAWN_ID_ANY_LIT		"-1"


#define EXP_CHANNEL_PREFIX "exp"
#define EXP_CHANNEL_PREFIX_LENGTH 3
#define isExpChannelName(name) \
    (0 == strncmp(name,EXP_CHANNEL_PREFIX,EXP_CHANNEL_PREFIX_LENGTH))

#define exp_is_stdinfd(x)	((x) == 0)
#define exp_is_devttyfd(x)	((x) == exp_dev_tty)

#define EXP_NOPID	0	/* Used when there is no associated pid to */
				/* wait for.  For example: */
				/* 1) When fd opened by someone else, e.g., */
139
140
141
142
143
144
145
146
147

148
149




150

151


152
153




154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176








177
178
179
180



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221































222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/* these are occasionally useful to distinguish between various expect */
/* commands and are also used as array indices into the per-fd eg[] arrays */
#define EXP_CMD_BEFORE	0
#define EXP_CMD_AFTER	1
#define EXP_CMD_BG	2
#define EXP_CMD_FG	3

/* each process is associated with a 'struct exp_f'.  An array of these */
/* ('exp_fs') keeps track of all processes.  They are indexed by the true fd */

/* to the master side of the pty */
struct exp_f {




	int *fd_ptr;

#if 0


	struct exp_f **ptr;	/* our own address to this exp_f */
			/* since address can change, provide this indirect */




			/* pointer for people (Tk) who require a fixed ptr */
#endif
	int pid;	/* pid or EXP_NOPID if no pid */
	char *buffer;	/* input buffer */
	char *lower;	/* input buffer in lowercase */
	int size;	/* current size of data */
	int msize;	/* size of buffer (true size is one greater
			   for trailing null) */
	int umsize;	/* user view of size of buffer */
	int rm_nulls;	/* if nulls should be stripped before pat matching */
	int valid;	/* if any of the other fields should be believed */
	int user_closed;/* if user has issued "close" command or close has */
			/* occurred implicitly */
	int sys_closed;	/* if close() has been called */
	int user_waited;/* if user has issued "wait" command */
	int sys_waited;	/* if wait() (or variant) has been called */
	WAIT_STATUS_TYPE wait;	/* raw status from wait() */
	int parity;	/* strip parity if false */
	int printed;	/* # of characters written to stdout (if logging on) */
			/* but not actually returned via a match yet */
	int echoed;	/* additional # of chars (beyond "printed" above) */
			/* echoed back but not actually returned via a match */
			/* yet.  This supports interact -echo */








	int key;	/* unique id that identifies what command instance */
			/* last touched this buffer */
	int force_read;	/* force read to occur (even if buffer already has */
			/* data).  This supports interact CAN_MATCH */



	int fg_armed;	/* If Tk_CreateFileHandler is active for responding */
			/* to foreground events */


#if TCL_MAJOR_VERSION < 8
	Tcl_File Master;	/* corresponds to master fd */
	Tcl_File Slave;		/* corresponds to slave_fd */
	Tcl_File MasterOutput;	/* corresponds to tcl_output */
	/*
	 *  Following comment only applies to Tcl 7.6:
	 *  Explicit fds aren't necessary now, but since the code is already
	 *  here from before Tcl required Tcl_File, we'll continue using
	 *  the old fds.  If we ever port this code to a non-UNIX system,
	 *  we'll dump the fds totally.
	 */
#endif /* TCL_MAJOR_VERSION < 8 */
	   
	int slave_fd;	/* slave fd if "spawn -pty" used */
#ifdef HAVE_PTYTRAP
	char *slave_name;/* Full name of slave, i.e., /dev/ttyp0 */
#endif /* HAVE_PTYTRAP */
	char *tcl_handle;/* If opened by someone else, i.e. Tcl's open */
	int tcl_output;	/* output fd if opened by someone else */
			/* input fd is the index of this struct (see above) */
	int leaveopen;	/* If we should not call Tcl's close when we close - */
			/* only relevant if Tcl does the original open */

	Tcl_Interp *bg_interp;	/* interp to process the bg cases */
	int bg_ecount;		/* number of background ecases */
	enum {
		blocked,	/* blocked because we are processing the */
				/* file handler */
		armed,		/* normal state when bg handler in use */
		unarmed,	/* no bg handler in use */
		disarm_req_while_blocked	/* while blocked, a request */
				/* was received to disarm it.  Rather than */
				/* processing the request immediately, defer */
				/* it so that when we later try to unblock */
				/* we will see at that time that it should */
				/* instead be disarmed */
	} bg_status;
};
































extern int exp_fd_max;		/* highest fd ever used */


#define EXP_TEMPORARY	1	/* expect */
#define EXP_PERMANENT	2	/* expect_after, expect_before, expect_bg */

#define EXP_DIRECT	1
#define EXP_INDIRECT	2

EXTERN struct exp_f *exp_fs;

EXTERN struct exp_f *	exp_fd2f _ANSI_ARGS_((Tcl_Interp *,int,int,int,char *));
EXTERN void		exp_adjust _ANSI_ARGS_((struct exp_f *));
EXTERN void		exp_buffer_shuffle _ANSI_ARGS_((Tcl_Interp *,struct exp_f *,int,char *,char *));
EXTERN int		exp_close _ANSI_ARGS_((Tcl_Interp *,int));
EXTERN void		exp_close_all _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_ecmd_remove_fd_direct_and_indirect 
				_ANSI_ARGS_((Tcl_Interp *,int));
EXTERN void		exp_trap_on _ANSI_ARGS_((int));
EXTERN int		exp_trap_off _ANSI_ARGS_((char *));

EXTERN void		exp_strftime();







|
|
>
|
|
>
>
>
>
|
>
|
>
>
|
|
>
>
>
>
|
<
|
|
|
<
|
<
|
<
<
<
<
<
|
<
<
<
|
|
|
|
|
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

|
<
<
|
|
>
|
|
|
|
|
|
|
|





|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
|







<
<
<
|
|
|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96

97

98





99



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
















122
123
124
125


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183



184
185
186
187
188
189
190
191
192
193
/* these are occasionally useful to distinguish between various expect */
/* commands and are also used as array indices into the per-fd eg[] arrays */
#define EXP_CMD_BEFORE	0
#define EXP_CMD_AFTER	1
#define EXP_CMD_BG	2
#define EXP_CMD_FG	3

/*
 * This structure describes per-instance state of an Exp channel.
 */

typedef struct ExpState {
    Tcl_Channel channel;	/* Channel associated with this file. */
    char name[EXP_CHANNELNAMELEN+1]; /* expect and interact set variables
				   to channel name, so for efficiency
				   cache it here */
    int fdin;		/* input fd */
    int fdout;		/* output fd - usually the same as fdin, although
			   may be different if channel opened by tcl::open */
    Tcl_Channel channel_orig;   /* If opened by someone else, i.e. tcl::open */
    int fd_slave;	/* slave fd if "spawn -pty" used */

    /* this may go away if we find it is not needed */
    /* it might be needed by inherited channels */
    int validMask;		/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates
				 * which operations are valid on the file. */


    int pid;		/* pid or EXP_NOPID if no pid */
    Tcl_Obj *buffer;	/* input buffer */


    int msize;	        /* # of bytes that buffer can hold (max) */

    int umsize;	        /* # of bytes (min) that is guaranteed to match */





			/* this comes from match_max command */



    int printed;	/* # of bytes written to stdout (if logging on) */
                        /* but not actually returned via a match yet */
    int echoed;	        /* additional # of bytes (beyond "printed" above) */
                        /* echoed back but not actually returned via a match */
                        /* yet.  This supports interact -echo */

    int rm_nulls;	/* if nulls should be stripped before pat matching */
    int open;		/* if fdin/fdout open */
    int user_waited;    /* if user has issued "wait" command */
    int sys_waited;	/* if wait() (or variant) has been called */
    int registered;	/* if channel registered */
    WAIT_STATUS_TYPE wait;	/* raw status from wait() */
    int parity;	        /* if parity should be preserved */
    int key;	        /* unique id that identifies what command instance */
                        /* last touched this buffer */
    int force_read;	/* force read to occur (even if buffer already has */
                        /* data).  This supports interact CAN_MATCH */
    int notified;	/* If Tcl_NotifyChannel has been called and we */
		        /* have not yet read from the channel. */
    int notifiedMask;	/* Mask reported when notified. */
    int fg_armed;	/* If Tk_CreateFileHandler is active for responding */
                        /* to foreground events */	   
















#ifdef HAVE_PTYTRAP
    char *slave_name;   /* Full name of slave, i.e., /dev/ttyp0 */
#endif /* HAVE_PTYTRAP */
    /* may go away */


    int leaveopen;	/* If we should not call Tcl's close when we close - */
                        /* only relevant if Tcl does the original open */

    Tcl_Interp *bg_interp;	/* interp to process the bg cases */
    int bg_ecount;		/* number of background ecases */
    enum {
	blocked,	/* blocked because we are processing the */
			/* file handler */
	armed,		/* normal state when bg handler in use */
	unarmed,	/* no bg handler in use */
	disarm_req_while_blocked	/* while blocked, a request */
				/* was received to disarm it.  Rather than */
				/* processing the request immediately, defer */
				/* it so that when we later try to unblock */
				/* we will see at that time that it should */
				/* instead be disarmed */
    } bg_status;

    /*
     * If the channel is freed while in the middle of a bg event handler,
     * remember that and defer freeing of the ExpState structure until
     * it is safe.
     */
    int freeWhenBgHandlerUnblocked;

    /* If channel is closed but not yet waited on, we tie up the fd by
     * attaching it to /dev/null.  We play this little game so that we
     * can embed the fd in the channel name.  If we didn't tie up the
     * fd, we'd get channel name collisions.  I'd consider naming the
     * channels independently of the fd, but this makes debugging easier.
     */
    int fdBusy;

    /* 
     * stdinout and stderr never go away so that our internal refs to them
     * don't have to be invalidated.  Having to worry about invalidating them
     * would be a major pain.  */
    int keepForever;

    /*  Remember that "reserved" esPtrs are no longer in use. */
    int valid;
    
    struct ExpState *nextPtr;	/* Pointer to next file in list of all
				 * file channels. */
} ExpState;

#define EXP_SPAWN_ID_BAD	((ExpState *)0)

#define EXP_TIME_INFINITY	-1


extern Tcl_ChannelType expChannelType;

#define EXP_TEMPORARY	1	/* expect */
#define EXP_PERMANENT	2	/* expect_after, expect_before, expect_bg */

#define EXP_DIRECT	1
#define EXP_INDIRECT	2




EXTERN void		expAdjust _ANSI_ARGS_((ExpState *));
EXTERN void		exp_buffer_shuffle _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,char *,char *));
EXTERN int		exp_close _ANSI_ARGS_((Tcl_Interp *,ExpState *));
EXTERN void		exp_close_all _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_ecmd_remove_fd_direct_and_indirect 
				_ANSI_ARGS_((Tcl_Interp *,int));
EXTERN void		exp_trap_on _ANSI_ARGS_((int));
EXTERN int		exp_trap_off _ANSI_ARGS_((char *));

EXTERN void		exp_strftime();
253
254
255
256
257
258
259
260
261
262

263
264


265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
				/* stack with no trace */

EXTERN void		exp_init_pty _ANSI_ARGS_((void));
EXTERN void		exp_pty_exit _ANSI_ARGS_((void));
EXTERN void		exp_init_tty _ANSI_ARGS_((void));
EXTERN void		exp_init_stdio _ANSI_ARGS_((void));
/*EXTERN void		exp_init_expect _ANSI_ARGS_((Tcl_Interp *));*/
EXTERN void		exp_init_spawn_ids _ANSI_ARGS_((void));
EXTERN void		exp_init_spawn_id_vars _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_trap _ANSI_ARGS_((void));

EXTERN void		exp_init_unit_random _ANSI_ARGS_((void));
EXTERN void		exp_init_sig _ANSI_ARGS_((void));



EXTERN int		exp_tcl2_returnvalue _ANSI_ARGS_((int));
EXTERN int		exp_2tcl_returnvalue _ANSI_ARGS_((int));

EXTERN void		exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp *));
EXTERN int		exp_string_to_signal _ANSI_ARGS_((Tcl_Interp *,char *));

EXTERN char *exp_onexit_action;

#define exp_new(x)	(x *)malloc(sizeof(x))

struct exp_fd_list {
	int fd;
	struct exp_fd_list *next;
};

/* describes a -i flag */
struct exp_i {
	int cmdtype;	/* EXP_CMD_XXX.  When an indirect update is */
			/* triggered by Tcl, this helps tell us in what */
			/* exp_i list to look in. */







|


>


>
>











|
|
|







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
				/* stack with no trace */

EXTERN void		exp_init_pty _ANSI_ARGS_((void));
EXTERN void		exp_pty_exit _ANSI_ARGS_((void));
EXTERN void		exp_init_tty _ANSI_ARGS_((void));
EXTERN void		exp_init_stdio _ANSI_ARGS_((void));
/*EXTERN void		exp_init_expect _ANSI_ARGS_((Tcl_Interp *));*/
EXTERN void		exp_init_spawn_ids _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_spawn_id_vars _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_trap _ANSI_ARGS_((void));
EXTERN void		exp_init_send _ANSI_ARGS_((void));
EXTERN void		exp_init_unit_random _ANSI_ARGS_((void));
EXTERN void		exp_init_sig _ANSI_ARGS_((void));
EXTERN void		expChannelInit _ANSI_ARGS_((void));
EXTERN int		expChannelCountGet _ANSI_ARGS_((void));

EXTERN int		exp_tcl2_returnvalue _ANSI_ARGS_((int));
EXTERN int		exp_2tcl_returnvalue _ANSI_ARGS_((int));

EXTERN void		exp_rearm_sigchld _ANSI_ARGS_((Tcl_Interp *));
EXTERN int		exp_string_to_signal _ANSI_ARGS_((Tcl_Interp *,char *));

EXTERN char *exp_onexit_action;

#define exp_new(x)	(x *)malloc(sizeof(x))

struct exp_state_list {
	ExpState *esPtr;
	struct exp_state_list *next;
};

/* describes a -i flag */
struct exp_i {
	int cmdtype;	/* EXP_CMD_XXX.  When an indirect update is */
			/* triggered by Tcl, this helps tell us in what */
			/* exp_i list to look in. */
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350


















			/* over time.  If type == direct, this is  the */
			/* cached value of variable use this to tell if it */
			/* has changed or not, and ergo whether it's */
			/* necessary to reparse. */

	int ecount;	/* # of ecases this is used by */

	struct exp_fd_list *fd_list;
	struct exp_i *next;
};

EXTERN struct exp_i *	exp_new_i_complex _ANSI_ARGS_((Tcl_Interp *,
					char *, int, Tcl_VarTraceProc *));
EXTERN struct exp_i *	exp_new_i_simple _ANSI_ARGS_((int,int));
EXTERN struct exp_fd_list *exp_new_fd _ANSI_ARGS_((int));
EXTERN void		exp_free_i _ANSI_ARGS_((Tcl_Interp *,struct exp_i *,
					Tcl_VarTraceProc *));
EXTERN void		exp_free_fd _ANSI_ARGS_((struct exp_fd_list *));
EXTERN void		exp_free_fd_single _ANSI_ARGS_((struct exp_fd_list *));
EXTERN void		exp_i_update _ANSI_ARGS_((Tcl_Interp *,
					struct exp_i *));

/*
 * definitions for creating commands
 */

#define EXP_NOPREFIX	1	/* don't define with "exp_" prefix */
#define EXP_REDEFINE	2	/* stomp on old commands with same name */

/* a hack for easily supporting both Tcl 7 and 8 CreateCommand/Obj split */
/* Can be discarded with Tcl 7 is. */
#if TCL_MAJOR_VERSION < 8
#define exp_proc(cmdproc) cmdproc
#else
#define exp_proc(cmdproc) 0, cmdproc
#endif

struct exp_cmd_data {
	char		*name;
#if TCL_MAJOR_VERSION >= 8
	Tcl_ObjCmdProc	*objproc;
#endif
	Tcl_CmdProc	*proc;
	ClientData	data;
	int 		flags;
};

EXTERN void		exp_create_commands _ANSI_ARGS_((Tcl_Interp *,
						struct exp_cmd_data *));
EXTERN void		exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_expect_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_interact_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_tty_cmds();


























|





|
|


|
|
|









<
<
<
<
<

<



<

<














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275





276

277
278
279

280

281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
			/* over time.  If type == direct, this is  the */
			/* cached value of variable use this to tell if it */
			/* has changed or not, and ergo whether it's */
			/* necessary to reparse. */

	int ecount;	/* # of ecases this is used by */

	struct exp_state_list *state_list;
	struct exp_i *next;
};

EXTERN struct exp_i *	exp_new_i_complex _ANSI_ARGS_((Tcl_Interp *,
					char *, int, Tcl_VarTraceProc *));
EXTERN struct exp_i *	exp_new_i_simple _ANSI_ARGS_((ExpState *,int));
EXTERN struct exp_state_list *exp_new_state _ANSI_ARGS_((ExpState *));
EXTERN void		exp_free_i _ANSI_ARGS_((Tcl_Interp *,struct exp_i *,
					Tcl_VarTraceProc *));
EXTERN void		exp_free_state _ANSI_ARGS_((struct exp_state_list *));
EXTERN void		exp_free_state_single _ANSI_ARGS_((struct exp_state_list *));
EXTERN int		exp_i_update _ANSI_ARGS_((Tcl_Interp *,
					struct exp_i *));

/*
 * definitions for creating commands
 */

#define EXP_NOPREFIX	1	/* don't define with "exp_" prefix */
#define EXP_REDEFINE	2	/* stomp on old commands with same name */






#define exp_proc(cmdproc) 0, cmdproc


struct exp_cmd_data {
	char		*name;

	Tcl_ObjCmdProc	*objproc;

	Tcl_CmdProc	*proc;
	ClientData	data;
	int 		flags;
};

EXTERN void		exp_create_commands _ANSI_ARGS_((Tcl_Interp *,
						struct exp_cmd_data *));
EXTERN void		exp_init_main_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_expect_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_most_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_trap_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_interact_cmds _ANSI_ARGS_((Tcl_Interp *));
EXTERN void		exp_init_tty_cmds();

EXTERN ExpState *	expStateCheck _ANSI_ARGS_((Tcl_Interp *,ExpState *,int,int,char *));
EXTERN ExpState *       expStateCurrent _ANSI_ARGS_((Tcl_Interp *,int,int,int));
EXTERN ExpState *       expStateFromChannelName _ANSI_ARGS_((Tcl_Interp *,char *,int,int,int,char *));
EXTERN void		expStateFree _ANSI_ARGS_((ExpState *));

EXTERN ExpState *	expCreateChannel _ANSI_ARGS_((Tcl_Interp *,int,int,int));
EXTERN ExpState *	expWaitOnAny _ANSI_ARGS_((void));
EXTERN ExpState *	expWaitOnOne _ANSI_ARGS_((void));
EXTERN void		expExpectVarsInit _ANSI_ARGS_((void));
EXTERN int		expStateAnyIs _ANSI_ARGS_((ExpState *));
EXTERN int		expDevttyIs _ANSI_ARGS_((ExpState *));
EXTERN int		expStdinOutIs _ANSI_ARGS_((ExpState *));
EXTERN ExpState *	expStdinoutGet _ANSI_ARGS_((void));
EXTERN ExpState *	expDevttyGet _ANSI_ARGS_((void));

/* generic functions that really should be provided by Tcl */
EXTERN int		expSizeGet _ANSI_ARGS_((ExpState *));
EXTERN int		expSizeZero _ANSI_ARGS_((ExpState *));

Changes to exp_console.c.

29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif

#include "tcl.h"
#include "exp_rename.h"
#include "exp_prog.h"

#include "exp_log.h"

static void
exp_console_manipulation_failed(s)
char *s;
{
	exp_errorlog("expect: spawn: cannot %s console, check permissions of /dev/console\n",s);
	exit(-1);
}

void
exp_console_set()
{
#ifdef SRIOCSREDIR
	int fd;







>






|
|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif

#include "tcl.h"
#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"

static void
exp_console_manipulation_failed(s)
char *s;
{
    expErrorLog("expect: spawn: cannot %s console, check permissions of /dev/console\n",s);
    exit(-1);
}

void
exp_console_set()
{
#ifdef SRIOCSREDIR
	int fd;

Changes to exp_event.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214

215
216


217
218
219
220



221
222
223
224
225
226
227
228
229
230
231
232
233

234

235
236
237
238
239
240
241
242
243
244






245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267








268
269










270












271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453



454
455
/* exp_event.c - event interface for Expect

Written by: Don Libes, NIST, 2/6/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.

*/

/* Notes:
I'm only a little worried because Tk does not check for errno == EBADF
after calling select.  I imagine that if the user passes in a bad file
descriptor, we'll never get called back, and thus, we'll hang forever
- it would be better to at least issue a diagnostic to the user.

Another possible problem: Tk does not do file callbacks round-robin.

Another possible problem: Calling Create/DeleteFileHandler
before/after every Tcl_Eval... in expect/interact could be very
expensive.

*/


#include "expect_cf.h"
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_PTYTRAP
#  include <sys/ptyio.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for struct exp_f defs */
#include "exp_event.h"

/* Tcl_DoOneEvent will call our filehandler which will set the following */
/* vars enabling us to know where and what kind of I/O we can do */
/*#define EXP_SPAWN_ID_BAD	-1*/
/*#define EXP_SPAWN_ID_TIMEOUT	-2*/	/* really indicates a timeout */

static int ready_fd = EXP_SPAWN_ID_BAD;
static int ready_mask;
static int default_mask = TCL_READABLE | TCL_EXCEPTION;


void
exp_event_disarm(fd)
int fd;
{
#if TCL_MAJOR_VERSION < 8
	Tcl_DeleteFileHandler(exp_fs[fd].Master);
#else
	Tcl_DeleteFileHandler(fd);
#endif

	/* remember that filehandler has been disabled so that */
	/* it can be turned on for fg expect's as well as bg */
	exp_fs[fd].fg_armed = FALSE;
}

void
exp_event_disarm_fast(fd,filehandler)
int fd;
Tcl_FileProc *filehandler;
{
	/* Temporarily delete the filehandler by assigning it a mask */
	/* that permits no events! */
	/* This reduces the calls to malloc/free inside Tcl_...FileHandler */
	/* Tk insists on having a valid proc here even though it isn't used */
#if TCL_MAJOR_VERSION < 8
	Tcl_CreateFileHandler(exp_fs[fd].Master,0,filehandler,(ClientData)0);
#else
	Tcl_CreateFileHandler(fd,0,filehandler,(ClientData)0);
#endif

	/* remember that filehandler has been disabled so that */
	/* it can be turned on for fg expect's as well as bg */
	exp_fs[fd].fg_armed = FALSE;
}

static void
exp_arm_background_filehandler_force(m)
int m;
{
#if TCL_MAJOR_VERSION < 8
	Tcl_CreateFileHandler(exp_fs[m].Master,
#else
	Tcl_CreateFileHandler(m,
#endif
		TCL_READABLE|TCL_EXCEPTION,
		exp_background_filehandler,
		(ClientData)(exp_fs[m].fd_ptr));

	exp_fs[m].bg_status = armed;
}

void
exp_arm_background_filehandler(m)
int m;

{
	switch (exp_fs[m].bg_status) {
	case unarmed:
		exp_arm_background_filehandler_force(m);
		break;
	case disarm_req_while_blocked:
		exp_fs[m].bg_status = blocked;	/* forget request */
		break;
	case armed:
	case blocked:
		/* do nothing */
		break;
	}
}

void
exp_disarm_background_filehandler(m)
int m;
{
	switch (exp_fs[m].bg_status) {
	case blocked:
		exp_fs[m].bg_status = disarm_req_while_blocked;
		break;
	case armed:
		exp_fs[m].bg_status = unarmed;
		exp_event_disarm(m);
		break;
	case disarm_req_while_blocked:
	case unarmed:
		/* do nothing */
		break;
	}
}

/* ignore block status and forcibly disarm handler - called from exp_close. */
/* After exp_close returns, we will not have an opportunity to disarm */
/* because the fd will be invalid, so we force it here. */
void
exp_disarm_background_filehandler_force(m)
int m;
{
	switch (exp_fs[m].bg_status) {
	case blocked:
	case disarm_req_while_blocked:
	case armed:
		exp_fs[m].bg_status = unarmed;
		exp_event_disarm(m);
		break;
	case unarmed:
		/* do nothing */
		break;
	}
}

/* this can only be called at the end of the bg handler in which */
/* case we know the status is some kind of "blocked" */
void
exp_unblock_background_filehandler(m)
int m;
{
	switch (exp_fs[m].bg_status) {
	case blocked:
		exp_arm_background_filehandler_force(m);
		break;
	case disarm_req_while_blocked:
		exp_disarm_background_filehandler_force(m);
		break;
	}
}

/* this can only be called at the beginning of the bg handler in which */
/* case we know the status must be "armed" */
void
exp_block_background_filehandler(m)
int m;
{
	exp_fs[m].bg_status = blocked;
	exp_event_disarm_fast(m,exp_background_filehandler);
}


/*ARGSUSED*/
static void
exp_timehandler(clientData)
ClientData clientData;
{
	*(int *)clientData = TRUE;	
}

static void exp_filehandler(clientData,mask)
ClientData clientData;
int mask;
{
	/* if input appears, record the fd on which it appeared */

	ready_fd = *(int *)clientData;
	ready_mask = mask;

	exp_event_disarm_fast(ready_fd,exp_filehandler);

#if 0
	if (ready_fd == *(int *)clientData) {
		/* if input appears from an fd which we've already heard */
		/* forcibly tell it to shut up.  We could also shut up */
		/* every instance, but it is more efficient to leave the */
		/* fd enabled with the belief that we may rearm soon enough */
		/* anyway. */


		exp_event_disarm_fast(ready_fd,exp_filehandler);
	} else {


		ready_fd = *(int *)clientData;
		ready_mask = mask;
	}
#endif



}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/* can now return RECONFIGURE, too */
/*ARGSUSED*/
int exp_get_next_event(interp,masters, n,master_out,timeout,key)
Tcl_Interp *interp;
int *masters;
int n;			/* # of masters */
int *master_out;	/* 1st ready master, not set if none */
int timeout;		/* seconds */
int key;
{

	static rr = 0;	/* round robin ptr */

	int i;	/* index into in-array */
#ifdef HAVE_PTYTRAP
	struct request_info ioctl_info;
#endif

	int old_configure_count = exp_configure_count;

	int timer_created = FALSE;
	int timer_fired = FALSE;
	Tcl_TimerToken timetoken;/* handle to Tcl timehandler descriptor */







	for (;;) {
		int m;
		struct exp_f *f;


		/* if anything has been touched by someone else, report that */
		/* an event has been received */

		for (i=0;i<n;i++) {
			rr++;
			if (rr >= n) rr = 0;

			m = masters[rr];
			f = exp_fs + m;

			if (f->key != key) {
				f->key = key;
				f->force_read = FALSE;
				*master_out = m;
				return(EXP_DATA_OLD);
			} else if ((!f->force_read) && (f->size != 0)) {
				*master_out = m;
				return(EXP_DATA_OLD);








			}
		}























		if (!timer_created) {
			if (timeout >= 0) {
				timetoken = Tcl_CreateTimerHandler(1000*timeout,
						exp_timehandler,
						(ClientData)&timer_fired);
				timer_created = TRUE;
			}
		}

		for (;;) {
			int j;

			/* make sure that all fds that should be armed are */
			for (j=0;j<n;j++) {
				int k = masters[j];

				if (!exp_fs[k].fg_armed) {

					Tcl_CreateFileHandler(
#if TCL_MAJOR_VERSION < 8
					     exp_fs[k].Master,
#else
					     k,
#endif
					     default_mask,

					     exp_filehandler,
					     (ClientData)exp_fs[k].fd_ptr);
					exp_fs[k].fg_armed = TRUE;
				}
			}

			Tcl_DoOneEvent(0);	/* do any event */

			if (timer_fired) return(EXP_TIMEOUT);

			if (old_configure_count != exp_configure_count) {
				if (timer_created)
					Tcl_DeleteTimerHandler(timetoken);
				return EXP_RECONFIGURE;
			}

			if (ready_fd == EXP_SPAWN_ID_BAD) continue;

			/* if it was from something we're not looking for at */
			/* the moment, ignore it */
			for (j=0;j<n;j++) {
				if (ready_fd == masters[j]) goto found;
			}

			/* not found */
			exp_event_disarm_fast(ready_fd,exp_filehandler);
			ready_fd = EXP_SPAWN_ID_BAD;
			continue;
		found:
			*master_out = ready_fd;
			ready_fd = EXP_SPAWN_ID_BAD;

			/* this test should be redundant but SunOS */
			/* raises both READABLE and EXCEPTION (for no */
			/* apparent reason) when selecting on a plain file */
			if (ready_mask & TCL_READABLE) {
				if (timer_created) Tcl_DeleteTimerHandler(timetoken);
				return EXP_DATA_NEW;
			}

			/* ready_mask must contain TCL_EXCEPTION */
#ifndef HAVE_PTYTRAP
			if (timer_created) Tcl_DeleteTimerHandler(timetoken);
			return(EXP_EOF);
#else
			if (ioctl(*master_out,TIOCREQCHECK,&ioctl_info) < 0) {
				exp_debuglog("ioctl error on TIOCREQCHECK: %s", Tcl_PosixError(interp));
				if (timer_created) Tcl_DeleteTimerHandler(timetoken);
				return(EXP_TCLERROR);
			}
			if (ioctl_info.request == TIOCCLOSE) {
				if (timer_created) Tcl_DeleteTimerHandler(timetoken);
				return(EXP_EOF);
			}
			if (ioctl(*master_out, TIOCREQSET, &ioctl_info) < 0) {
				exp_debuglog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
			}
			/* presumably, we trapped an open here */
			continue;
#endif /* !HAVE_PTYTRAP */
		}
	}
}

/* Having been told there was an event for a specific fd, get it */
/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event_info(interp,fd,ready_mask)
Tcl_Interp *interp;
int fd;
int ready_mask;

{
#ifdef HAVE_PTYTRAP
	struct request_info ioctl_info;
#endif

	if (ready_mask & TCL_READABLE) return EXP_DATA_NEW;

	/* ready_mask must contain TCL_EXCEPTION */

#ifndef HAVE_PTYTRAP
	return(EXP_EOF);
#else
	if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) {
		exp_debuglog("ioctl error on TIOCREQCHECK: %s",
				Tcl_PosixError(interp));
		return(EXP_TCLERROR);
	}
	if (ioctl_info.request == TIOCCLOSE) {
		return(EXP_EOF);
	}
	if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) {
		exp_debuglog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
	}
	/* presumably, we trapped an open here */
	/* call it an error for lack of anything more descriptive */
	/* it will be thrown away by caller anyway */
	return EXP_TCLERROR;
#endif
}

/*ARGSUSED*/
int	/* returns TCL_XXX */
exp_dsleep(interp,sec)
Tcl_Interp *interp;
double sec;
{
	int timer_fired = FALSE;

	Tcl_CreateTimerHandler((int)(sec*1000),exp_timehandler,(ClientData)&timer_fired);

	while (1) {
		Tcl_DoOneEvent(0);
		if (timer_fired) return TCL_OK;

		if (ready_fd == EXP_SPAWN_ID_BAD) continue;

		exp_event_disarm_fast(ready_fd,exp_filehandler);
		ready_fd = EXP_SPAWN_ID_BAD;
	}
}

#if 0
/*ARGSUSED*/
int	/* returns TCL_XXX */
exp_usleep(interp,usec)
Tcl_Interp *interp;
long usec;
{
	int timer_fired = FALSE;

	Tcl_CreateTimerHandler(usec/1000,exp_timehandler,(ClientData)&timer_fired);

	while (1) {
		Tcl_DoOneEvent(0);
		if (timer_fired) return TCL_OK;

		if (ready_fd == EXP_SPAWN_ID_BAD) continue;

		exp_event_disarm_fast(ready_fd,exp_filehandler);
		ready_fd = EXP_SPAWN_ID_BAD;
	}
}
#endif

static char destroy_cmd[] = "destroy .";

static void
exp_event_exit_real(interp)
Tcl_Interp *interp;
{
	Tcl_Eval(interp,destroy_cmd);
}

/* set things up for later calls to event handler */
void
exp_init_event()
{



	exp_event_exit = exp_event_exit_real;
}




<
|
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|


<
<
<
<
|
<
<
<
|
|
<
<
<
|
<
<
<
<
<
|
<
<
<
|
<

|
<
|

<
<
<
<
<
<
<
<
<
|
<
<
<



|
|

<
<
<
|
<
|
|
|

|



|
<
>

|

|
|

|
|


|
|
|



|
|

|

|
|

|
|
|


|
|
|






|
|

|



|
|
|

|
|
|





|
|

|

|
|

|
|
|





|
|

|
|








|


|



|

|
|
>
|
|
<
<
<
<
<
<
<

>
|
|
>
>
|
<
|
<
>
>
>





|

|
|
|



>
|
>
|

|


|

<
|
|
>
>
>
>
>
>
|
<
<
<

>
|
|

|
|
|

<
|

|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
<
|
|

<
<
<
|
|
<
|
|
>
|
<
<
|
<
<
<
>
|
|
|
|
|

|
|
|
|
|
<
<
|
|
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|


|

<
<
>


|


|

|
<

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|









|

|

|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<







|






>
>
>
|

1
2
3
4

5
6
7
8















9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27




28



29
30



31





32



33

34
35

36
37









38



39
40
41
42
43
44



45

46
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155







156
157
158
159
160
161
162

163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
198



199
200
201
202
203
204
205
206
207

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257



258
259

260
261
262
263


264



265
266
267
268
269
270
271
272
273
274
275
276


277
278
279

280




281









































282
283
284
285
286
287


288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329

330




















331
332







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/* exp_event.c - event interface for Expect

Written by: Don Libes, NIST, 2/6/90


I hereby place this software in the public domain.  However, the author and
NIST would appreciate credit if this program or parts of it are used.

*/
















#include "expect_cf.h"
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_PTYTRAP
#  include <sys/ptyio.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for ExpState defs */
#include "exp_event.h"





typedef struct ThreadSpecificData {



    int rr;		/* round robin ptr */
} ThreadSpecificData;









static Tcl_ThreadDataKey dataKey;





void
exp_event_disarm_bg(esPtr)

ExpState *esPtr;
{









    Tcl_DeleteChannelHandler(esPtr->channel,exp_background_channelhandler,(ClientData)esPtr);



}

static void
exp_arm_background_channelhandler_force(esPtr)
ExpState *esPtr;
{



    Tcl_CreateChannelHandler(esPtr->channel,

	    TCL_READABLE|TCL_EXCEPTION,
	    exp_background_channelhandler,
	    (ClientData)esPtr);

    esPtr->bg_status = armed;
}

void
exp_arm_background_channelhandler(esPtr)

ExpState *esPtr;
{
    switch (esPtr->bg_status) {
	case unarmed:
	    exp_arm_background_channelhandler_force(esPtr);
	    break;
	case disarm_req_while_blocked:
	    esPtr->bg_status = blocked;	/* forget request */
	    break;
	case armed:
	case blocked:
	    /* do nothing */
	    break;
    }
}

void
exp_disarm_background_channelhandler(esPtr)
ExpState *esPtr;
{
    switch (esPtr->bg_status) {
	case blocked:
	    esPtr->bg_status = disarm_req_while_blocked;
	    break;
	case armed:
	    esPtr->bg_status = unarmed;
	    exp_event_disarm_bg(esPtr);
	    break;
	case disarm_req_while_blocked:
	case unarmed:
	    /* do nothing */
	    break;
    }
}

/* ignore block status and forcibly disarm handler - called from exp_close. */
/* After exp_close returns, we will not have an opportunity to disarm */
/* because the fd will be invalid, so we force it here. */
void
exp_disarm_background_channelhandler_force(esPtr)
ExpState *esPtr;
{
    switch (esPtr->bg_status) {
	case blocked:
	case disarm_req_while_blocked:
	case armed:
	    esPtr->bg_status = unarmed;
	    exp_event_disarm_bg(esPtr);
	    break;
	case unarmed:
	    /* do nothing */
	    break;
    }
}

/* this can only be called at the end of the bg handler in which */
/* case we know the status is some kind of "blocked" */
void
exp_unblock_background_channelhandler(esPtr)
    ExpState *esPtr;
{
    switch (esPtr->bg_status) {
	case blocked:
	    exp_arm_background_channelhandler_force(esPtr);
	    break;
	case disarm_req_while_blocked:
	    exp_disarm_background_channelhandler_force(esPtr);
	    break;
    }
}

/* this can only be called at the beginning of the bg handler in which */
/* case we know the status must be "armed" */
void
exp_block_background_channelhandler(esPtr)
ExpState *esPtr;
{
    esPtr->bg_status = blocked;
    exp_event_disarm_bg(esPtr);
}


/*ARGSUSED*/
static void
exp_timehandler(clientData)
ClientData clientData;
{
    *(int *)clientData = TRUE;	
}

static void exp_channelhandler(clientData,mask)
ClientData clientData;
int mask;
{
    ExpState *esPtr = (ExpState *)clientData;

    esPtr->notified = TRUE;
    esPtr->notifiedMask = mask;

    exp_event_disarm_fg(esPtr);
}








void
exp_event_disarm_fg(esPtr)
ExpState *esPtr;
{
    /*printf("DeleteChannelHandler: %s\r\n",esPtr->name);*/
    Tcl_DeleteChannelHandler(esPtr->channel,exp_channelhandler,(ClientData)esPtr);



    /* remember that ChannelHandler has been disabled so that */
    /* it can be turned on for fg expect's as well as bg */
    esPtr->fg_armed = FALSE;
}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/* can now return RECONFIGURE, too */
/*ARGSUSED*/
int exp_get_next_event(interp,esPtrs,n,esPtrOut,timeout,key)
Tcl_Interp *interp;
ExpState *(esPtrs[]);
int n;			/* # of esPtrs */
ExpState **esPtrOut;	/* 1st ready esPtr, not set if none */
int timeout;		/* seconds */
int key;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    ExpState *esPtr;
    int i;	/* index into in-array */
#ifdef HAVE_PTYTRAP
    struct request_info ioctl_info;
#endif

    int old_configure_count = exp_configure_count;


    int timerFired = FALSE;
    Tcl_TimerToken timerToken = 0;/* handle to Tcl timehandler descriptor */
    /* We must delete any timer before returning.  Doing so throughout
     * the code makes it unreadable; isolate the unreadable nonsense here.
     */
#define RETURN(x) { \
	if (timerToken) Tcl_DeleteTimerHandler(timerToken); \
	return(x); \
    }




    for (;;) {
	/* if anything has been touched by someone else, report that */
	/* an event has been received */

	for (i=0;i<n;i++) {
	    tsdPtr->rr++;
	    if (tsdPtr->rr >= n) tsdPtr->rr = 0;


	    esPtr = esPtrs[tsdPtr->rr];

	    if (esPtr->key != key) {
		esPtr->key = key;
		esPtr->force_read = FALSE;
		*esPtrOut = esPtr;
		RETURN(EXP_DATA_OLD);
	    } else if ((!esPtr->force_read) && (!expSizeZero(esPtr))) {
		*esPtrOut = esPtr;
		RETURN(EXP_DATA_OLD);
	    } else if (esPtr->notified) {
		/* this test of the mask should be redundant but SunOS */
		/* raises both READABLE and EXCEPTION (for no */
		/* apparent reason) when selecting on a plain file */
		if (esPtr->notifiedMask & TCL_READABLE) {
		    *esPtrOut = esPtr;
		    esPtr->notified = FALSE;
		    RETURN(EXP_DATA_NEW);
		}

		/*
		 * at this point we know that the event must be TCL_EXCEPTION
		 * indicating either EOF or HP ptytrap.
		 */
#ifndef HAVE_PTYTRAP
		RETURN(EXP_EOF);
#else
		if (ioctl(esPtr->fdin,TIOCREQCHECK,&ioctl_info) < 0) {
		    expDiagLog("ioctl error on TIOCREQCHECK: %s", Tcl_PosixError(interp));
		    RETURN(EXP_TCLERROR);
		}
		if (ioctl_info.request == TIOCCLOSE) {
		    RETURN(EXP_EOF);
		}
		if (ioctl(esPtr->fdin, TIOCREQSET, &ioctl_info) < 0) {
		    expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
		}
		/* presumably, we trapped an open here */
		/* so simply continue by falling thru */
#endif /* !HAVE_PTYTRAP */
	    }
	}

	if (!timerToken) {
	    if (timeout >= 0) {
		timerToken = Tcl_CreateTimerHandler(1000*timeout,
			exp_timehandler,
			(ClientData)&timerFired);

	    }
	}




	/* make sure that all fds that should be armed are */
	for (i=0;i<n;i++) {

	    esPtr = esPtrs[i];
	    if (!esPtr->fg_armed) {
		/*printf("CreateChannelHandler: %s\r\n",esPtr->name);*/
		Tcl_CreateChannelHandler(


					 esPtr->channel,



					 TCL_READABLE | TCL_EXCEPTION,
					 exp_channelhandler,
					 (ClientData)esPtr);
		esPtr->fg_armed = TRUE;
	    }
	}

	Tcl_DoOneEvent(0);	/* do any event */
	
	if (timerFired) return(EXP_TIMEOUT);
	
	if (old_configure_count != exp_configure_count) {


	    RETURN(EXP_RECONFIGURE);
	}
    }

}














































/* Having been told there was an event for a specific ExpState, get it */
/* This returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event_info(interp,esPtr)
Tcl_Interp *interp;


ExpState *esPtr;
{
#ifdef HAVE_PTYTRAP
    struct request_info ioctl_info;
#endif

    if (esPtr->notifiedMask & TCL_READABLE) return EXP_DATA_NEW;

    /* ready_mask must contain TCL_EXCEPTION */

#ifndef HAVE_PTYTRAP
    return(EXP_EOF);
#else
    if (ioctl(esPtr->fdin,TIOCREQCHECK,&ioctl_info) < 0) {
	expDiagLog("ioctl error on TIOCREQCHECK: %s",
		Tcl_PosixError(interp));
	return(EXP_TCLERROR);
    }
    if (ioctl_info.request == TIOCCLOSE) {
	return(EXP_EOF);
    }
    if (ioctl(esPtr->fdin, TIOCREQSET, &ioctl_info) < 0) {
	expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
    }
    /* presumably, we trapped an open here */
    /* call it an error for lack of anything more descriptive */
    /* it will be thrown away by caller anyway */
    return EXP_TCLERROR;
#endif
}

/*ARGSUSED*/
int	/* returns TCL_XXX */
exp_dsleep(interp,sec)
Tcl_Interp *interp;
double sec;
{
    int timerFired = FALSE;

    Tcl_CreateTimerHandler((int)(sec*1000),exp_timehandler,(ClientData)&timerFired);

    while (!timerFired) {
	Tcl_DoOneEvent(0);

    }




















    return TCL_OK;
}








static char destroy_cmd[] = "destroy .";

static void
exp_event_exit_real(interp)
Tcl_Interp *interp;
{
    Tcl_Eval(interp,destroy_cmd);
}

/* set things up for later calls to event handler */
void
exp_init_event()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->rr = 0;

    exp_event_exit = exp_event_exit_real;
}

Changes to exp_event.h.

1
2
3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
/* exp_event.h - event definitions */

int exp_get_next_event _ANSI_ARGS_((Tcl_Interp *,int *, int, int *, int, int));
int exp_get_next_event_info _ANSI_ARGS_((Tcl_Interp *, int, int));
int exp_dsleep _ANSI_ARGS_((Tcl_Interp *, double));
void exp_init_event _ANSI_ARGS_((void));

extern void (*exp_event_exit) _ANSI_ARGS_((Tcl_Interp *));

void exp_event_disarm _ANSI_ARGS_((int));



void exp_arm_background_filehandler _ANSI_ARGS_((int));
void exp_disarm_background_filehandler _ANSI_ARGS_((int));
void exp_disarm_background_filehandler_force _ANSI_ARGS_((int));
void exp_unblock_background_filehandler _ANSI_ARGS_((int));
void exp_block_background_filehandler _ANSI_ARGS_((int));

void exp_background_filehandler _ANSI_ARGS_((ClientData,int));



|
|





|
>
>

|
|
|
|
|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* exp_event.h - event definitions */

int exp_get_next_event _ANSI_ARGS_((Tcl_Interp *,ExpState **, int, ExpState **, int, int));
int exp_get_next_event_info _ANSI_ARGS_((Tcl_Interp *, ExpState *));
int exp_dsleep _ANSI_ARGS_((Tcl_Interp *, double));
void exp_init_event _ANSI_ARGS_((void));

extern void (*exp_event_exit) _ANSI_ARGS_((Tcl_Interp *));

void exp_event_disarm _ANSI_ARGS_((ExpState *,Tcl_FileProc *));
void exp_event_disarm_bg _ANSI_ARGS_((ExpState *));
void exp_event_disarm_fg _ANSI_ARGS_((ExpState *));

void exp_arm_background_channelhandler _ANSI_ARGS_((ExpState *));
void exp_disarm_background_channelhandler _ANSI_ARGS_((ExpState *));
void exp_disarm_background_channelhandler_force _ANSI_ARGS_((ExpState *));
void exp_unblock_background_channelhandler _ANSI_ARGS_((ExpState *));
void exp_block_background_channelhandler _ANSI_ARGS_((ExpState *));

void exp_background_channelhandler _ANSI_ARGS_((ClientData,int));

Changes to exp_glob.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120



121
122
123
124
125
126
127

*/

#include "expect_cf.h"
#include "tcl.h"
#include "exp_int.h"

#if 0
/* The following functions implement expect's glob-style string matching */
/* Exp_StringMatch allow's implements the unanchored front (or conversely */
/* the '^') feature.  Exp_StringMatch2 does the rest of the work. */
int	/* returns # of chars that matched */
Exp_StringMatch(string, pattern,offset)
char *string;
char *pattern;
int *offset;	/* offset from beginning of string where pattern matches */
{
	char *s;
	int sm;	/* count of chars matched or -1 */
	int caret = FALSE;

	*offset = 0;

	if (pattern[0] == '^') {
		caret = TRUE;
		pattern++;
	}

	sm = Exp_StringMatch2(string,pattern);
	if (sm >= 0) return(sm);

	if (caret) return(-1);

	if (pattern[0] == '*') return(-1);

	for (s = string;*s;s++) {
 		sm = Exp_StringMatch2(s,pattern);
		if (sm != -1) {
			*offset = s-string;
			return(sm);
		}
	}
	return(-1);
}
#endif

/* The following functions implement expect's glob-style string matching */
/* Exp_StringMatch allow's implements the unanchored front (or conversely */
/* the '^') feature.  Exp_StringMatch2 does the rest of the work. */
int	/* returns # of chars that matched */
Exp_StringMatch(string, pattern,offset)
char *string;
char *pattern;
int *offset;	/* offset from beginning of string where pattern matches */
{
	char *s;
	int sm;	/* count of chars matched or -1 */
	int caret = FALSE;
	int star = FALSE;

	*offset = 0;

	if (pattern[0] == '^') {
		caret = TRUE;
		pattern++;
	} else if (pattern[0] == '*') {
		star = TRUE;
	}

	/*
	 * test if pattern matches in initial position.
	 * This handles front-anchor and 1st iteration of non-front-anchor.
	 * Note that 1st iteration must be tried even if string is empty.
	 */

	sm = Exp_StringMatch2(string,pattern);
	if (sm >= 0) return(sm);

	if (caret) return -1;
	if (star) return -1;

	if (*string == '\0') return -1;

	for (s = string+1;*s;s++) {
 		sm = Exp_StringMatch2(s,pattern);
		if (sm != -1) {
			*offset = s-string;
			return(sm);
		}
	}
	return -1;
}

/* Exp_StringMatch2 --

Like Tcl_StringMatch except that
1) returns number of characters matched, -1 if failed.
	(Can return 0 on patterns like "" or "$")
2) does not require pattern to match to end of string
3) much of code is stolen from Tcl_StringMatch
4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor)
*/

int Exp_StringMatch2(string,pattern)
    register char *string;	/* String. */
    register char *pattern;	/* Pattern, which may contain
				 * special characters. */

{
    char c2;
    int match = 0;	/* # of chars matched */




    while (1) {
	/* If at end of pattern, success! */
	if (*pattern == 0) {
		return match;
	}








<



|
|


<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


|


















|







|
|








|

|







|



>

|
|
>
>
>







11
12
13
14
15
16
17

18
19
20
21
22
23
24





25
































26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

*/

#include "expect_cf.h"
#include "tcl.h"
#include "exp_int.h"


/* The following functions implement expect's glob-style string matching */
/* Exp_StringMatch allow's implements the unanchored front (or conversely */
/* the '^') feature.  Exp_StringMatch2 does the rest of the work. */
int	/* returns # of BYTES that matched */
Exp_StringCaseMatch(string, pattern, nocase, offset)		/* INTL */
char *string;
char *pattern;





int nocase;
































int *offset;	/* offset in bytes from beginning of string where pattern matches */
{
	char *s;
	int sm;	/* count of bytes matched or -1 */
	int caret = FALSE;
	int star = FALSE;

	*offset = 0;

	if (pattern[0] == '^') {
		caret = TRUE;
		pattern++;
	} else if (pattern[0] == '*') {
		star = TRUE;
	}

	/*
	 * test if pattern matches in initial position.
	 * This handles front-anchor and 1st iteration of non-front-anchor.
	 * Note that 1st iteration must be tried even if string is empty.
	 */

	sm = Exp_StringCaseMatch2(string,pattern, nocase);
	if (sm >= 0) return(sm);

	if (caret) return -1;
	if (star) return -1;

	if (*string == '\0') return -1;

	for (s = Tcl_UtfNext(string);*s;s = Tcl_UtfNext(s)) {
 		sm = Exp_StringCaseMatch2(s,pattern, nocase);
		if (sm != -1) {
			*offset = s-string;
			return(sm);
		}
	}
	return -1;
}

/* Exp_StringCaseMatch2 --

Like Tcl_StringCaseMatch except that
1) returns number of characters matched, -1 if failed.
	(Can return 0 on patterns like "" or "$")
2) does not require pattern to match to end of string
3) much of code is stolen from Tcl_StringMatch
4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor)
*/

int Exp_StringCaseMatch2(string,pattern, nocase)	/* INTL */
    register char *string;	/* String. */
    register char *pattern;	/* Pattern, which may contain
				 * special characters. */
    int nocase;
{
    Tcl_UniChar ch1, ch2;
    int match = 0;	/* # of bytes matched */
    char *oldString;

    char *pstart = pattern;

    while (1) {
	/* If at end of pattern, success! */
	if (*pattern == 0) {
		return match;
	}

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192




193
194
195
196
197
198
199
200


201



202
203
204
205
206
207

208
209
210
211
212
213
214
215

216





217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238


239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257




258
259
260
261
262
263
264

265
266
	/* Check for a "*" as the next pattern character.  It matches
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
	 * match or we reach the end of the string.
	 */
	
	if (*pattern == '*') {
#if 1
	    int head_len;
	    char *tail;
#endif
	    pattern += 1;
	    if (*pattern == 0) {
		return(strlen(string)+match); /* DEL */
	    }
#if 1
	    /* find longest match - switched to this on 12/31/93 */
	    head_len = strlen(string);	/* length before tail */
	    tail = string + head_len;
	    while (head_len >= 0) {
		int rc;

		if (-1 != (rc = Exp_StringMatch2(tail, pattern))) {
		    return rc + match + head_len;	/* DEL */



		}
		tail--;
		head_len--;
	    }
#else
	    /* find shortest match */
	    while (*string != 0) {
		int rc;					/* DEL */

		if (-1 != (rc = Exp_StringMatch2(string, pattern))) {
		    return rc+match;		/* DEL */
		}
		string += 1;
		match++;				/* DEL */
	    }
	    if (*pattern == '$') return 0;	/* handle *$ */
#endif
	    return -1;					/* DEL */
	}
    
	/*
	 * after this point, all patterns must match at least one
	 * character, so check this
	 */

	if (*string == 0) return -1;

	/* Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (*pattern == '?') {
	    goto thisCharOK;




	}

	/* Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (*pattern == '[') {


	    pattern += 1;



	    while (1) {
		if ((*pattern == ']') || (*pattern == 0)) {
		    return -1;			/* was 0; DEL */
		}
		if (*pattern == *string) {
		    break;

		}
		if (pattern[1] == '-') {
		    c2 = pattern[2];
		    if (c2 == 0) {
			return -1;		/* DEL */
		    }
		    if ((*pattern <= *string) && (c2 >= *string)) {
			break;

		    }





		    if ((*pattern >= *string) && (c2 <= *string)) {
			break;
		    }
		    pattern += 2;
		}
		pattern += 1;
	    }

/* OOPS! Found a bug in vanilla Tcl - have sent back to Ousterhout */
/* but he hasn't integrated it yet. - DEL */

#if 0
	    while ((*pattern != ']') && (*pattern != 0)) {
#else
	    while (*pattern != ']') {
		if (*pattern == 0) {
		    pattern--;
		    break;
	        }
#endif
		pattern += 1;
	    }


	    goto thisCharOK;
	}
    
	/* If the next pattern character is backslash, strip it off
	 * so we do exact matching on the character that follows.
	 */
	
	if (*pattern == '\\') {
	    pattern += 1;
	    if (*pattern == 0) {
		return -1;
	    }
	}

	/* There's no special character.  Just make sure that the next
	 * characters of each string match.
	 */
	
	if (*pattern != *string) {




	    return -1;
	}

	thisCharOK: pattern += 1;
	string += 1;
	match++;
    }

}








<
<

|




|
|
<
|
|


|
|
>
>
>

<
<
|
<
<
|
<
|
<
<
<
|
<

<
<















|
>
>
>
>








>
>
|
>
>
>

|


|
|
>

|
|
|


|
|
>

>
>
>
>
>
|


|
<
|
|
|
<
<
<
<
<
<

|
|

|
<
|

>
>
|

|















|
>
>
>
>
|
|
|
|
<
<
|
>
|
|
102
103
104
105
106
107
108


109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126


127


128

129



130

131


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194






195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


231
232
233
234
	/* Check for a "*" as the next pattern character.  It matches
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
	 * match or we reach the end of the string.
	 */
	
	if (*pattern == '*') {


	    char *tail;

	    pattern += 1;
	    if (*pattern == 0) {
		return(strlen(string)+match); /* DEL */
	    }

	    /* find LONGEST match */

	    tail = string + strlen(string);
	    while (1) {
		int rc;

		if (-1 != (rc = Exp_StringCaseMatch2(tail, pattern, nocase))) {
		    return match + (tail - string) + rc;
		    /* match = # of bytes we've skipped before this */
		    /* (...) = # of bytes we've skipped due to "*" */
		    /* rc    = # of bytes we've matched after "*" */
		}





		/* if we've backed up to beginning of string, give up */

		if (tail == string) break;



		tail = Tcl_UtfPrev(tail,string);

	    }


	    return -1;					/* DEL */
	}
    
	/*
	 * after this point, all patterns must match at least one
	 * character, so check this
	 */

	if (*string == 0) return -1;

	/* Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (*pattern == '?') {
	    pattern++;
	    oldString = string;
	    string = Tcl_UtfNext(string);
	    match += (string - oldString); /* incr by # of bytes in char */
	    continue;
	}

	/* Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (*pattern == '[') {
	    Tcl_UniChar ch, startChar, endChar;

	    pattern++;
	    oldString = string;
	    string += Tcl_UtfToUniChar(string, &ch);

	    while (1) {
		if ((*pattern == ']') || (*pattern == '\0')) {
		    return -1;			/* was 0; DEL */
		}
		pattern += Tcl_UtfToUniChar(pattern, &startChar);
		if (nocase) {
		    startChar = Tcl_UniCharToLower(startChar);
		}
		if (*pattern == '-') {
		    pattern++;
		    if (*pattern == '\0') {
			return -1;		/* DEL */
		    }
		    pattern += Tcl_UtfToUniChar(pattern, &endChar);
		    if (nocase) {
			endChar = Tcl_UniCharToLower(endChar);
		    }
		    if (((startChar <= ch) && (ch <= endChar))
			    || ((endChar <= ch) && (ch <= startChar))) {
			/*
			 * Matches ranges of form [a-z] or [z-a].
			 */

			break;
		    }
		} else if (startChar == ch) {

		    break;
		}
	    }






	    while (*pattern != ']') {
		if (*pattern == '\0') {
		    pattern = Tcl_UtfPrev(pattern, pstart);
		    break;
		}

		pattern = Tcl_UtfNext(pattern);
	    }
	    pattern++;
	    match += (string - oldString); /* incr by # of bytes in char */
	    continue;
	}
 
	/* If the next pattern character is backslash, strip it off
	 * so we do exact matching on the character that follows.
	 */
	
	if (*pattern == '\\') {
	    pattern += 1;
	    if (*pattern == 0) {
		return -1;
	    }
	}

	/* There's no special character.  Just make sure that the next
	 * characters of each string match.
	 */
	
	oldString = string;
	string  += Tcl_UtfToUniChar(string, &ch1);
	pattern += Tcl_UtfToUniChar(pattern, &ch2);
	if (nocase) {
	    if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
		return -1;
	    }
	} else if (ch1 != ch2) {
	    return -1;


	}
	match += (string - oldString);  /* incr by # of bytes in char */
    }
}

Changes to exp_int.h.

17
18
19
20
21
22
23
24
25
26





27
28
29
30
31
32
33

#ifndef HAVE_MEMCPY
#define memcpy(x,y,len) bcopy(y,x,len)
#endif

#include <errno.h>

int		Exp_StringMatch();
int		Exp_StringMatch2();
void		exp_console_set _ANSI_ARGS_((void));






#ifdef NO_STDLIB_H
#  include "../compat/stdlib.h"
#else
#  include <stdlib.h>		/* for malloc */
#endif /*NO_STDLIB_H*/








|
|
|
>
>
>
>
>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#ifndef HAVE_MEMCPY
#define memcpy(x,y,len) bcopy(y,x,len)
#endif

#include <errno.h>

void	exp_console_set     _ANSI_ARGS_((void));
void	expDiagLogPtrSet    _ANSI_ARGS_((void (*)_ANSI_ARGS_((char *))));
void	expDiagLogPtr       _ANSI_ARGS_((char *));
void	expDiagLogPtrX      _ANSI_ARGS_((char *,int));
void	expDiagLogPtrStr    _ANSI_ARGS_((char *,char *));
void	expDiagLogPtrStrStr _ANSI_ARGS_((char *,char *,char *));
void	expErrnoMsgSet      _ANSI_ARGS_((char * (*) _ANSI_ARGS_((int))));
char *	expErrnoMsg         _ANSI_ARGS_((int));

#ifdef NO_STDLIB_H
#  include "../compat/stdlib.h"
#else
#  include <stdlib.h>		/* for malloc */
#endif /*NO_STDLIB_H*/

Changes to exp_inter.c.

39
40
41
42
43
44
45
46
47

48
49

50
51
52
53
54





55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "string.h"

#include "exp_tty_in.h"
#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"
#include "exp_tstamp.h"	/* remove when timestamp stuff is gone */


#include "tclRegexp.h"
#include "exp_regexp.h"


extern char *TclGetRegError();
extern void TclRegError();

#define INTER_OUT "interact_out"






/*
 * tests if we are running this using a real tty
 *
 * these tests are currently only used to control what gets written to the
 * logfile.  Note that removal of the test of "..._is_tty" means that stdin
 * or stdout could be redirected and yet stdout would still be logged.
 * However, it's not clear why anyone would use log_file when these are
 * redirected in the first place.  On the other hand, it is reasonable to
 * run expect as a daemon in which case, stdin/out do not appear to be
 * ttys, yet it makes sense for them to be logged with log_file as if they
 * were.
 */
#if 0
#define real_tty_output(x) (exp_stdout_is_tty && (((x)==1) || ((x)==exp_dev_tty)))
#define real_tty_input(x) (exp_stdin_is_tty && (((x)==0) || ((x)==exp_dev_tty)))
#endif

#define real_tty_output(x) (((x)==1) || ((x)==exp_dev_tty))
#define real_tty_input(x) (exp_stdin_is_tty && (((x)==0) || ((x)==exp_dev_tty)))

#define new(x)	(x *)ckalloc(sizeof(x))

struct action {
	char *statement;
	int tty_reset;		/* if true, reset tty mode upon action */
	int iread;		/* if true, reread indirects */
	int iwrite;		/* if true, write spawn_id element */
	int timestamp;		/* if true, generate timestamp */
	struct action *next;	/* chain only for later for freeing */
};

struct keymap {
	char *keys;	/* original pattern provided by user */
	regexp *re;
	int null;	/* true if looking to match 0 byte */
	int case_sensitive;
	int echo;	/* if keystrokes should be echoed */
	int writethru;	/* if keystrokes should go through to process */
	int indices;	/* true if should write indices */
	struct action action;
	struct keymap *next;







<

>
|
|
>

<
|


>
>
>
>
>


















|
|




|



<




|
|







39
40
41
42
43
44
45

46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
#include "string.h"

#include "exp_tty_in.h"
#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"


typedef struct ThreadSpecificData {
    Tcl_Obj *cmdObjReturn;
    Tcl_Obj *cmdObjInterpreter;
} ThreadSpecificData;


static Tcl_ThreadDataKey dataKey;

#define INTER_OUT "interact_out"
#define out(var,val) \
 expDiagLog("interact: set %s(%s) ",INTER_OUT,var); \
 expDiagLogU(expPrintify(val)); \
 expDiagLogU("\"\r\n"); \
 Tcl_SetVar2(interp,INTER_OUT,var,val,0);

/*
 * tests if we are running this using a real tty
 *
 * these tests are currently only used to control what gets written to the
 * logfile.  Note that removal of the test of "..._is_tty" means that stdin
 * or stdout could be redirected and yet stdout would still be logged.
 * However, it's not clear why anyone would use log_file when these are
 * redirected in the first place.  On the other hand, it is reasonable to
 * run expect as a daemon in which case, stdin/out do not appear to be
 * ttys, yet it makes sense for them to be logged with log_file as if they
 * were.
 */
#if 0
#define real_tty_output(x) (exp_stdout_is_tty && (((x)==1) || ((x)==exp_dev_tty)))
#define real_tty_input(x) (exp_stdin_is_tty && (((x)==0) || ((x)==exp_dev_tty)))
#endif

#define real_tty_output(x) ((x->fdout == 1) || (expDevttyIs(x)))
#define real_tty_input(x) (exp_stdin_is_tty && ((x->fdin==0) || (expDevttyIs(x))))

#define new(x)	(x *)ckalloc(sizeof(x))

struct action {
	Tcl_Obj *statement;
	int tty_reset;		/* if true, reset tty mode upon action */
	int iread;		/* if true, reread indirects */
	int iwrite;		/* if true, write spawn_id element */

	struct action *next;	/* chain only for later for freeing */
};

struct keymap {
	Tcl_Obj *keys;	/* original pattern provided by user */
	int re;		/* true if looking to match a regexp. */
	int null;	/* true if looking to match 0 byte */
	int case_sensitive;
	int echo;	/* if keystrokes should be echoed */
	int writethru;	/* if keystrokes should go through to process */
	int indices;	/* true if should write indices */
	struct action action;
	struct keymap *next;
108
109
110
111
112
113
114

































115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
	struct action *action_eof;
	struct action *action_timeout;
	struct keymap *keymap;
	int timeout_nominal;		/* timeout nominal */
	int timeout_remaining;		/* timeout remaining */
	struct input *next;
};


































static void free_input();
static void free_keymap();
static void free_output();
static void free_action();
static struct action *new_action();
static int inter_eval();

/* in_keymap() accepts user keystrokes and returns one of MATCH,
CANMATCH, or CANTMATCH.  These describe whether the keystrokes match a
key sequence, and could or can't if more characters arrive.  The
function assigns a matching keymap if there is a match or can-match.
A matching keymap is assigned on can-match so we know whether to echo
or not.

in_keymap is optimized (if you can call it that) towards a small
number of key mappings, but still works well for large maps, since no
function calls are made, and we stop as soon as there is a single-char
mismatch, and go on to the next one.  A hash table or compiled DFA
probably would not buy very much here for most maps.

The basic idea of how this works is it does a smart sequential search.
At each position of the input string, we attempt to match each of the







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|






|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
	struct action *action_eof;
	struct action *action_timeout;
	struct keymap *keymap;
	int timeout_nominal;		/* timeout nominal */
	int timeout_remaining;		/* timeout remaining */
	struct input *next;
};

/*
 * Once we are handed an ExpState from the event handler, we can figure out
 * which "struct input *" it references by using expStateToInput.  This has is
 * populated by expCreateStateToInput.
 */

struct input *
expStateToInput(hash,esPtr)
    ExpState *esPtr;
    Tcl_HashTable *hash;
{
    Tcl_HashEntry *entry = Tcl_FindHashEntry(hash,(char *)esPtr);

    if (!entry) {
	/* should never happen */
	return 0;
    }
    return ((struct input *)Tcl_GetHashValue(entry));
}

void
expCreateStateToInput(hash,esPtr,inp)
    ExpState *esPtr;
    Tcl_HashTable *hash;
    struct input *inp;
{
    Tcl_HashEntry *entry;
    int newPtr;

    entry = Tcl_CreateHashEntry(hash,(char *)esPtr,&newPtr);
    Tcl_SetHashValue(entry,(ClientData)inp);
}

static void free_input();
static void free_keymap();
static void free_output();
static void free_action();
static struct action *new_action();
static int inter_eval();

/* intMatch() accepts user keystrokes and returns one of MATCH,
CANMATCH, or CANTMATCH.  These describe whether the keystrokes match a
key sequence, and could or can't if more characters arrive.  The
function assigns a matching keymap if there is a match or can-match.
A matching keymap is assigned on can-match so we know whether to echo
or not.

intMatch is optimized (if you can call it that) towards a small
number of key mappings, but still works well for large maps, since no
function calls are made, and we stop as soon as there is a single-char
mismatch, and go on to the next one.  A hash table or compiled DFA
probably would not buy very much here for most maps.

The basic idea of how this works is it does a smart sequential search.
At each position of the input string, we attempt to match each of the
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

160

161
162

163


164





165
166
167
168
169
170
171
172
173
174
175


176
177




178
179


180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198



199


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243


244

245
246
247
248


249


250




251
252

253
254
255
256
257
258
259
260


























































261







































262



263
264

265
266

267
268
269
270
271
272
273
274
275
276
277

278
279


280
281
282













283
284
285
286




287


288
289


290
291
292
293
294
295
296
is to force the pattern to always be anchored at the front.  That way,
it doesn't waste time attempting to match later in the string (before
we're ready).  The other is to return can-match.

*/

static int
in_keymap(string,stringlen,keymap,km_match,match_length,skip,rm_nulls)
char *string;
int stringlen;
struct keymap *keymap;		/* linked list of keymaps */
struct keymap **km_match;	/* keymap that matches or can match */
int *match_length;		/* # of chars that matched */
int *skip;			/* # of chars to skip */
int rm_nulls;			/* skip nulls if true */

{

	struct keymap *km;
	char *ks;		/* string from a keymap */

	char *start_search;	/* where in the string to start searching */


	char *string_end;






	/* assert (*km == 0) */

	/* a shortcut that should help master output which typically */
	/* is lengthy and has no key maps.  Otherwise it would mindlessly */
	/* iterate on each character anyway. */
	if (!keymap) {
		*skip = stringlen;
		return(EXP_CANTMATCH);
	}



	string_end = string + stringlen;





	/* Mark beginning of line for ^ . */
	regbol = string;



/* skip over nulls - Pascal Meheut, [email protected] 18-May-1993 */
/*    for (start_search = string;*start_search;start_search++) {*/
    for (start_search = string;start_search<string_end;start_search++) {
	if (*km_match) break; /* if we've already found a CANMATCH */
			/* don't bother starting search from positions */
			/* further along the string */

	for (km=keymap;km;km=km->next) {
	    char *s;	/* current character being examined */

	    if (km->null) {
		if (*start_search == 0) {
		    *skip = start_search-string;
		    *match_length = 1;	/* s - start_search == 1 */
		    *km_match = km;
		    return(EXP_MATCH);
	        }
	    } else if (!km->re) {



		/* fixed string */


		for (s = start_search,ks = km->keys ;;s++,ks++) {
			/* if we hit the end of this map, must've matched! */
			if (*ks == 0) {
				*skip = start_search-string;
				*match_length = s-start_search;
				*km_match = km;
				return(EXP_MATCH);
			}

			/* if we ran out of user-supplied characters, and */
			/* still haven't matched, it might match if the user */
			/* supplies more characters next time */

			if (s == string_end) {
				/* skip to next key entry, but remember */
				/* possibility that this entry might match */
				if (!*km_match) *km_match = km;
				break;
			}



			/* if this is a problem for you, use exp_parity command */
/*			if ((*s & 0x7f) == *ks) continue;*/
			if (*s == *ks) continue;
			if ((*s == '\0') && rm_nulls) {
				ks--;
				continue;
			}
			break;
		}
	    } else {
		/* regexp */
		int r;	/* regtry status */
		regexp *prog = km->re;

		/* if anchored, but we're not at beginning, skip pattern */
		if (prog->reganch) {
			if (string != start_search) continue;
		}

		/* known starting char - quick test 'fore lotta work */
		if (prog->regstart) {
			/* if this is a problem for you, use exp_parity command */
/*			/* if ((*start_search & 0x7f) != prog->regstart) continue; */
			if (*start_search != prog->regstart) continue;


		}

		r = exp_regtry(prog,start_search,match_length);
		if (r == EXP_MATCH) {
			*km_match = km;
			*skip = start_search-string;


			return(EXP_MATCH);


		}




		if (r == EXP_CANMATCH) {
			if (!*km_match) *km_match = km;

		}
	    }
	}
    }

	if (*km_match) {
		/* report a can-match */



























































		char *p;











































		*skip = (start_search-string)-1;
#if 0

		*match_length = stringlen - *skip;
#else

		/*
		 * there may be nulls in the string in which case
		 * the pattern matchers can report CANMATCH when
		 * the null is hit.  So find the null and compute
		 * the length of the possible match.
		 *
		 * Later, after we squeeze out the nulls, we will
		 * retry the match, but for now, go along with
		 * calling it a CANMATCH
		 */
		p = start_search;

		while (*p) {
			p++;


		}
		*match_length = (p - start_search) + 1;
		/*printf(" match_length = %d\n",*match_length);*/













#endif
		return(EXP_CANMATCH);
	}





	*skip = start_search-string;


	return(EXP_CANTMATCH);
}



#ifdef SIMPLE_EVENT

/*

The way that the "simple" interact works is that the original Expect
process reads from the tty and writes to the spawned process.  A child







|
|
<
|
|
|
|
<
>

>
|
|
>
|
>
>
|
>
>
>
>
>

|

|
|
|
|
|
|
|

>
>
|

>
>
>
>
|
|
>
>

<
|
|








|

|




>
>
>

>
>
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|

>
>
|
<
|
|
|
|
|
|



<
|
|
<
|
<
|
|
<
<
<
<
<
>
>
|
>
|
|
|
|
>
>
|
>
>
|
>
>
>
>
|

>
|




|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
|
|
>
|
<
<
<
<
<
|
|
<
|
|
>
|
|
>
>
|
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>

<
|

>
>
>
>
|
>
>
|

>
>







182
183
184
185
186
187
188
189
190

191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288

289
290

291

292
293





294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431





432
433

434
435
436
437
438
439
440
441


442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
is to force the pattern to always be anchored at the front.  That way,
it doesn't waste time attempting to match later in the string (before
we're ready).  The other is to return can-match.

*/

static int
intMatch(esPtr,keymap,km_match,matchLen,skip,info)
    ExpState *esPtr;

    struct keymap *keymap;	/* linked list of keymaps */
    struct keymap **km_match;	/* keymap that matches or can match */
    int *matchLen;		/* # of bytes that matched */
    int *skip;			/* # of chars to skip */

    Tcl_RegExpInfo *info;
{
    char *string;
    struct keymap *km;
    char *ks;		/* string from a keymap */

    char *start_search;	/* where in string to start searching */
    int offset;		/* # of chars from string to start searching */

    char *string_end;
    int stringBytes, bytesThisChar;
    int rm_nulls;		/* skip nulls if true */
    Tcl_UniChar ch;

    string = Tcl_GetStringFromObj(esPtr->buffer,&stringBytes);

    /* assert (*km == 0) */

    /* a shortcut that should help master output which typically */
    /* is lengthy and has no key maps.  Otherwise it would mindlessly */
    /* iterate on each character anyway. */
    if (!keymap) {
	*skip = stringBytes;
	return(EXP_CANTMATCH);
    }

    rm_nulls = esPtr->rm_nulls;

    string_end = string + stringBytes;

    /*
     * Maintain both a character index and a string pointer so we
     * can easily index into either the UTF or the Unicode representations.
     */

    for (start_search = string, offset = 0;
	 start_search < string_end;
	 start_search += bytesThisChar, offset++) {


	bytesThisChar = Tcl_UtfToUniChar(start_search, &ch);
	
	if (*km_match) break; /* if we've already found a CANMATCH */
			/* don't bother starting search from positions */
			/* further along the string */

	for (km=keymap;km;km=km->next) {
	    char *s;	/* current character being examined */

	    if (km->null) {
		if (ch == 0) {
		    *skip = start_search-string;
		    *matchLen = 1;	/* s - start_search == 1 */
		    *km_match = km;
		    return(EXP_MATCH);
	        }
	    } else if (!km->re) {
		int slen, kslen;
		Tcl_UniChar sch, ksch;
		
		/* fixed string */

		ks = Tcl_GetString(km->keys);
		for (s = start_search;; s += slen, ks += kslen) {
		    /* if we hit the end of this map, must've matched! */
		    if (*ks == 0) {
			*skip = start_search-string;
			*matchLen = s-start_search;
			*km_match = km;
			return(EXP_MATCH);
		    }

		    /* if we ran out of user-supplied characters, and */
		    /* still haven't matched, it might match if the user */
		    /* supplies more characters next time */

		    if (s == string_end) {
			/* skip to next key entry, but remember */
			/* possibility that this entry might match */
			if (!*km_match) *km_match = km;
			break;
		    }

		    slen = Tcl_UtfToUniChar(s, &sch);
		    kslen = Tcl_UtfToUniChar(ks, &ksch);
		    

		    if (sch == ksch) continue;
		    if ((sch == '\0') && rm_nulls) {
			kslen = 0;
			continue;
		    }
		    break;
		}
	    } else {
		/* regexp */

		Tcl_RegExp re;
		int flags;

		int result;


		re = Tcl_GetRegExpFromObj(NULL, km->keys,





			TCL_REG_ADVANCED|TCL_REG_BOSONLY|TCL_REG_CANMATCH);
		flags = (offset > 0) ? TCL_REG_NOTBOL : 0;

		result = Tcl_RegExpExecObj(NULL, re, esPtr->buffer, offset,
			-1 /* nmatches */, flags);
		if (result > 0) {
		    *km_match = km;
		    *skip = start_search-string;
		    Tcl_RegExpGetInfo(re, info);
		    *matchLen = Tcl_UtfAtIndex(start_search,info->matches[0].end) - start_search;
		    return EXP_MATCH;
		} else if (result == 0) {
		    Tcl_RegExpGetInfo(re, info);

		    /*
		     * Check to see if there was a partial match starting
		     * at the current character.
		     */
		    if (info->extendStart == 0) {
			if (!*km_match) *km_match = km;
		    }
		}		    
	    }
	}
    }

    if (*km_match) {
	/* report CANMATCH for -re and -ex */

	/*
	 * since canmatch is only detected after we've advanced too far,
	 * adjust start_search back to make other computations simpler
	 */
	start_search--;

	*skip = start_search - string;
	*matchLen = string_end - start_search;
	return(EXP_CANMATCH);
    }
    
    *skip = start_search-string;
    return(EXP_CANTMATCH);
}

/* put regexp result in variables */
static void
intRegExpMatchProcess(interp,esPtr,km,info,offset)
     Tcl_Interp *interp;
     ExpState *esPtr;
     struct keymap *km;	/* ptr for above while parsing */
     Tcl_RegExpInfo *info;
     int offset;
{
    char name[20], value[20];
    int i;

    for (i=0;i<=info->nsubs;i++) {
	int start, end;
	Tcl_Obj *val;

	start = info->matches[i].start + offset;
	if (start == -1) continue;
	end = (info->matches[i].end-1) + offset;

	if (km->indices) {
	    /* start index */
	    sprintf(name,"%d,start",i);
	    sprintf(value,"%d",start);
	    out(name,value);
		    
	    /* end index */
	    sprintf(name,"%d,end",i);
	    sprintf(value,"%d",end);
	    out(name,value);
	}

	/* string itself */
	sprintf(name,"%d,string",i);
	val = Tcl_GetRange(esPtr->buffer, start, end);
	expDiagLog("expect_background: set %s(%s) \"",INTER_OUT,name);
	expDiagLogU(expPrintifyObj(val));
	expDiagLogU("\"\r\n");
	Tcl_SetVar2Ex(interp,INTER_OUT,name,val,0);
    }
}

/*
 * echo chars
 */ 
static void
intEcho(esPtr,skipBytes,matchBytes)
    ExpState *esPtr;
    int skipBytes;
    int matchBytes;
{
    int seenBytes;	/* either printed or echoed */
    int echoBytes;
    int offsetBytes;

    /* write is unlikely to fail, since we just read from same descriptor */
    seenBytes = esPtr->printed + esPtr->echoed;
    if (skipBytes >= seenBytes) {
	echoBytes = matchBytes;
	offsetBytes = skipBytes;
    } else if ((matchBytes + skipBytes - seenBytes) > 0) {
	echoBytes = matchBytes + skipBytes - seenBytes;
	offsetBytes = seenBytes;
    }

    Tcl_WriteChars(esPtr->channel,
		   Tcl_GetString(esPtr->buffer) + offsetBytes,
		   echoBytes);

    esPtr->echoed = matchBytes + skipBytes - esPtr->printed;
}

/*
 * intRead() does the logical equivalent of a read() for the interact command.
 * Returns # of bytes read or negative number (EXP_XXX) indicating unusual event.
 */
static int
intRead(interp,esPtr,warnOnBufferFull,interruptible,key)
    Tcl_Interp *interp;
    ExpState *esPtr;
    int warnOnBufferFull;
    int interruptible;
    int key;
{
    char *eobOld;  /* old end of buffer */
    int cc;
    int size;
    char *str;

    str = Tcl_GetStringFromObj(esPtr->buffer,&size);
    eobOld = str+size;

    if (size + TCL_UTF_MAX >= esPtr->msize) {
	/*





	 * In theory, interact could be invoked when this situation
	 * already exists, hence the "probably" in the warning below

	 */
	if (warnOnBufferFull) {
	    expDiagLogU("WARNING: interact buffer is full, probably because your\r\n");
	    expDiagLogU("patterns have matched all of it but require more chars\r\n");
	    expDiagLogU("in order to complete the match.\r\n");
	    expDiagLogU("Dumping first half of buffer in order to continue\r\n");
	    expDiagLogU("Recommend you enlarge the buffer or fix your patterns.\r\n");
	}


	exp_buffer_shuffle(interp,esPtr,0,INTER_OUT,"interact");
    }
    if (!interruptible) {
	cc = Tcl_ReadChars(esPtr->channel,
		esPtr->buffer,
		esPtr->msize - (size / TCL_UTF_MAX),
		1 /* append */);
    } else {
#ifdef SIMPLE_EVENT
	cc = intIRead(esPtr->channel,
		esPtr->buffer,
		esPtr->msize - (size / TCL_UTF_MAX),
		1 /* append */);
#endif

    }

    if (cc > 0) {
	expDiagLog("spawn id %s sent <",esPtr->name);
	expDiagLogU(expPrintify(eobOld));
	expDiagLogU(">\r\n");

	esPtr->key = key;
    }
    return cc;
}



#ifdef SIMPLE_EVENT

/*

The way that the "simple" interact works is that the original Expect
process reads from the tty and writes to the spawned process.  A child
315
316
317
318
319
320
321



322


323
324
325
326
327
328

329
330
331





332
333
334
335
336
337

338






339
340


341
342
343
344
345
346
347
348



349

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
#endif

#include <setjmp.h>




static jmp_buf env;		/* for interruptable read() */


static int reading;		/* while we are reading */
				/* really, while "env" is valid */
static int deferred_interrupt = FALSE;	/* if signal is received, but not */
				/* in i_read record this here, so it will */
				/* be handled next time through i_read */


void sigchld_handler()
{
	if (reading) longjmp(env,1);






	deferred_interrupt = TRUE;
}

#define EXP_CHILD_EOF -100


/* interruptable read */






static int
i_read(fd,buffer,length)


int fd;
char *buffer;
int length;
{
	int cc = EXP_CHILD_EOF;

	if (deferred_interrupt) return(cc);




	if (0 == setjmp(env)) {

		reading = TRUE;
		cc = read(fd,buffer,length);
	}
	reading = FALSE;
	return(cc);
}

/* exit status for the child process created by cmdInteract */
#define CHILD_DIED		-2
#define SPAWNED_PROCESS_DIED	-3

static void
clean_up_after_child(interp,master)
Tcl_Interp *interp;
int master;
{
/* should really be recoded using the common wait code in command.c */
	int status;
	int pid;
	int i;

	pid = wait(&status);	/* for slave */
	for (i=0;i<=exp_fd_max;i++) {
		if (exp_fs[i].pid == pid) {
			exp_fs[i].sys_waited = TRUE;
			exp_fs[i].wait = status;
		}
	}
	pid = wait(&status);	/* for child */
	for (i=0;i<=exp_fd_max;i++) {
		if (exp_fs[i].pid == pid) {
			exp_fs[i].sys_waited = TRUE;
			exp_fs[i].wait = status;
		}
	}

	deferred_interrupt = FALSE;
	exp_close(interp,master);
	master = -1;
}
#endif /*SIMPLE_EVENT*/

static int
update_interact_fds(interp,fd_count,fd_to_input,fd_list,input_base,
			do_indirect,config_count,real_tty_caller)
Tcl_Interp *interp;
int *fd_count;
struct input ***fd_to_input;	/* map from fd's to "struct input"s */
int **fd_list;
struct input *input_base;
int do_indirect;		/* if true do indirects */
int *config_count;
int *real_tty_caller;
{
	struct input *inp;
	struct output *outp;
	struct exp_fd_list *fdp;
	int count;

	int real_tty = FALSE;

	*config_count = exp_configure_count;

	count = 0;







>
>
>

>
>



|
|

>
|

|
>
>
>
>
>
|
|




>
|
>
>
>
>
>
>

|
>
>
|
<
|

|

|

>
>
>
|
>
|
|
|
|
|







|

<
<
<
|
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
|
|
<




|


|
|
|







|







494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565



566


567
568






569




570


571
572

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597

#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
#endif

#include <setjmp.h>

#ifdef HAVE_SIGLONGJMP
static sigjmp_buf env;                /* for interruptable read() */
#else
static jmp_buf env;		/* for interruptable read() */
#endif  /* HAVE_SIGLONGJMP */

static int reading;		/* while we are reading */
				/* really, while "env" is valid */
static int deferred_interrupt = FALSE;	/* if signal is received, but not */
				/* in expIRead record this here, so it will */
				/* be handled next time through expIRead */

static void
sigchld_handler()
{
  if (reading) {
#ifdef HAVE_SIGLONGJMP
     siglongjmp(env,1);
#else
    longjmp(env,1);
#endif  /* HAVE_SIGLONGJMP */
  }
  deferred_interrupt = TRUE;
}

#define EXP_CHILD_EOF -100

/*
 * Name: expIRead, do an interruptable read
 *
 * intIRead() reads from chars from the user.
 *
 * It returns early if it detects the death of a proc (either the spawned
 * process or the child (surrogate).
 */
static int
intIRead(channel,obj,size,flags);
Tcl_Channel channel;
Tcl_Obj *obj;
int size;

int flags;
{
    int cc = EXP_CHILD_EOF;

    if (deferred_interrupt) return(cc);

#ifdef HAVE_SIGLONGJMP
    if (0 == sigsetjmp(env,1)) {
#else
    if (0 == setjmp(env)) {
#endif  /* HAVE_SIGLONGJMP */
	reading = TRUE;
	cc = Tcl_ReadChars(channel,obj,size,flags);
    }
    reading = FALSE;
    return(cc);
}

/* exit status for the child process created by cmdInteract */
#define CHILD_DIED		-2
#define SPAWNED_PROCESS_DIED	-3

static void
clean_up_after_child(interp,esPtr)
Tcl_Interp *interp;



ExpState *esPtr;


{
    expWaitOnOne(); /* wait for slave */






    expWaitOnOne(); /* wait for child */







    deferred_interrupt = FALSE;
    exp_close(interp,esPtr);

}
#endif /*SIMPLE_EVENT*/

static int
update_interact_fds(interp,esPtrCount,esPtrToInput,esPtrs,input_base,
			do_indirect,config_count,real_tty_caller)
Tcl_Interp *interp;
int *esPtrCount;
Tcl_HashTable **esPtrToInput;	/* map from ExpStates to "struct inputs" */
ExpState ***esPtrs;
struct input *input_base;
int do_indirect;		/* if true do indirects */
int *config_count;
int *real_tty_caller;
{
	struct input *inp;
	struct output *outp;
	struct exp_state_list *fdp;
	int count;

	int real_tty = FALSE;

	*config_count = exp_configure_count;

	count = 0;
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457
458

459
460
461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
				if (outp->i_list->direct == EXP_INDIRECT) {
					exp_i_update(interp,outp->i_list);
				}
			}
		}

		/* revalidate all input descriptors */
		for (fdp = inp->i_list->fd_list;fdp;fdp=fdp->next) {
			count++;
			/* have to "adjust" just in case spawn id hasn't had */
			/* a buffer sized yet */
			if (!exp_fd2f(interp,fdp->fd,1,1,"interact"))
				return(TCL_ERROR);

		}

		/* revalidate all output descriptors */
		for (outp = inp->output;outp;outp=outp->next) {
			for (fdp = outp->i_list->fd_list;fdp;fdp=fdp->next) {
				/* make user_spawn_id point to stdout */
				if (fdp->fd == 0) {
					fdp->fd = 1;
				} else if (fdp->fd == 1) {
					/* do nothing */
				} else if (!exp_fd2f(interp,fdp->fd,1,0,"interact"))
					return(TCL_ERROR);

			}
		}
	}
	if (!do_indirect) return TCL_OK;

	if (*fd_to_input == 0) {
		*fd_to_input = (struct input **)ckalloc(
				(exp_fd_max+1) * sizeof(struct input *));
		*fd_list = (int *)ckalloc(count * sizeof(int));
	} else {
		*fd_to_input = (struct input **)ckrealloc((char *)*fd_to_input,

				(exp_fd_max+1) * sizeof(struct input *));
		*fd_list = (int *)ckrealloc((char *)*fd_list,count * sizeof(int));
	}


	count = 0;
	for (inp = input_base;inp;inp=inp->next) {
		for (fdp = inp->i_list->fd_list;fdp;fdp=fdp->next) {
			/* build map to translate from spawn_id to struct input */
			(*fd_to_input)[fdp->fd] = inp;

			/* build input to ready() */
			(*fd_list)[count] = fdp->fd;

			if (real_tty_input(fdp->fd)) real_tty = TRUE;

			count++;
		}
	}
	*fd_count = count;

	*real_tty_caller = real_tty; /* tell caller if we have found that */
					/* we are using real tty */

	return TCL_OK;
}








|
|
|
|
|
|
>




|

<
|
<
<
|
|
>





|
|
<
|

<
>
|
|

>



|
|
|

|
|

|

|
|

|







607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626

627


628
629
630
631
632
633
634
635
636
637

638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
				if (outp->i_list->direct == EXP_INDIRECT) {
					exp_i_update(interp,outp->i_list);
				}
			}
		}

		/* revalidate all input descriptors */
		for (fdp = inp->i_list->state_list;fdp;fdp=fdp->next) {
		    count++;
		    /* have to "adjust" just in case spawn id hasn't had */
		    /* a buffer sized yet */
		    if (!expStateCheck(interp,fdp->esPtr,1,1,"interact")) {
			return(TCL_ERROR);
		    }
		}

		/* revalidate all output descriptors */
		for (outp = inp->output;outp;outp=outp->next) {
			for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) {
				/* make user_spawn_id point to stdout */

			    if (!expStdinoutIs(fdp->esPtr)) {


				if (!expStateCheck(interp,fdp->esPtr,1,0,"interact"))
				    return(TCL_ERROR);
			    }
			}
		}
	}
	if (!do_indirect) return TCL_OK;

	if (*esPtrToInput == 0) {
	    *esPtrToInput = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));

	    *esPtrs = (ExpState **)ckalloc(count * sizeof(ExpState *));
	} else {

	    /* if hash table already exists, delete it and start over */
	    Tcl_DeleteHashTable(*esPtrToInput);
	    *esPtrs = (ExpState **)ckrealloc((char *)*esPtrs,count * sizeof(ExpState *));
	}
	Tcl_InitHashTable(*esPtrToInput,TCL_ONE_WORD_KEYS);

	count = 0;
	for (inp = input_base;inp;inp=inp->next) {
	    for (fdp = inp->i_list->state_list;fdp;fdp=fdp->next) {
		/* build map to translate from spawn_id to struct input */
		expCreateStateToInput(*esPtrToInput,fdp->esPtr,inp);

		/* build input to ready() */
		(*esPtrs)[count] = fdp->esPtr;

		if (real_tty_input(fdp->esPtr)) real_tty = TRUE;

		count++;
	    }
	}
	*esPtrCount = count;

	*real_tty_caller = real_tty; /* tell caller if we have found that */
					/* we are using real tty */

	return TCL_OK;
}

498
499
500
501
502
503
504
505
506
507
508
509
510

511


512
513
514
515
516
517
518

519
520
521


522
523

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580


581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617



618
619
620

621
622
623
624
625
626



627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647




648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

671
672
673
674

675
676
677
678
679
680
681
682
683












684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708

709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734


735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

783
784
785

786
787
788



789
790





791





792
793
794
795
796
797
798
799

800
801
802
803
804
















805



806






























807














808

809

810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829


830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866


867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928





929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979

980
981
982

983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071



1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191


1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

1313
1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383

1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489










1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
#define finish(x)	{ status = x; goto done; }

static char return_cmd[] = "return";
static char interpreter_cmd[] = "interpreter";

/*ARGSUSED*/
int
Exp_InteractCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{

	char *arg;	/* shorthand for current argv */


#ifdef SIMPLE_EVENT
	int pid;
#endif /*SIMPLE_EVENT*/

	/*declarations*/
	int input_count;	/* count of struct input descriptors */
	struct input **fd_to_input;	/* map from fd's to "struct input"s */

	int *fd_list;
	struct keymap *km;	/* ptr for above while parsing */
/* 	extern char *tclRegexpError;	/* declared in tclInt.h */


	int master = EXP_SPAWN_ID_BAD;
	char *master_string = 0;/* string representation of master */

	int need_to_close_master = FALSE;	/* if an eof is received */
				/* we use this to defer close until later */

	int next_tty_reset = FALSE;	/* if we've seen a single -reset */
	int next_iread = FALSE;/* if we've seen a single -iread */
	int next_iwrite = FALSE;/* if we've seen a single -iread */
	int next_re = FALSE;	/* if we've seen a single -re */
	int next_null = FALSE;	/* if we've seen the null keyword */
	int next_writethru = FALSE;/*if macros should also go to proc output */
	int next_indices = FALSE;/* if we should write indices */
	int next_echo = FALSE;	/* if macros should be echoed */
	int next_timestamp = FALSE; /* if we should generate a timestamp */
/*	int next_case_sensitive = TRUE;*/
	char **oldargv = 0;	/* save original argv here if we split it */
	int status = TCL_OK;	/* final return value */
	int i;			/* trusty temp */


	int timeout_simple = TRUE;	/* if no or global timeout */

	int real_tty;		/* TRUE if we are interacting with real tty */
	int tty_changed = FALSE;/* true if we had to change tty modes for */
				/* interact to work (i.e., to raw, noecho) */
	int was_raw;
	int was_echo;
	exp_tty tty_old;

	char *replace_user_by_process = 0; /* for -u flag */

	struct input *input_base;
#define input_user input_base
	struct input *input_default;
	struct input *inp;	/* overused ptr to struct input */
	struct output *outp;	/* overused ptr to struct output */

	int dash_input_count = 0; /* # of "-input"s seen */
	int arbitrary_timeout;
	int default_timeout;
	struct action action_timeout;	/* common to all */
	struct action action_eof;	/* common to all */
	struct action **action_eof_ptr;	/* allow -input/ouput to */
		/* leave their eof-action assignable by a later */
		/* -eof */
	struct action *action_base = 0;
	struct keymap **end_km;

	int key;
	int configure_count;	/* monitor reconfigure events */

	if ((argc == 2) && exp_one_arg_braced(argv[1])) {
		return(exp_eval_with_one_arg(clientData,interp,argv));
	} else if ((argc == 3) && streq(argv[1],"-brace")) {
		char *new_argv[2];
		new_argv[0] = argv[0];
		new_argv[1] = argv[2];
		return(exp_eval_with_one_arg(clientData,interp,new_argv));
	}



	argv++;
	argc--;

	default_timeout = EXP_TIME_INFINITY;
	arbitrary_timeout = EXP_TIME_INFINITY;	/* if user specifies */
		/* a bunch of timeouts with EXP_TIME_INFINITY, this will be */
		/* left around for us to find. */

	input_user = new(struct input);
	input_user->i_list = exp_new_i_simple(0,EXP_TEMPORARY); /* stdin by default */
	input_user->output = 0;
	input_user->action_eof = &action_eof;
	input_user->timeout_nominal = EXP_TIME_INFINITY;
	input_user->action_timeout = 0;
	input_user->keymap = 0;

	end_km = &input_user->keymap;
	inp = input_user;
	action_eof_ptr = &input_user->action_eof;

	input_default = new(struct input);
	input_default->i_list = exp_new_i_simple(EXP_SPAWN_ID_BAD,EXP_TEMPORARY); /* fix up later */
	input_default->output = 0;
	input_default->action_eof = &action_eof;
	input_default->timeout_nominal = EXP_TIME_INFINITY;
	input_default->action_timeout = 0;
	input_default->keymap = 0;
	input_default->next = 0;		/* no one else */
	input_user->next = input_default;

	/* default and common -eof action */
	action_eof.statement = return_cmd;
	action_eof.tty_reset = FALSE;
	action_eof.iread = FALSE;
	action_eof.iwrite = FALSE;
	action_eof.timestamp = FALSE;




	for (;argc>0;argc--,argv++) {
		arg = *argv;
		if (exp_flageq("eof",arg,3)) {

			struct action *action;

			argc--;argv++;
			*action_eof_ptr = action = new_action(&action_base);

			action->statement = *argv;




			action->tty_reset = next_tty_reset;
			next_tty_reset = FALSE;
			action->iwrite = next_iwrite;
			next_iwrite = FALSE;
			action->iread = next_iread;
			next_iread = FALSE;
			action->timestamp = next_timestamp;
			next_timestamp = FALSE;
			continue;
		} else if (exp_flageq("timeout",arg,7)) {
			int t;
			struct action *action;

			argc--;argv++;
			if (argc < 1) {
				exp_error(interp,"timeout needs time");
				return(TCL_ERROR);
			}
			t = atoi(*argv);
			argc--;argv++;





			/* we need an arbitrary timeout to start */
			/* search for lowest one later */
			if (t != -1) arbitrary_timeout = t;

			timeout_simple = FALSE;
			action = inp->action_timeout = new_action(&action_base);
			inp->timeout_nominal = t;

			action->statement = *argv;

			action->tty_reset = next_tty_reset;
			next_tty_reset = FALSE;
			action->iwrite = next_iwrite;
			next_iwrite = FALSE;
			action->iread = next_iread;
			next_iread = FALSE;
			action->timestamp = next_timestamp;
			next_timestamp = FALSE;
			continue;
		} else if (exp_flageq("null",arg,4)) {
			next_null = TRUE;			
		} else if (arg[0] == '-') {

			arg++;
			if (exp_flageq1('-',arg)		/* "--" */
			 || (exp_flageq("exact",arg,3))) {
				argc--;argv++;

			} else if (exp_flageq("regexp",arg,2)) {
				if (argc < 1) {
					exp_error(interp,"-re needs pattern");
					return(TCL_ERROR);
				}
				next_re = TRUE;
				argc--;
				argv++;
			} else if (exp_flageq("input",arg,2)) {












				dash_input_count++;
				if (dash_input_count == 2) {
					inp = input_default;
					input_user->next = input_default;
				} else if (dash_input_count > 2) {
					struct input *previous_input = inp;
					inp = new(struct input);
					previous_input->next = inp;
				}
				inp->output = 0;
				inp->action_eof = &action_eof;
				action_eof_ptr = &inp->action_eof;
				inp->timeout_nominal = default_timeout;
				inp->action_timeout = &action_timeout;
				inp->keymap = 0;
				end_km = &inp->keymap;
				inp->next = 0;
				argc--;argv++;
				if (argc < 1) {
					exp_error(interp,"-input needs argument");
					return(TCL_ERROR);
				}
/*				inp->spawn_id = atoi(*argv);*/
				inp->i_list = exp_new_i_complex(interp,*argv,
						EXP_TEMPORARY,inter_updateproc);

				continue;
			} else if (exp_flageq("output",arg,3)) {
				struct output *tmp;

				/* imply a "-input" */
				if (dash_input_count == 0) dash_input_count = 1;

				outp = new(struct output);

				/* link new output in front of others */
				tmp = inp->output;
				inp->output = outp;
				outp->next = tmp;

				argc--;argv++;
				if (argc < 1) {
					exp_error(interp,"-output needs argument");
					return(TCL_ERROR);
				}
				outp->i_list = exp_new_i_complex(interp,*argv,
					EXP_TEMPORARY,inter_updateproc);

				outp->action_eof = &action_eof;
				action_eof_ptr = &outp->action_eof;
				continue;
			} else if (exp_flageq1('u',arg)) {	/* treat process as user */


				argc--;argv++;
				if (argc < 1) {
					exp_error(interp,"-u needs argument");
					return(TCL_ERROR);
				}
				replace_user_by_process = *argv;

				/* imply a "-input" */
				if (dash_input_count == 0) dash_input_count = 1;

				continue;
			} else if (exp_flageq1('o',arg)) {
				/* apply following patterns to opposite side */
				/* of interaction */

				end_km = &input_default->keymap;

				/* imply two "-input" */
				if (dash_input_count < 2) {
					dash_input_count = 2;
					inp = input_default;
					action_eof_ptr = &inp->action_eof;
				}
				continue;
			} else if (exp_flageq1('i',arg)) {
				/* substitute master */

				argc--;argv++;
/*				master = atoi(*argv);*/
				master_string = *argv;
				/* will be used later on */

				end_km = &input_default->keymap;

				/* imply two "-input" */
				if (dash_input_count < 2) {
					dash_input_count = 2;
					inp = input_default;
					action_eof_ptr = &inp->action_eof;
				}
				continue;
/*			} else if (exp_flageq("nocase",arg,3)) {*/
/*				next_case_sensitive = FALSE;*/
/*				continue;*/
			} else if (exp_flageq("echo",arg,4)) {
				next_echo = TRUE;
				continue;
			} else if (exp_flageq("nobuffer",arg,3)) {

				next_writethru = TRUE;
				continue;
			} else if (exp_flageq("indices",arg,3)) {

				next_indices = TRUE;
				continue;
			} else if (exp_flageq1('f',arg)) {



				/* leftover from "fast" days */
				continue;





			} else if (exp_flageq("reset",arg,5)) {





				next_tty_reset = TRUE;
				continue;
			} else if (exp_flageq1('F',arg)) {
				/* leftover from "fast" days */
				continue;
			} else if (exp_flageq("iread",arg,2)) {
				next_iread = TRUE;
				continue;

			} else if (exp_flageq("iwrite",arg,2)) {
				next_iwrite = TRUE;
				continue;
			} else if (exp_flageq("eof",arg,3)) {
				struct action *action;




















				argc--;argv++;






























				debuglog("-eof is deprecated, use eof\r\n");














				*action_eof_ptr = action = new_action(&action_base);

				action->statement = *argv;

				action->tty_reset = next_tty_reset;
				next_tty_reset = FALSE;
				action->iwrite = next_iwrite;
				next_iwrite = FALSE;
				action->iread = next_iread;
				next_iread = FALSE;
				action->timestamp = next_timestamp;
				next_timestamp = FALSE;

				continue;
			} else if (exp_flageq("timeout",arg,7)) {

				int t;
				struct action *action;
				debuglog("-timeout is deprecated, use timeout\r\n");

				argc--;argv++;
				if (argc < 1) {
					exp_error(interp,"-timeout needs time");
					return(TCL_ERROR);
				}



				t = atoi(*argv);
				argc--;argv++;
				if (t != -1)
					arbitrary_timeout = t;
				/* we need an arbitrary timeout to start */
				/* search for lowest one later */

#if 0
				/* if -timeout comes before "-input", then applies */
				/* to all descriptors, else just the current one */
				if (dash_input_count > 0) {
					timeout_simple = FALSE;
					action = inp->action_timeout = 
						new_action(&action_base);
					inp->timeout_nominal = t;
				} else {
					action = &action_timeout;
					default_timeout = t;
				}
#endif
				timeout_simple = FALSE;
				action = inp->action_timeout = new_action(&action_base);
				inp->timeout_nominal = t;

				action->statement = *argv;

				action->tty_reset = next_tty_reset;
				next_tty_reset = FALSE;
				action->iwrite = next_iwrite;
				next_iwrite = FALSE;
				action->iread = next_iread;
				next_iread = FALSE;
				action->timestamp = next_timestamp;
				next_timestamp = FALSE;
				continue;
			} else if (exp_flageq("timestamp",arg,2)) {
				debuglog("-timestamp is deprecated, use exp_timestamp command\r\n");


				next_timestamp = TRUE;
				continue;
			} else if (exp_flageq("nobrace",arg,7)) {
				/* nobrace does nothing but take up space */
				/* on the command line which prevents */
				/* us from re-expanding any command lines */
				/* of one argument that looks like it should */
				/* be expanded to multiple arguments. */

				continue;
			}
		}

		/*
		 * pick up the pattern
		 */


		km = new(struct keymap);

		/* so that we can match in order user specified */
		/* link to end of keymap list */
		*end_km = km;
		km->next = 0;
		end_km = &km->next;

		km->echo = next_echo;
		km->writethru = next_writethru;
		km->indices = next_indices;
		km->action.tty_reset = next_tty_reset;
		km->action.iwrite = next_iwrite;
		km->action.iread = next_iread;
		km->action.timestamp = next_timestamp;
/*		km->case_sensitive = next_case_sensitive;*/

		next_indices = next_echo = next_writethru = FALSE;
		next_tty_reset = FALSE;
		next_iwrite = next_iread = FALSE;
/*		next_case_sensitive = TRUE;*/

		km->keys = *argv;

		km->null = FALSE;
		km->re = 0;
		if (next_re) {
			TclRegError((char *)0);
			if (0 == (km->re = TclRegComp(*argv))) {
				exp_error(interp,"bad regular expression: %s",
								TclGetRegError());
				return(TCL_ERROR);
			}
			next_re = FALSE;
		} if (next_null) {
			km->null = TRUE;
			next_null = FALSE;
		}

		argc--;argv++;

		km->action.statement = *argv;
		debuglog("defining key %s, action %s\r\n",
		 km->keys,
		 km->action.statement?(dprintify(km->action.statement))

				   :interpreter_cmd);






		/* imply a "-input" */
		if (dash_input_count == 0) dash_input_count = 1;
	}

	/* if the user has not supplied either "-output" for the */
	/* default two "-input"s, fix them up here */

	if (!input_user->output) {
		struct output *o = new(struct output);
		if (master_string == 0) {
			if (0 == exp_update_master(interp,&master,1,1)) {
				return(TCL_ERROR);
			}
			o->i_list = exp_new_i_simple(master,EXP_TEMPORARY);
		} else {
			o->i_list = exp_new_i_complex(interp,master_string,
					EXP_TEMPORARY,inter_updateproc);
		}
#if 0
		if (master == EXP_SPAWN_ID_BAD) {
			if (0 == exp_update_master(interp,&master,1,1)) {
				return(TCL_ERROR);
			}
		}
		o->i_list = exp_new_i_simple(master,EXP_TEMPORARY);
#endif
		o->next = 0;	/* no one else */
		o->action_eof = &action_eof;
		input_user->output = o;
	}

	if (!input_default->output) {
		struct output *o = new(struct output);
		o->i_list = exp_new_i_simple(1,EXP_TEMPORARY);/* stdout by default */
		o->next = 0;	/* no one else */
		o->action_eof = &action_eof;
		input_default->output = o;
	}

	/* if user has given "-u" flag, substitute process for user */
	/* in first two -inputs */
	if (replace_user_by_process) {
		/* through away old ones */
		exp_free_i(interp,input_user->i_list,   inter_updateproc);
		exp_free_i(interp,input_default->output->i_list,inter_updateproc);

		/* replace with arg to -u */
		input_user->i_list = exp_new_i_complex(interp,
				replace_user_by_process,
				EXP_TEMPORARY,inter_updateproc);

		input_default->output->i_list = exp_new_i_complex(interp,
				replace_user_by_process,
				EXP_TEMPORARY,inter_updateproc);

	}

	/*
	 * now fix up for default spawn id
	 */

	/* user could have replaced it with an indirect, so force update */
	if (input_default->i_list->direct == EXP_INDIRECT) {
		exp_i_update(interp,input_default->i_list);
	}

	if    (input_default->i_list->fd_list
	   && (input_default->i_list->fd_list->fd == EXP_SPAWN_ID_BAD)) {
		if (master_string == 0) {
			if (0 == exp_update_master(interp,&master,1,1)) {
				return(TCL_ERROR);
			}
			input_default->i_list->fd_list->fd = master;
		} else {
			/* discard old one and install new one */
			exp_free_i(interp,input_default->i_list,inter_updateproc);
			input_default->i_list = exp_new_i_complex(interp,master_string,
				EXP_TEMPORARY,inter_updateproc);
		}
#if 0
		if (master == EXP_SPAWN_ID_BAD) {
			if (0 == exp_update_master(interp,&master,1,1)) {
				return(TCL_ERROR);
			}
		}
		input_default->i_list->fd_list->fd = master;
#endif
	}

	/*
	 * check for user attempting to interact with self
	 * they're almost certainly just fooling around
	 */

	/* user could have replaced it with an indirect, so force update */
	if (input_user->i_list->direct == EXP_INDIRECT) {
		exp_i_update(interp,input_user->i_list);
	}

	if (input_user->i_list->fd_list && input_default->i_list->fd_list
	    && (input_user->i_list->fd_list->fd == input_default->i_list->fd_list->fd)) {
		exp_error(interp,"cannot interact with self - set spawn_id to a spawned process");
		return(TCL_ERROR);
	}

	fd_list = 0;
	fd_to_input = 0;

	/***************************************************************/

	/* all data structures are sufficiently set up that we can now */
	/* "finish()" to terminate this procedure                      */
	/***************************************************************/


	status = update_interact_fds(interp,&input_count,&fd_to_input,&fd_list,input_base,1,&configure_count,&real_tty);
	if (status == TCL_ERROR) finish(TCL_ERROR);

	if (real_tty) {
		tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
	}

	for (inp = input_base,i=0;inp;inp=inp->next,i++) {
	    /* start timers */
	    inp->timeout_remaining = inp->timeout_nominal;
	}

	key = expect_key++;

	/* declare ourselves "in sync" with external view of close/indirect */
	configure_count = exp_configure_count;

#ifndef SIMPLE_EVENT
	/* loop waiting (in event handler) for input */
	for (;;) {
		int te;	/* result of Tcl_Eval */
		struct exp_f *u;
		int rc;	/* return code from ready.  This is further */
			/* refined by matcher. */
		int cc;	/* chars count from read() */
		int m;	/* master */
		int m_out; /* where master echoes to */
		struct action *action = 0;
		time_t previous_time;
		time_t current_time;
		int match_length, skip;



		int change;	/* if action requires cooked mode */
		int attempt_match = TRUE;
		struct input *soonest_input;
		int print;		/* # of chars to print */
		int oldprinted;		/* old version of u->printed */

		int timeout;	/* current as opposed to default_timeout */

		/* calculate how long to wait */
		/* by finding shortest remaining timeout */
		if (timeout_simple) {
			timeout = default_timeout;
		} else {
			timeout = arbitrary_timeout;

			for (inp=input_base;inp;inp=inp->next) {
				if ((inp->timeout_remaining != EXP_TIME_INFINITY) &&
				    (inp->timeout_remaining <= timeout)) {
					soonest_input = inp;
					timeout = inp->timeout_remaining;
				}
			}

			time(&previous_time);
			/* timestamp here rather than simply saving old */
			/* current time (after ready()) to account for */
			/* possibility of slow actions */

			/* timeout can actually be EXP_TIME_INFINITY here if user */
			/* explicitly supplied it in a few cases (or */
			/* the count-down code is broken) */
		}

		/* update the world, if necessary */
		if (configure_count != exp_configure_count) {
			status = update_interact_fds(interp,&input_count,
					&fd_to_input,&fd_list,input_base,1,
					&configure_count,&real_tty);
			if (status) finish(status);
		}

		rc = exp_get_next_event(interp,fd_list,input_count,&m,timeout,key);
		if (rc == EXP_TCLERROR) return(TCL_ERROR);

		if (rc == EXP_RECONFIGURE) continue;

		if (rc == EXP_TIMEOUT) {
			if (timeout_simple) {
				action = &action_timeout;
				goto got_action;
			} else {
				action = soonest_input->action_timeout;
				/* arbitrarily pick first fd out of list */
				m = soonest_input->i_list->fd_list->fd;
			}
		}
		if (!timeout_simple) {
			int time_diff;

			time(&current_time);
			time_diff = current_time - previous_time;

			/* update all timers */
			for (inp=input_base;inp;inp=inp->next) {
				if (inp->timeout_remaining != EXP_TIME_INFINITY) {
					inp->timeout_remaining -= time_diff;
					if (inp->timeout_remaining < 0)
						inp->timeout_remaining = 0;
				}
			}
		}

		/* at this point, we have some kind of event which can be */
		/* immediately processed - i.e. something that doesn't block */

		/* figure out who we are */
		inp = fd_to_input[m];
/*		u = inp->f;*/
		u = exp_fs+m;

		/* reset timer */
		inp->timeout_remaining = inp->timeout_nominal;

		switch (rc) {
		case EXP_DATA_NEW:
			if (u->size == u->msize) {
			    /* In theory, interact could be invoked when this situation */
			    /* already exists, hence the "probably" in the warning below */

			    debuglog("WARNING: interact buffer is full, probably because your\r\n");
			    debuglog("patterns have matched all of it but require more chars\r\n");
			    debuglog("in order to complete the match.\r\n");
			    debuglog("Dumping first half of buffer in order to continue\r\n");
			    debuglog("Recommend you enlarge the buffer or fix your patterns.\r\n");
			    exp_buffer_shuffle(interp,u,0,INTER_OUT,"interact");
		        }
			cc = read(m,	u->buffer + u->size,
					u->msize - u->size);
			if (cc > 0) {
				u->key = key;
				u->size += cc;
				u->buffer[u->size] = '\0';

				/* strip parity if requested */
				if (u->parity == 0) {
					/* do it from end backwards */
					char *p = u->buffer + u->size - 1;
					int count = cc;
					while (count--) {
						*p-- &= 0x7f;
					}
				}

				/* avoid another function call if possible */
				if (debugfile || is_debugging) {
					debuglog("spawn id %d sent <%s>\r\n",m,
						exp_printify(u->buffer + u->size - cc));
				}
				break;
			}



			rc = EXP_EOF;
			/* Most systems have read() return 0, allowing */
			/* control to fall thru and into this code.  On some */
			/* systems (currently HP and new SGI), read() does */
			/* see eof, and it must be detected earlier.  Then */
			/* control jumps directly to this EXP_EOF label. */

			/*FALLTHRU*/
		case EXP_EOF:
			action = inp->action_eof;
			attempt_match = FALSE;
			skip = u->size;
			debuglog("interact: received eof from spawn_id %d\r\n",m);
			/* actual close is done later so that we have a */
			/* chance to flush out any remaining characters */
			need_to_close_master = TRUE;

#if EOF_SO
			/* should really check for remaining chars and */
			/* flush them but this will only happen in the */
			/* unlikely scenario that there are partially */
			/* matched buffered chars. */
			/* So for now, indicate no chars to skip. */
			skip = 0;
			exp_close(interp,m);
#endif
			break;
		case EXP_DATA_OLD:
			cc = 0;
			break;
		case EXP_TIMEOUT:
			action = inp->action_timeout;
			attempt_match = FALSE;
			skip = u->size;
			break;
		}

		km = 0;

		if (attempt_match) {
			rc = in_keymap(u->buffer,u->size,inp->keymap,
				&km,&match_length,&skip,u->rm_nulls);
		} else {
			attempt_match = TRUE;
		}

		/* put regexp result in variables */
		if (km && km->re) {
#define out(var,val)  debuglog("expect: set %s(%s) \"%s\"\r\n",INTER_OUT,var, \
						dprintify(val)); \
		    Tcl_SetVar2(interp,INTER_OUT,var,val,0);

			char name[20], value[20];
			regexp *re = km->re;
			char match_char;/* place to hold char temporarily */
					/* uprooted by a NULL */

			for (i=0;i<NSUBEXP;i++) {
				int offset;

				if (re->startp[i] == 0) continue;

				if (km->indices) {
				  /* start index */
				  sprintf(name,"%d,start",i);
				  offset = re->startp[i]-u->buffer;
				  sprintf(value,"%d",offset);
				  out(name,value);

				  /* end index */
				  sprintf(name,"%d,end",i);
				  sprintf(value,"%d",re->endp[i]-u->buffer-1);
				  out(name,value);
				}

				/* string itself */
				sprintf(name,"%d,string",i);
				/* temporarily null-terminate in */
				/* middle */
				match_char = *re->endp[i];
				*re->endp[i] = 0;
				out(name,re->startp[i]);
				*re->endp[i] = match_char;
			}
		}

		/*
		 * dispose of chars that should be skipped
		 * i.e., chars that cannot possibly be part of a match.
		 */
		
		/* "skip" is count of chars not involved in match */
		/* "print" is count with chars involved in match */

		if (km && km->writethru) {
			print = skip + match_length;
		} else print = skip;

		/*
		 * echo chars if appropriate
		 */
		if (km && km->echo) {
			int seen;	/* either printed or echoed */

			/* echo to stdout rather than stdin */
			m_out = (m == 0)?1:m;

			/* write is unlikely to fail, since we just read */
			/* from same descriptor */
			seen = u->printed + u->echoed;
			if (skip >= seen) {
				write(m_out,u->buffer+skip,match_length);
			} else if ((match_length + skip - seen) > 0) {
				write(m_out,u->buffer+seen,match_length+skip-seen);
			}
			u->echoed = match_length + skip - u->printed;
		}

		oldprinted = u->printed;


		/* If expect has left characters in buffer, it has */
		/* already echoed them to the screen, thus we must */
		/* prevent them being rewritten.  Unfortunately this */
		/* gives the possibility of matching chars that have */
		/* already been output, but we do so since the user */
		/* could have avoided it by flushing the output */
		/* buffers directly. */

		if (print > u->printed) {	/* usual case */
			int wc;	/* return code from write() */
			for (outp = inp->output;outp;outp=outp->next) {
			    struct exp_fd_list *fdp;
			    for (fdp = outp->i_list->fd_list;fdp;fdp=fdp->next) {
				int od;	/* output descriptor */

				/* send to logfile if open */
				/* and user is seeing it */
				if (logfile && real_tty_output(fdp->fd)) {
					fwrite(u->buffer+u->printed,1,
					       print - u->printed,logfile);
				}

				/* send to each output descriptor */
				od = fdp->fd;
				/* if opened by Tcl, it may use a different */
				/* output descriptor */
				od = (exp_fs[od].tcl_handle?exp_fs[od].tcl_output:od);


				wc = write(od,u->buffer+u->printed,
					print - u->printed);
				if (wc <= 0) {
					debuglog("interact: write on spawn id %d failed (%s)\r\n",fdp->fd,Tcl_PosixError(interp));
					action = outp->action_eof;
					change = (action && action->tty_reset);

					if (change && tty_changed)
						exp_tty_set(interp,&tty_old,was_raw,was_echo);
					te = inter_eval(interp,action,m);

					if (change && real_tty) tty_changed =
					   exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
					switch (te) {
					case TCL_BREAK:
					case TCL_CONTINUE:
						finish(te);
					case EXP_TCL_RETURN:
						finish(TCL_RETURN);
					case TCL_RETURN:
						finish(TCL_OK);
					case TCL_OK:
						/* god knows what the user might */
						/* have done to us in the way of */
						/* closed fds, so .... */
						action = 0;	/* reset action */
						continue;
					default:
						finish(te);
					}
				}
			    }
			}
			u->printed = print;
		}

		/* u->printed is now accurate with respect to the buffer */
		/* However, we're about to shift the old data out of the */
		/* buffer.  Thus, u->size, printed, and echoed must be */
		/* updated */

		/* first update size based on skip information */
		/* then set skip to the total amount skipped */


		if (rc == EXP_MATCH) {
			action = &km->action;

			skip += match_length;
			u->size -= skip;

			if (u->size) {
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);
			}
		} else {

			if (skip) {
				u->size -= skip;
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);
			}
		}

#if EOF_SO
		/* as long as buffer is still around, null terminate it */
		if (rc != EXP_EOF) {
			u->buffer[u->size] = '\0';
			u->lower [u->size] = '\0';
		}
#else
		u->buffer[u->size] = '\0';
		u->lower [u->size] = '\0';
#endif

		/* now update printed based on total amount skipped */

		u->printed -= skip;
		/* if more skipped than printed (i.e., keymap encountered) */
		/* for printed positive */
		if (u->printed < 0) u->printed = 0;

		/* if we are in the middle of a match, force the next event */
		/* to wait for more data to arrive */
		u->force_read = (rc == EXP_CANMATCH);

		/* finally reset echoed if necessary */
		if (rc != EXP_CANMATCH) {
			if (skip >= oldprinted + u->echoed) u->echoed = 0;
		}

		if (rc == EXP_EOF) {
			exp_close(interp,m);
			need_to_close_master = FALSE;
		}

		if (action) {
got_action:
			change = (action && action->tty_reset);
			if (change && tty_changed)
				exp_tty_set(interp,&tty_old,was_raw,was_echo);

			te = inter_eval(interp,action,m);

			if (change && real_tty) tty_changed =
			   exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
			switch (te) {
			case TCL_BREAK:
			case TCL_CONTINUE:
				finish(te);
			case EXP_TCL_RETURN:
				finish(TCL_RETURN);
			case TCL_RETURN:
				finish(TCL_OK);
			case TCL_OK:
				/* god knows what the user might */
				/* have done to us in the way of */
				/* closed fds, so .... */
				action = 0;	/* reset action */
				continue;
			default:
				finish(te);
			}
		}
	}

#else /* SIMPLE_EVENT */
/*	deferred_interrupt = FALSE;*/
{
		int te;	/* result of Tcl_Eval */
		struct exp_f *u;
		int rc;	/* return code from ready.  This is further */
			/* refined by matcher. */
		int cc;	/* chars count from read() */
		int m;	/* master */
		struct action *action = 0;
		time_t previous_time;
		time_t current_time;
		int match_length, skip;
		int change;	/* if action requires cooked mode */
		int attempt_match = TRUE;
		struct input *soonest_input;
		int print;		/* # of chars to print */
		int oldprinted;		/* old version of u->printed */

		int timeout;	/* current as opposed to default_timeout */

	if (-1 == (pid = fork())) {
		exp_error(interp,"fork: %s",Tcl_PosixError(interp));
		finish(TCL_ERROR);
	}
	if (pid == 0) { /* child - send process output to user */










	    exp_close(interp,0);

	    m = fd_list[1];	/* get 2nd fd */
	    input_count = 1;

	    while (1) {

		/* calculate how long to wait */
		/* by finding shortest remaining timeout */
		if (timeout_simple) {







|


|
|

>
|
>
>

|


|
|
|
>
|
|
<
>
>
|
<
>
|


|
|
|
|
|
|
|
|
<
<
<
|
|
>

|

|
|

|
|
|

|

|

|
|
|

|
|
|
|
|
|


|
|

|
|

|
|
|
|
|
|
|
|

>
>
|
|

|
|



|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|
|
<

>
>
>
|
|
|
>
|
|
<
<
|
<
>
>
>
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
<
<
|
|
|
|
>
>
>
>

<
<
<
|
|
<
<
|
<
|
<
<
<
<
<
<
<
<
|
|
<
|
>
|
<
<
<
>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
>
|
|
|

|
|

|


|
|
|

|
|
|
|
|
|
|
|
|
|
|
<
>
>
|
|
|
|
|
|

|
|
|
<
|
|
|

|

|
|
|
|
|
|
|
|
|

|
<
|
|

|

|
|
|
|
|
|
|
<
|
<
<
|
|
<
>
|
|
<
>
|
|
|
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
|
|
<
|
<
|
|
|
>
|
<
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
|
|
|
|
|
|
<
|
<
<
>
|
|
<

|
|
|
|
|
>
>
|
<
|
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
|
|
<
|
|
|

|
>
|
|
|
|
|
|
<
<
|
<
<
>
>
|
<
<
<
<
<
<
|
>
|
|
|
<
|
|
|

>
|

|
|
|
|
|

|
|
|
|
|
|
<
<

|
|
|
<

|

|
|
|
<
|
<
<
|
|
<
|
|
|
|

|
|
|
<
|
|
>
|
>
>
>
>
>

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
|
<
<
<
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
>
|
|
|
>
|

|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
|
<
<
<
|

|
|
|
|

|
|
|
|

|
|
|
|
|

|
<

<
>
|
|
<
>

|
|

|
|
|

|
|
|
|

|

|
|
|

|
|
|
<
|
<
|
<
<
|
|
|
|
>
>
>
|
|
|
<
<
<
|

|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|

|
|

|
<
<
|

|
|

|
|
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
>
>
|
<
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|

|

|
<
<
<
<
<
|
<
|
<
<
<
|
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

|
|
|
|
<
<
<
<
|
|
|

<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|

>
|
|
|
|
|
|
|
>
|
<
|
|
|
<
|
<
|
<
<
<
<
|
<
<
<
<
<
|
>
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

>
|
|

|
|
<
|
|
|
|
|
>
|
|
|
<
|
|
|
<
<
<
<
<
<
<
<
<
<

|

|
|
|
|

|
|
|

|
|
|
|

|
|
|
|

|

|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|





|



<



|












|
>
>
>
>
>
>
>
>
>
>
|

|







681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707

708
709
710

711
712
713
714
715
716
717
718
719
720
721
722



723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813


814

815
816
817
818
819
820
821
822
823
824
825
826




827



828
829
830
831
832
833
834
835
836



837
838


839

840








841
842

843
844
845



846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889

890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925
926
927
928
929

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946

947
948
949
950
951
952
953
954
955
956
957
958

959


960
961

962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986

987

988
989
990
991
992

993

994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071

1072


1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086

1087
1088











1089
1090

1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102


1103


1104
1105
1106






1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130


1131
1132
1133
1134

1135
1136
1137
1138
1139
1140

1141


1142
1143

1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178




1179
1180



1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232




1233
1234



1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253

1254

1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280

1281

1282


1283
1284
1285
1286
1287
1288
1289
1290
1291
1292



1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329

1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360


1361
1362
1363
1364
1365
1366
1367



1368









1369


















1370
1371

1372
1373
1374

1375
1376
1377
1378
1379
1380

1381
1382
1383
1384
1385
1386
1387
1388










1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402





1403

1404



1405




1406


1407

1408






















1409
1410
1411
1412
1413
1414




1415
1416
1417
1418



1419

1420


1421











1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436

1437

1438




1439





1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491

1492
1493
1494
1495
1496
1497
1498
1499
1500

1501
1502
1503










1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563

1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
#define finish(x)	{ status = x; goto done; }

static char return_cmd[] = "return";
static char interpreter_cmd[] = "interpreter";

/*ARGSUSED*/
int
Exp_InteractObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_Obj *CONST *objv_copy;	/* original, for error messages */
    char *string;
#ifdef SIMPLE_EVENT
    int pid;
#endif /*SIMPLE_EVENT*/

    /*declarations*/
    int input_count;	/* count of struct input descriptors */

    Tcl_HashTable *esPtrToInput = 0;	/* map from ExpState to "struct inputs" */
    ExpState **esPtrs;
    struct keymap *km;	/* ptr for above while parsing */

    Tcl_RegExpInfo reInfo;
    ExpState *u = 0;
    ExpState *esPtr = 0;

    Tcl_Obj *chanName = 0;
    int need_to_close_master = FALSE;	/* if an eof is received */
				/* we use this to defer close until later */

    int next_tty_reset = FALSE;	/* if we've seen a single -reset */
    int next_iread = FALSE;/* if we've seen a single -iread */
    int next_iwrite = FALSE;/* if we've seen a single -iread */
    int next_re = FALSE;	/* if we've seen a single -re */
    int next_null = FALSE;	/* if we've seen the null keyword */
    int next_writethru = FALSE;/*if macros should also go to proc output */
    int next_indices = FALSE;/* if we should write indices */
    int next_echo = FALSE;	/* if macros should be echoed */



    int status = TCL_OK;	/* final return value */
    int i;			/* misc temp */
    int size;			/* size temp */

    int timeout_simple = TRUE;	/* if no or global timeout */

    int real_tty;		/* TRUE if we are interacting with real tty */
    int tty_changed = FALSE;/* true if we had to change tty modes for */
				/* interact to work (i.e., to raw, noecho) */
    int was_raw;
    int was_echo;
    exp_tty tty_old;

    Tcl_Obj *replace_user_by_process = 0; /* for -u flag */

    struct input *input_base;
#define input_user input_base
    struct input *input_default;
    struct input *inp;	/* overused ptr to struct input */
    struct output *outp;	/* overused ptr to struct output */

    int dash_input_count = 0; /* # of "-input"s seen */
    int arbitrary_timeout;
    int default_timeout;
    struct action action_timeout;	/* common to all */
    struct action action_eof;	/* common to all */
    struct action **action_eof_ptr;	/* allow -input/ouput to */
		/* leave their eof-action assignable by a later */
		/* -eof */
    struct action *action_base = 0;
    struct keymap **end_km;

    int key;
    int configure_count;	/* monitor reconfigure events */

    if ((objc == 2) && exp_one_arg_braced(objv[1])) {
	return(exp_eval_with_one_arg(clientData,interp,objv));
    } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) {
	Tcl_Obj *new_objv[2];
	new_objv[0] = objv[0];
	new_objv[1] = objv[2];
	return(exp_eval_with_one_arg(clientData,interp,new_objv));
    }

    objv_copy = objv;

    objv++;
    objc--;

    default_timeout = EXP_TIME_INFINITY;
    arbitrary_timeout = EXP_TIME_INFINITY;	/* if user specifies */
		/* a bunch of timeouts with EXP_TIME_INFINITY, this will be */
		/* left around for us to find. */

    input_user = new(struct input);
    input_user->i_list = exp_new_i_simple(expStdinoutGet(),EXP_TEMPORARY); /* stdin by default */
    input_user->output = 0;
    input_user->action_eof = &action_eof;
    input_user->timeout_nominal = EXP_TIME_INFINITY;
    input_user->action_timeout = 0;
    input_user->keymap = 0;

    end_km = &input_user->keymap;
    inp = input_user;
    action_eof_ptr = &input_user->action_eof;

    input_default = new(struct input);
    input_default->i_list = exp_new_i_simple((ExpState *)0,EXP_TEMPORARY); /* fix up later */
    input_default->output = 0;
    input_default->action_eof = &action_eof;
    input_default->timeout_nominal = EXP_TIME_INFINITY;
    input_default->action_timeout = 0;
    input_default->keymap = 0;
    input_default->next = 0;		/* no one else */
    input_user->next = input_default;

    /* default and common -eof action */
    action_eof.statement = tsdPtr->cmdObjReturn;
    action_eof.tty_reset = FALSE;
    action_eof.iread = FALSE;
    action_eof.iwrite = FALSE;


    /*
     * Parse the command arguments.
     */
    for (;objc>0;objc--,objv++) {
	string = Tcl_GetString(*objv);
	if (string[0] == '-') {
	    static char *switches[] = {
		"--",		"-exact",	"-re",		"-input",
		"-output",	"-u",		"-o",		"-i",


		"-echo",	"-nobuffer",	"-indices",	"-f",

		"-reset",	"-F",		"-iread",	"-iwrite",
		"-eof",		"-timeout",	"-nobrace",	(char *)0
	    };
	    enum switches {
		EXP_SWITCH_DASH,	EXP_SWITCH_EXACT,
		EXP_SWITCH_REGEXP,	EXP_SWITCH_INPUT,
		EXP_SWITCH_OUTPUT,	EXP_SWITCH_USER,
		EXP_SWITCH_OPPOSITE,	EXP_SWITCH_SPAWN_ID,
		EXP_SWITCH_ECHO,	EXP_SWITCH_NOBUFFER,
		EXP_SWITCH_INDICES,	EXP_SWITCH_FAST,
		EXP_SWITCH_RESET,	EXP_SWITCH_CAPFAST,
		EXP_SWITCH_IREAD,	EXP_SWITCH_IWRITE,




		EXP_SWITCH_EOF,		EXP_SWITCH_TIMEOUT,



		EXP_SWITCH_NOBRACE
	    };
	    int index;

	    /*
	     * Allow abbreviations of switches and report an error if we
	     * get an invalid switch.
	     */




	    if (Tcl_GetIndexFromObj(interp, *objv, switches, "switch", 0,
		    &index) != TCL_OK) {


		return TCL_ERROR;

	    }








	    switch ((enum switches) index) {
		case EXP_SWITCH_DASH:

		case EXP_SWITCH_EXACT:
		    objc--;
		    objv++;



		    goto pattern;
		case EXP_SWITCH_REGEXP:
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"-re pattern");
			return(TCL_ERROR);
		    }
		    next_re = TRUE;
		    objc--;
		    objv++;

		    /*
		     * Try compiling the expression so we can report
		     * any errors now rather then when we first try to
		     * use it.
		     */

		    if (!(Tcl_GetRegExpFromObj(interp, *objv,
			    TCL_REG_ADVANCED|TCL_REG_BOSONLY))) {
			return TCL_ERROR;
		    }
		    goto pattern;
		case EXP_SWITCH_INPUT:
		    dash_input_count++;
		    if (dash_input_count == 2) {
			inp = input_default;
			input_user->next = input_default;
		    } else if (dash_input_count > 2) {
			struct input *previous_input = inp;
			inp = new(struct input);
			previous_input->next = inp;
		    }
		    inp->output = 0;
		    inp->action_eof = &action_eof;
		    action_eof_ptr = &inp->action_eof;
		    inp->timeout_nominal = default_timeout;
		    inp->action_timeout = &action_timeout;
		    inp->keymap = 0;
		    end_km = &inp->keymap;
		    inp->next = 0;
		    objc--;objv++;
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"-input spawn_id");
			return(TCL_ERROR);
		    }

		    inp->i_list = exp_new_i_complex(interp,Tcl_GetString(*objv),
			    EXP_TEMPORARY,inter_updateproc);
		    if (!inp->i_list) return TCL_ERROR;
		    break;
		case EXP_SWITCH_OUTPUT: {
		    struct output *tmp;

		    /* imply a "-input" */
		    if (dash_input_count == 0) dash_input_count = 1;

		    outp = new(struct output);

				/* link new output in front of others */
		    tmp = inp->output;
		    inp->output = outp;
		    outp->next = tmp;

		    objc--;objv++;
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"-output spawn_id");
			return(TCL_ERROR);
		    }
		    outp->i_list = exp_new_i_complex(interp,Tcl_GetString(*objv),
			    EXP_TEMPORARY,inter_updateproc);
		    if (!outp->i_list) return TCL_ERROR;
		    outp->action_eof = &action_eof;
		    action_eof_ptr = &outp->action_eof;
		    break;

		}
		case EXP_SWITCH_USER:
		    objc--;objv++;
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"-u spawn_id");
			return(TCL_ERROR);
		    }
		    replace_user_by_process = *objv;

		    /* imply a "-input" */
		    if (dash_input_count == 0) dash_input_count = 1;
		    break;

		case EXP_SWITCH_OPPOSITE:
		    /* apply following patterns to opposite side */
		    /* of interaction */

		    end_km = &input_default->keymap;

		    /* imply two "-input" */
		    if (dash_input_count < 2) {
			dash_input_count = 2;
			inp = input_default;
			action_eof_ptr = &inp->action_eof;
		    }
		    break;
		case EXP_SWITCH_SPAWN_ID:
		    /* substitute master */

		    objc--;objv++;

		    chanName = *objv;
		    /* will be used later on */

		    end_km = &input_default->keymap;

		    /* imply two "-input" */
		    if (dash_input_count < 2) {
			dash_input_count = 2;
			inp = input_default;
			action_eof_ptr = &inp->action_eof;
		    }
		    break;

		case EXP_SWITCH_ECHO:


		    next_echo = TRUE;
		    break;

		case EXP_SWITCH_NOBUFFER:
		    next_writethru = TRUE;
		    break;

		case EXP_SWITCH_INDICES:
		    next_indices = TRUE;
		    break;
		case EXP_SWITCH_RESET:
		    next_tty_reset = TRUE;
		    break;
		case EXP_SWITCH_IREAD:
		    next_iread = TRUE;
		    break;
		case EXP_SWITCH_IWRITE:
			next_iwrite= TRUE;
		    break;
		case EXP_SWITCH_EOF: {
		    struct action *action;

		    objc--;objv++;
		    expDiagLogU("-eof is deprecated, use eof\r\n");
		    *action_eof_ptr = action = new_action(&action_base);
		    action->statement = *objv;
		    action->tty_reset = next_tty_reset;
		    next_tty_reset = FALSE;
		    action->iwrite = next_iwrite;

		    next_iwrite = FALSE;

		    action->iread = next_iread;
		    next_iread = FALSE;
		    break;
		}
		case EXP_SWITCH_TIMEOUT: {

		    int t;

		    struct action *action;
		    expDiagLogU("-timeout is deprecated, use timeout\r\n");

		    objc--;objv++;
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"-timeout time");
			return(TCL_ERROR);
		    }

		    if (Tcl_GetIntFromObj(interp, *objv, &t) != TCL_OK) {
			return TCL_ERROR;
		    }
		    objc--;objv++;
		    if (t != -1)
			arbitrary_timeout = t;
		    /* we need an arbitrary timeout to start */
		    /* search for lowest one later */

		    timeout_simple = FALSE;
		    action = inp->action_timeout = new_action(&action_base);
		    inp->timeout_nominal = t;

		    action->statement = *objv;
		    action->tty_reset = next_tty_reset;
		    next_tty_reset = FALSE;
		    action->iwrite = next_iwrite;
		    next_iwrite = FALSE;
		    action->iread = next_iread;
		    next_iread = FALSE;
		    break;
		}
		case EXP_SWITCH_FAST:
		case EXP_SWITCH_CAPFAST:
		    /* noop compatibility switches for fast mode */
		    break;
		case EXP_SWITCH_NOBRACE:
		    /* nobrace does nothing but take up space */
		    /* on the command line which prevents */
		    /* us from re-expanding any command lines */
		    /* of one argument that looks like it should */
		    /* be expanded to multiple arguments. */
		    break;
	    }
	    continue;
    	} else {
	    static char *options[] = {
		"eof", "timeout", "null", (char *)0
	    };
	    enum options {
		EXP_OPTION_EOF, EXP_OPTION_TIMEOUT, EXP_OPTION_NULL
	    };
	    int index;

	    /*
	     * Match keywords exactly, otherwise they are patterns.
	     */

	    if (Tcl_GetIndexFromObj(interp, *objv, options, "option",
		    1 /* exact */, &index) != TCL_OK) {
		Tcl_ResetResult(interp);
		goto pattern;
	    }
	    switch ((enum options) index) {
		case EXP_OPTION_EOF: {
		    struct action *action;

		    objc--;objv++;
		    *action_eof_ptr = action = new_action(&action_base);

		    action->statement = *objv;

		    action->tty_reset = next_tty_reset;
		    next_tty_reset = FALSE;
		    action->iwrite = next_iwrite;
		    next_iwrite = FALSE;
		    action->iread = next_iread;
		    next_iread = FALSE;
		    break;

		}


		case EXP_OPTION_TIMEOUT: {
		    int t;
		    struct action *action;


		    objc--;objv++;
		    if (objc < 1) {
			Tcl_WrongNumArgs(interp,1,objv_copy,"timeout time");
			return(TCL_ERROR);
		    }
		    if (Tcl_GetIntFromObj(interp, *objv, &t) != TCL_OK) {
			return TCL_ERROR;
		    }

		    objc--;objv++;


		    /* we need an arbitrary timeout to start */
		    /* search for lowest one later */











		    if (t != -1) arbitrary_timeout = t;


		    timeout_simple = FALSE;
		    action = inp->action_timeout = new_action(&action_base);
		    inp->timeout_nominal = t;

		    action->statement = *objv;

		    action->tty_reset = next_tty_reset;
		    next_tty_reset = FALSE;
		    action->iwrite = next_iwrite;
		    next_iwrite = FALSE;
		    action->iread = next_iread;
		    next_iread = FALSE;


		    break;


		}
		case EXP_OPTION_NULL:
		    next_null = TRUE;






		    goto pattern;
	    }
	    continue;
	}
    

	/*
	 * pick up the pattern
	 */

	pattern:
	km = new(struct keymap);

	/* so that we can match in order user specified */
	/* link to end of keymap list */
	*end_km = km;
	km->next = 0;
	end_km = &km->next;

	km->echo = next_echo;
	km->writethru = next_writethru;
	km->indices = next_indices;
	km->action.tty_reset = next_tty_reset;
	km->action.iwrite = next_iwrite;
	km->action.iread = next_iread;



	next_indices = next_echo = next_writethru = FALSE;
	next_tty_reset = FALSE;
	next_iwrite = next_iread = FALSE;


	km->keys = *objv;

	km->null = FALSE;
	km->re = 0;
	if (next_re) {

	    km->re = TRUE;


	    next_re = FALSE;
	}

	if (next_null) {
	    km->null = TRUE;
	    next_null = FALSE;
	}

	objc--;objv++;
	if (objc >= 1) {
	    km->action.statement = *objv;

	} else {
	    km->action.statement = 0;
	}

	expDiagLogU("defining key ");
	expDiagLogU(Tcl_GetString(km->keys));
	expDiagLogU(", action ");
	expDiagLogU(km->action.statement?expPrintify(Tcl_GetString(km->action.statement)):"interpreter");
	expDiagLogU("\r\n");

	/* imply a "-input" */
	if (dash_input_count == 0) dash_input_count = 1;
    }

    /* if the user has not supplied either "-output" for the */
    /* default two "-input"s, fix them up here */

    if (!input_user->output) {
	struct output *o = new(struct output);
	if (!chanName) {
	    if (!(esPtr = expStateCurrent(interp,1,1,0))) {
		return(TCL_ERROR);
	    }
	    o->i_list = exp_new_i_simple(esPtr,EXP_TEMPORARY);
	} else {
	    o->i_list = exp_new_i_complex(interp,Tcl_GetString(chanName),
		    EXP_TEMPORARY,inter_updateproc);




	    if (!o->i_list) return TCL_ERROR;
	}



	o->next = 0;	/* no one else */
	o->action_eof = &action_eof;
	input_user->output = o;
    }

    if (!input_default->output) {
	struct output *o = new(struct output);
	o->i_list = exp_new_i_simple(expStdinoutGet(),EXP_TEMPORARY);/* stdout by default */
	o->next = 0;	/* no one else */
	o->action_eof = &action_eof;
	input_default->output = o;
    }

    /* if user has given "-u" flag, substitute process for user */
    /* in first two -inputs */
    if (replace_user_by_process) {
	/* through away old ones */
	exp_free_i(interp,input_user->i_list,   inter_updateproc);
	exp_free_i(interp,input_default->output->i_list,inter_updateproc);

	/* replace with arg to -u */
	input_user->i_list = exp_new_i_complex(interp,
		Tcl_GetString(replace_user_by_process),
		EXP_TEMPORARY,inter_updateproc);
	if (!input_user->i_list) return TCL_ERROR;
	input_default->output->i_list = exp_new_i_complex(interp,
		Tcl_GetString(replace_user_by_process),
		EXP_TEMPORARY,inter_updateproc);
	if (!input_default->output->i_list) return TCL_ERROR;
    }

    /*
     * now fix up for default spawn id
     */

    /* user could have replaced it with an indirect, so force update */
    if (input_default->i_list->direct == EXP_INDIRECT) {
	exp_i_update(interp,input_default->i_list);
    }

    if (input_default->i_list->state_list
	    && (input_default->i_list->state_list->esPtr == EXP_SPAWN_ID_BAD)) {
	if (!chanName) {
	    if (!(esPtr = expStateCurrent(interp,1,1,0))) {
		return(TCL_ERROR);
	    }
	    input_default->i_list->state_list->esPtr = esPtr;
	} else {
	    /* discard old one and install new one */
	    exp_free_i(interp,input_default->i_list,inter_updateproc);
	    input_default->i_list = exp_new_i_complex(interp,Tcl_GetString(chanName),
		    EXP_TEMPORARY,inter_updateproc);




	    if (!input_default->i_list) return TCL_ERROR;
	}



    }

    /*
     * check for user attempting to interact with self
     * they're almost certainly just fooling around
     */

    /* user could have replaced it with an indirect, so force update */
    if (input_user->i_list->direct == EXP_INDIRECT) {
	exp_i_update(interp,input_user->i_list);
    }

    if (input_user->i_list->state_list && input_default->i_list->state_list
	    && (input_user->i_list->state_list->esPtr == input_default->i_list->state_list->esPtr)) {
	exp_error(interp,"cannot interact with self - set spawn_id to a spawned process");
	return(TCL_ERROR);
    }

    esPtrs = 0;



    /*
     * all data structures are sufficiently set up that we can now
     * "finish()" to terminate this procedure

     */

    status = update_interact_fds(interp,&input_count,&esPtrToInput,&esPtrs,input_base,1,&configure_count,&real_tty);
    if (status == TCL_ERROR) finish(TCL_ERROR);

    if (real_tty) {
	tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
    }

    for (inp = input_base,i=0;inp;inp=inp->next,i++) {
	/* start timers */
	inp->timeout_remaining = inp->timeout_nominal;
    }

    key = expect_key++;

    /* declare ourselves "in sync" with external view of close/indirect */
    configure_count = exp_configure_count;
    
#ifndef SIMPLE_EVENT
    /* loop waiting (in event handler) for input */
    for (;;) {
	int te;	/* result of Tcl_Eval */

	int rc;	/* return code from ready.  This is further refined by matcher. */

	int cc;			/* # of chars from read() */


	struct action *action = 0;
	time_t previous_time;
	time_t current_time;
	int matchLen;	/* # of chars matched */
	int skip;		/* # of chars not involved in match */
	int print;		/* # of chars to print */
	int oldprinted;		/* old version of u->printed */
	int change;		/* if action requires cooked mode */
	int attempt_match = TRUE;
	struct input *soonest_input;



	int timeout;	/* current as opposed to default_timeout */

	/* calculate how long to wait */
	/* by finding shortest remaining timeout */
	if (timeout_simple) {
	    timeout = default_timeout;
	} else {
	    timeout = arbitrary_timeout;

	    for (inp=input_base;inp;inp=inp->next) {
		if ((inp->timeout_remaining != EXP_TIME_INFINITY) &&
			(inp->timeout_remaining <= timeout)) {
		    soonest_input = inp;
		    timeout = inp->timeout_remaining;
		}
	    }

	    time(&previous_time);
	    /* timestamp here rather than simply saving old */
	    /* current time (after ready()) to account for */
	    /* possibility of slow actions */
	    
	    /* timeout can actually be EXP_TIME_INFINITY here if user */
	    /* explicitly supplied it in a few cases (or */
	    /* the count-down code is broken) */
	}

	/* update the world, if necessary */
	if (configure_count != exp_configure_count) {
	    status = update_interact_fds(interp,&input_count,
		    &esPtrToInput,&esPtrs,input_base,1,
		    &configure_count,&real_tty);
	    if (status) finish(status);
	}

	rc = exp_get_next_event(interp,esPtrs,input_count,&u,timeout,key);
	if (rc == EXP_TCLERROR) return(TCL_ERROR);

	if (rc == EXP_RECONFIGURE) continue;

	if (rc == EXP_TIMEOUT) {
	    if (timeout_simple) {
		action = &action_timeout;
		goto got_action;
	    } else {
		action = soonest_input->action_timeout;
		/* arbitrarily pick first fd out of list */
		u = soonest_input->i_list->state_list->esPtr;
	    }
	}
	if (!timeout_simple) {
	    int time_diff;

	    time(&current_time);
	    time_diff = current_time - previous_time;

	    /* update all timers */
	    for (inp=input_base;inp;inp=inp->next) {
		if (inp->timeout_remaining != EXP_TIME_INFINITY) {
		    inp->timeout_remaining -= time_diff;
		    if (inp->timeout_remaining < 0)
			inp->timeout_remaining = 0;
		}
	    }
	}

	/* at this point, we have some kind of event which can be */
	/* immediately processed - i.e. something that doesn't block */

	/* figure out who we are */


	inp = expStateToInput(esPtrToInput,u);

	/* reset timer */
	inp->timeout_remaining = inp->timeout_nominal;

	switch (rc) {
	    case EXP_DATA_NEW:



		cc = intRead(interp,u,1,0,key);









		if (cc > 0) break;



















		rc = EXP_EOF;

		/*
		 * FALLTHRU
		 *

		 * Most systems have read() return 0, allowing
		 * control to fall thru and into this code.  On some
		 * systems (currently HP and new SGI), read() does
		 * see eof, and it must be detected earlier.  Then
		 * control jumps directly to this EXP_EOF label.
		 */

	    case EXP_EOF:
		action = inp->action_eof;
		attempt_match = FALSE;
		skip = expSizeGet(u);
		expDiagLog("interact: received eof from spawn_id %s\r\n",u->name);
		/* actual close is done later so that we have a */
		/* chance to flush out any remaining characters */
		need_to_close_master = TRUE;










		break;
	    case EXP_DATA_OLD:
		cc = 0;
		break;
	    case EXP_TIMEOUT:
		action = inp->action_timeout;
		attempt_match = FALSE;
		skip = expSizeGet(u);
		break;
	}

	km = 0;

	if (attempt_match) {





	    rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo);

	    if ((rc == EXP_MATCH) && km && km->re) {



		intRegExpMatchProcess(interp,u,km,&reInfo,skip);




	    }


	} else {

	    attempt_match = TRUE;






















	}

	/*
	 * dispose of chars that should be skipped
	 * i.e., chars that cannot possibly be part of a match.
	 */




	if (km && km->writethru) {
	    print = skip + matchLen;
	} else print = skip;




	if (km && km->echo) {

	    intEcho(u,skip,matchLen);


	}











	oldprinted = u->printed;

	/*
	 * If expect has left characters in buffer, it has
	 * already echoed them to the screen, thus we must
	 * prevent them being rewritten.  Unfortunately this
	 * gives the possibility of matching chars that have
	 * already been output, but we do so since the user
	 * could have avoided it by flushing the output
	 * buffers directly.
	 */
	if (print > u->printed) {	/* usual case */

	    for (outp = inp->output;outp;outp=outp->next) {
		struct exp_state_list *fdp;
		for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) {

		    /* send to channel (and log if chan is stdout or devtty) */

		    /*




		     * Following should eventually be rewritten to ...WriteCharsAnd...





		     */
		    int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr,
			    Tcl_GetString(u->buffer) + u->printed,
			    print - u->printed);
		    if (wc <= 0) {
			expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp));
			action = outp->action_eof;
			change = (action && action->tty_reset);
			
			if (change && tty_changed)
			    exp_tty_set(interp,&tty_old,was_raw,was_echo);
			te = inter_eval(interp,action,u);

			if (change && real_tty) tty_changed =
						    exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
			switch (te) {
			    case TCL_BREAK:
			    case TCL_CONTINUE:
				finish(te);
			    case EXP_TCL_RETURN:
				finish(TCL_RETURN);
			    case TCL_RETURN:
				finish(TCL_OK);
			    case TCL_OK:
				/* god knows what the user might */
				/* have done to us in the way of */
				/* closed fds, so .... */
				action = 0;	/* reset action */
				continue;
			    default:
				finish(te);
			}
		    }
		}
	    }
	    u->printed = print;
	}
	
	/* u->printed is now accurate with respect to the buffer */
	/* However, we're about to shift the old data out of the */
	/* buffer.  Thus size, printed, and echoed must be */
	/* updated */
	
	/* first update size based on skip information */
	/* then set skip to the total amount skipped */

	size = expSizeGet(u);
	if (rc == EXP_MATCH) {
	    action = &km->action;

	    skip += matchLen;
	    size -= skip;

	    if (size) {
		string = Tcl_GetString(u->buffer);
		memmove(string, string + skip, size);
	    }
	} else {
	    string = Tcl_GetString(u->buffer);
	    if (skip) {
		size -= skip;
		memcpy(string, string + skip, size);

	    }
	}
	Tcl_SetObjLength(u->buffer,size);











	/* now update printed based on total amount skipped */

	u->printed -= skip;
	/* if more skipped than printed (i.e., keymap encountered) */
	/* for printed positive */
	if (u->printed < 0) u->printed = 0;

	/* if we are in the middle of a match, force the next event */
	/* to wait for more data to arrive */
	u->force_read = (rc == EXP_CANMATCH);

	/* finally reset echoed if necessary */
	if (rc != EXP_CANMATCH) {
	    if (skip >= oldprinted + u->echoed) u->echoed = 0;
	}

	if (rc == EXP_EOF) {
	    exp_close(interp,u);
	    need_to_close_master = FALSE;
	}

	if (action) {
got_action:
	    change = (action && action->tty_reset);
	    if (change && tty_changed)
		exp_tty_set(interp,&tty_old,was_raw,was_echo);

	    te = inter_eval(interp,action,u);

	    if (change && real_tty) tty_changed =
					exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
	    switch (te) {
		case TCL_BREAK:
		case TCL_CONTINUE:
		    finish(te);
		case EXP_TCL_RETURN:
		    finish(TCL_RETURN);
		case TCL_RETURN:
		    finish(TCL_OK);
		case TCL_OK:
		    /* god knows what the user might */
		    /* have done to us in the way of */
		    /* closed fds, so .... */
		    action = 0;	/* reset action */
		    continue;
		default:
		    finish(te);
	    }
	}
    }

#else /* SIMPLE_EVENT */
/*	deferred_interrupt = FALSE;*/
{
		int te;	/* result of Tcl_Eval */
		ExpState *u;    /*master*/
		int rc;	/* return code from ready.  This is further */
			/* refined by matcher. */
		int cc;	/* chars count from read() */

		struct action *action = 0;
		time_t previous_time;
		time_t current_time;
		int matchLen, skip;
		int change;	/* if action requires cooked mode */
		int attempt_match = TRUE;
		struct input *soonest_input;
		int print;		/* # of chars to print */
		int oldprinted;		/* old version of u->printed */

		int timeout;	/* current as opposed to default_timeout */

	if (-1 == (pid = fork())) {
		exp_error(interp,"fork: %s",Tcl_PosixError(interp));
		finish(TCL_ERROR);
	}
	if (pid == 0) {
	    /*
	     * This is a new child process.
	     * It exists only for this interact command and will go away when
	     * the interact returns.
	     *
	     * The purpose of this child process is to read output from the
	     * spawned process and send it to the user tty.
	     * (See diagram above.)
	     */

	    exp_close(interp,expStdinoutGet());

	    u = esPtrs[1];  /* get 2nd ExpState */
	    input_count = 1;

	    while (1) {

		/* calculate how long to wait */
		/* by finding shortest remaining timeout */
		if (timeout_simple) {
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579

1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
1745
1746

1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797








1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815

			/* timeout can actually be EXP_TIME_INFINITY here if user */
			/* explicitly supplied it in a few cases (or */
			/* the count-down code is broken) */
		}

		/* +1 so we can look at the "other" file descriptor */
		rc = exp_get_next_event(interp,fd_list+1,input_count,&m,timeout,key);
		if (!timeout_simple) {
			int time_diff;

			time(&current_time);
			time_diff = current_time - previous_time;

			/* update all timers */
			for (inp=input_base;inp;inp=inp->next) {
				if (inp->timeout_remaining != EXP_TIME_INFINITY) {
					inp->timeout_remaining -= time_diff;
					if (inp->timeout_remaining < 0)
						inp->timeout_remaining = 0;
				}
			}
		}

		/* at this point, we have some kind of event which can be */
		/* immediately processed - i.e. something that doesn't block */

		/* figure out who we are */
		inp = fd_to_input[m];
/*		u = inp->f;*/
		u = exp_fs+m;

		switch (rc) {
		case EXP_DATA_NEW:
			cc = read(m,	u->buffer + u->size,
					u->msize - u->size);
			if (cc > 0) {
				u->key = key;
				u->size += cc;
				u->buffer[u->size] = '\0';

				/* strip parity if requested */
				if (u->parity == 0) {
					/* do it from end backwards */
					char *p = u->buffer + u->size - 1;
					int count = cc;
					while (count--) {
						*p-- &= 0x7f;
					}
				}

				/* avoid another function call if possible */
				if (debugfile || is_debugging) {
					debuglog("spawn id %d sent <%s>\r\n",m,
						exp_printify(u->buffer + u->size - cc));
				}
				break;
			}
			/*FALLTHRU*/

			/* Most systems have read() return 0, allowing */
			/* control to fall thru and into this code.  On some */
			/* systems (currently HP and new SGI), read() does */
			/* see eof, and it must be detected earlier.  Then */
			/* control jumps directly to this EXP_EOF label. */

		case EXP_EOF:
			action = inp->action_eof;
			attempt_match = FALSE;
			skip = u->size;
			rc = EXP_EOF;
			debuglog("interact: child received eof from spawn_id %d\r\n",m);
			exp_close(interp,m);
			break;
		case EXP_DATA_OLD:
			cc = 0;
			break;
		}

		km = 0;

		if (attempt_match) {
			rc = in_keymap(u->buffer,u->size,inp->keymap,
				&km,&match_length,&skip);
		} else {
			attempt_match = TRUE;
		}

		/* put regexp result in variables */
		if (km && km->re) {
#define INTER_OUT "interact_out"
#define out(i,val)  debuglog("expect: set %s(%s) \"%s\"\r\n",INTER_OUT,i, \
						dprintify(val)); \
		    Tcl_SetVar2(interp,INTER_OUT,i,val,0);

			char name[20], value[20];
			regexp *re = km->re;
			char match_char;/* place to hold char temporarily */
					/* uprooted by a NULL */

			for (i=0;i<NSUBEXP;i++) {
				int offset;

				if (re->startp[i] == 0) continue;

				if (km->indices) {
				  /* start index */
				  sprintf(name,"%d,start",i);
				  offset = re->startp[i]-u->buffer;
				  sprintf(value,"%d",offset);
				  out(name,value);

				  /* end index */
				  sprintf(name,"%d,end",i);
				  sprintf(value,"%d",re->endp[i]-u->buffer-1);
				  out(name,value);
				}

				/* string itself */
				sprintf(name,"%d,string",i);
				/* temporarily null-terminate in */
				/* middle */
				match_char = *re->endp[i];
				*re->endp[i] = 0;
				out(name,re->startp[i]);
				*re->endp[i] = match_char;
			}
		}

		/* dispose of chars that should be skipped */
		
		/* skip is chars not involved in match */
		/* print is with chars involved in match */

		if (km && km->writethru) {
			print = skip + match_length;
		} else print = skip;

		/* figure out if we should echo any chars */
		if (km && km->echo) {
			int seen;	/* either printed or echoed */

			/* echo to stdout rather than stdin */
			if (m == 0) m = 1;

			/* write is unlikely to fail, since we just read */
			/* from same descriptor */
			seen = u->printed + u->echoed;
			if (skip >= seen) {
				write(m,u->buffer+skip,match_length);
			} else if ((match_length + skip - seen) > 0) {
				write(m,u->buffer+seen,match_length+skip-seen);
			}
			u->echoed = match_length + skip - u->printed;
		}

		oldprinted = u->printed;

		/* If expect has left characters in buffer, it has */
		/* already echoed them to the screen, thus we must */
		/* prevent them being rewritten.  Unfortunately this */
		/* gives the possibility of matching chars that have */
		/* already been output, but we do so since the user */
		/* could have avoided it by flushing the output */
		/* buffers directly. */
		if (print > u->printed) {	/* usual case */
			int wc;	/* return code from write() */
			for (outp = inp->output;outp;outp=outp->next) {
			    struct exp_fd_list *fdp;
			    for (fdp = outp->i_list->fd_list;fdp;fdp=fdp->next) {
				int od;	/* output descriptor */

				/* send to logfile if open */
				/* and user is seeing it */
				if (logfile && real_tty_output(fdp->fd)) {
					fwrite(u->buffer+u->printed,1,
					       print - u->printed,logfile);
				}

				/* send to each output descriptor */
				od = fdp->fd;
				/* if opened by Tcl, it may use a different */
				/* output descriptor */
				od = (exp_fs[od].tcl_handle?exp_fs[od].tcl_output:od);

				wc = write(od,u->buffer+u->printed,
					print - u->printed);
				if (wc <= 0) {
					debuglog("interact: write on spawn id %d failed (%s)\r\n",fdp->fd,Tcl_PosixError(interp));
					action = outp->action_eof;

					te = inter_eval(interp,action,m);

					switch (te) {
					case TCL_BREAK:
					case TCL_CONTINUE:
						finish(te);
					case EXP_TCL_RETURN:
						finish(TCL_RETURN);
					case TCL_RETURN:
						finish(TCL_OK);
					case TCL_OK:
						/* god knows what the user might */
						/* have done to us in the way of */
						/* closed fds, so .... */
						action = 0;	/* reset action */
						continue;
					default:
						finish(te);
					}
				}
			    }
			}
			u->printed = print;
		}

		/* u->printed is now accurate with respect to the buffer */
		/* However, we're about to shift the old data out of the */
		/* buffer.  Thus, u->size, printed, and echoed must be */
		/* updated */

		/* first update size based on skip information */
		/* then set skip to the total amount skipped */


		if (rc == EXP_MATCH) {
			action = &km->action;

			skip += match_length;
			u->size -= skip;

			if (u->size)
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);

		} else {
			if (skip) {
				u->size -= skip;
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);
			}
		}

		/* as long as buffer is still around, null terminate it */
		if (rc != EXP_EOF) {
			u->buffer[u->size] = '\0';
			u->lower [u->size] = '\0';
		}
		/* now update printed based on total amount skipped */

		u->printed -= skip;
		/* if more skipped than printed (i.e., keymap encountered) */
		/* for printed positive */
		if (u->printed < 0) u->printed = 0;

		/* if we are in the middle of a match, force the next event */
		/* to wait for more data to arrive */
		u->force_read = (rc == EXP_CANMATCH);

		/* finally reset echoed if necessary */
		if (rc != EXP_CANMATCH) {
			if (skip >= oldprinted + u->echoed) u->echoed = 0;
		}

		if (action) {
			te = inter_eval(interp,action,m);
			switch (te) {
			case TCL_BREAK:
			case TCL_CONTINUE:
				finish(te);
			case EXP_TCL_RETURN:
				finish(TCL_RETURN);
			case TCL_RETURN:
				finish(TCL_OK);
			case TCL_OK:
				/* god knows what the user might */
				/* have done to us in the way of */
				/* closed fds, so .... */
				action = 0;	/* reset action */
				continue;
			default:
				finish(te);
			}
		}
	    }
	} else { /* parent - send user keystrokes to process */








#include <signal.h>

#if defined(SIGCLD) && !defined(SIGCHLD)
#define SIGCHLD SIGCLD
#endif
		debuglog("fork = %d\r\n",pid);
		signal(SIGCHLD,sigchld_handler);
/*	restart:*/
/*		tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);*/

	    m = fd_list[0];	/* get 1st fd */
	    input_count = 1;

	    while (1) {
		/* calculate how long to wait */
		/* by finding shortest remaining timeout */
		if (timeout_simple) {
			timeout = default_timeout;







|




















<
<
|



|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
>



|

|
|









<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|


<

<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<










<
|
|
|
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|





>
|
|

|
|
<
|
|
<
>

|
|
|
<
|

|
<
<
<
<
|

















|



















|
>
>
>
>
>
>
>
>





|




|







1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643


1644
1645
1646
1647
1648

1649



1650

















1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674





1675

1676




1677




1678


1679

1680






















1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691

1692

1693


1694











1695
1696
1697
1698
1699
1700
1701
1702
1703
1704

1705
1706
1707

1708






1709





1710

1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754

1755
1756

1757
1758
1759
1760
1761

1762
1763
1764




1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829

			/* timeout can actually be EXP_TIME_INFINITY here if user */
			/* explicitly supplied it in a few cases (or */
			/* the count-down code is broken) */
		}

		/* +1 so we can look at the "other" file descriptor */
		rc = exp_get_next_event(interp,esPtrs+1,input_count,&u,timeout,key);
		if (!timeout_simple) {
			int time_diff;

			time(&current_time);
			time_diff = current_time - previous_time;

			/* update all timers */
			for (inp=input_base;inp;inp=inp->next) {
				if (inp->timeout_remaining != EXP_TIME_INFINITY) {
					inp->timeout_remaining -= time_diff;
					if (inp->timeout_remaining < 0)
						inp->timeout_remaining = 0;
				}
			}
		}

		/* at this point, we have some kind of event which can be */
		/* immediately processed - i.e. something that doesn't block */

		/* figure out who we are */


		inp = expStateToInput(esPtrToInput,u);

		switch (rc) {
		case EXP_DATA_NEW:
		    cc = intRead(interp,u,0,0,key);

		    if (cc > 0) break;



		    /*

















		     * FALLTHRU
		     *
		     * Most systems have read() return 0, allowing
		     * control to fall thru and into this code.  On some
		     * systems (currently HP and new SGI), read() does
		     * see eof, and it must be detected earlier.  Then
		     * control jumps directly to this EXP_EOF label.
		     */
		case EXP_EOF:
			action = inp->action_eof;
			attempt_match = FALSE;
			skip = expSizeGet(u);
			rc = EXP_EOF;
			expDiagLog("interact: child received eof from spawn_id %s\r\n",u->name);
			exp_close(interp,u);
			break;
		case EXP_DATA_OLD:
			cc = 0;
			break;
		}

		km = 0;

		if (attempt_match) {





		    rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo);

		    if ((rc == EXP_MATCH) && km && km->re) {




			intRegExpMatchProcess(interp,u,km,&reInfo,skip);




		    }


		} else {

		    attempt_match = TRUE;






















		}

		/* dispose of chars that should be skipped */
		
		/* skip is chars not involved in match */
		/* print is with chars involved in match */

		if (km && km->writethru) {
			print = skip + matchLen;
		} else print = skip;


		if (km && km->echo) {

		    intEcho(u,skip,matchLen);


		}











		oldprinted = u->printed;

		/* If expect has left characters in buffer, it has */
		/* already echoed them to the screen, thus we must */
		/* prevent them being rewritten.  Unfortunately this */
		/* gives the possibility of matching chars that have */
		/* already been output, but we do so since the user */
		/* could have avoided it by flushing the output */
		/* buffers directly. */
		if (print > u->printed) {	/* usual case */

		    for (outp = inp->output;outp;outp=outp->next) {
			struct exp_state_list *fdp;
			for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) {

			    /* send to channel (and log if chan is stdout or devtty) */






			    int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr,





				    Tcl_GetString(u->buffer) + u->printed,

				    print - u->printed);
			    if (wc <= 0) {
				expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp));
				action = outp->action_eof;

				te = inter_eval(interp,action,u);

				switch (te) {
				    case TCL_BREAK:
				    case TCL_CONTINUE:
					finish(te);
				    case EXP_TCL_RETURN:
					finish(TCL_RETURN);
				    case TCL_RETURN:
					finish(TCL_OK);
				    case TCL_OK:
					/* god knows what the user might */
					/* have done to us in the way of */
					/* closed fds, so .... */
					action = 0;	/* reset action */
					continue;
				    default:
					finish(te);
				}
			    }
			}
		    }
		    u->printed = print;
		}

		/* u->printed is now accurate with respect to the buffer */
		/* However, we're about to shift the old data out of the */
		/* buffer.  Thus size, printed, and echoed must be */
		/* updated */

		/* first update size based on skip information */
		/* then set skip to the total amount skipped */

		size = expSizeGet(u);
		if (rc =n= EXP_MATCH) {
		    action = &km->action;

		    skip += matchLen;
		    size -= skip;

		    if (size) {
			memcpy(u->buffer, u->buffer + skip, size);

		    }
		} else {
		    if (skip) {
			size -= skip;
			memcpy(u->buffer, u->buffer + skip, size);

		    }
		}
		Tcl_SetObjLength(size);





		/* now update printed based on total amount skipped */

		u->printed -= skip;
		/* if more skipped than printed (i.e., keymap encountered) */
		/* for printed positive */
		if (u->printed < 0) u->printed = 0;

		/* if we are in the middle of a match, force the next event */
		/* to wait for more data to arrive */
		u->force_read = (rc == EXP_CANMATCH);

		/* finally reset echoed if necessary */
		if (rc != EXP_CANMATCH) {
			if (skip >= oldprinted + u->echoed) u->echoed = 0;
		}

		if (action) {
			te = inter_eval(interp,action,u);
			switch (te) {
			case TCL_BREAK:
			case TCL_CONTINUE:
				finish(te);
			case EXP_TCL_RETURN:
				finish(TCL_RETURN);
			case TCL_RETURN:
				finish(TCL_OK);
			case TCL_OK:
				/* god knows what the user might */
				/* have done to us in the way of */
				/* closed fds, so .... */
				action = 0;	/* reset action */
				continue;
			default:
				finish(te);
			}
		}
	    }
	} else {
	    /*
	     * This is the original Expect process.
	     *
	     * It now loops, reading keystrokes from the user tty
	     * and sending them to the spawned process.
	     * (See diagram above.)
	     */

#include <signal.h>

#if defined(SIGCLD) && !defined(SIGCHLD)
#define SIGCHLD SIGCLD
#endif
		expDiagLog("fork = %d\r\n",pid);
		signal(SIGCHLD,sigchld_handler);
/*	restart:*/
/*		tty_changed = exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);*/

	    u = esPtrs[0];  /* get 1st ExpState */
	    input_count = 1;

	    while (1) {
		/* calculate how long to wait */
		/* by finding shortest remaining timeout */
		if (timeout_simple) {
			timeout = default_timeout;
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904

1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061

2062
2063
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
			/* possibility of slow actions */

			/* timeout can actually be EXP_TIME_INFINITY here if user */
			/* explicitly supplied it in a few cases (or */
			/* the count-down code is broken) */
		}

		rc = exp_get_next_event(interp,fd_list,input_count,&m,timeout,key);
		if (!timeout_simple) {
			int time_diff;

			time(&current_time);
			time_diff = current_time - previous_time;

			/* update all timers */
			for (inp=input_base;inp;inp=inp->next) {
				if (inp->timeout_remaining != EXP_TIME_INFINITY) {
					inp->timeout_remaining -= time_diff;
					if (inp->timeout_remaining < 0)
						inp->timeout_remaining = 0;
				}
			}
		}

		/* at this point, we have some kind of event which can be */
		/* immediately processed - i.e. something that doesn't block */

		/* figure out who we are */
		inp = fd_to_input[m];
/*		u = inp->f;*/
		u = exp_fs+m;

		switch (rc) {
		case EXP_DATA_NEW:
			cc = i_read(m,	u->buffer + u->size,
					u->msize - u->size);
			if (cc > 0) {
				u->key = key;
				u->size += cc;
				u->buffer[u->size] = '\0';

				/* strip parity if requested */
				if (u->parity == 0) {
					/* do it from end backwards */
					char *p = u->buffer + u->size - 1;
					int count = cc;
					while (count--) {
						*p-- &= 0x7f;
					}
				}

				/* avoid another function call if possible */
				if (debugfile || is_debugging) {
					debuglog("spawn id %d sent <%s>\r\n",m,
						exp_printify(u->buffer + u->size - cc));
				}
				break;
			} else if (cc == EXP_CHILD_EOF) {
				/* user could potentially have two outputs in which */
				/* case we might be looking at the wrong one, but */
				/* the likelihood of this is nil */
				action = inp->output->action_eof;
				attempt_match = FALSE;
				skip = u->size;
				rc = EXP_EOF;
				debuglog("interact: process died/eof\r\n");
				clean_up_after_child(interp,fd_list[1]);
				break;
			}

			/*FALLTHRU*/

			/* Most systems have read() return 0, allowing */
			/* control to fall thru and into this code.  On some */
			/* systems (currently HP and new SGI), read() does */
			/* see eof, and it must be detected earlier.  Then */
			/* control jumps directly to this EXP_EOF label. */

		case EXP_EOF:
			action = inp->action_eof;
			attempt_match = FALSE;
			skip = u->size;
			rc = EXP_EOF;
			debuglog("user sent EOF or disappeared\n\n");
			break;
		case EXP_DATA_OLD:
			cc = 0;
			break;
		}

		km = 0;

		if (attempt_match) {
			rc = in_keymap(u->buffer,u->size,inp->keymap,
				&km,&match_length,&skip);
		} else {
			attempt_match = TRUE;
		}

		/* put regexp result in variables */
		if (km && km->re) {
			char name[20], value[20];
			regexp *re = km->re;
			char match_char;/* place to hold char temporarily */
					/* uprooted by a NULL */

			for (i=0;i<NSUBEXP;i++) {
				int offset;

				if (re->startp[i] == 0) continue;

				if (km->indices) {
				  /* start index */
				  sprintf(name,"%d,start",i);
				  offset = re->startp[i]-u->buffer;
				  sprintf(value,"%d",offset);
				  out(name,value);

				  /* end index */
				  sprintf(name,"%d,end",i);
				  sprintf(value,"%d",re->endp[i]-u->buffer-1);
				  out(name,value);
				}

				/* string itself */
				sprintf(name,"%d,string",i);
				/* temporarily null-terminate in */
				/* middle */
				match_char = *re->endp[i];
				*re->endp[i] = 0;
				out(name,re->startp[i]);
				*re->endp[i] = match_char;
			}
		}

		/* dispose of chars that should be skipped */
		
		/* skip is chars not involved in match */
		/* print is with chars involved in match */

		if (km && km->writethru) {
			print = skip + match_length;
		} else print = skip;

		/* figure out if we should echo any chars */
		if (km && km->echo) {
			int seen;	/* either printed or echoed */

			/* echo to stdout rather than stdin */
			if (m == 0) m = 1;

			/* write is unlikely to fail, since we just read */
			/* from same descriptor */
			seen = u->printed + u->echoed;
			if (skip >= seen) {
				write(m,u->buffer+skip,match_length);
			} else if ((match_length + skip - seen) > 0) {
				write(m,u->buffer+seen,match_length+skip-seen);
			}
			u->echoed = match_length + skip - u->printed;
		}

		oldprinted = u->printed;

		/* If expect has left characters in buffer, it has */
		/* already echoed them to the screen, thus we must */
		/* prevent them being rewritten.  Unfortunately this */
		/* gives the possibility of matching chars that have */
		/* already been output, but we do so since the user */
		/* could have avoided it by flushing the output */
		/* buffers directly. */
		if (print > u->printed) {	/* usual case */
			int wc;	/* return code from write() */
			for (outp = inp->output;outp;outp=outp->next) {
			    struct exp_fd_list *fdp;
			    for (fdp = outp->i_list->fd_list;fdp;fdp=fdp->next) {
				int od;	/* output descriptor */

				/* send to logfile if open */
				/* and user is seeing it */
				if (logfile && real_tty_output(fdp->fd)) {
					fwrite(u->buffer+u->printed,1,
					       print - u->printed,logfile);
				}

				/* send to each output descriptor */
				od = fdp->fd;
				/* if opened by Tcl, it may use a different */
				/* output descriptor */
				od = (exp_fs[od].tcl_handle?exp_fs[od].tcl_output:od);

				wc = write(od,u->buffer+u->printed,
					print - u->printed);
				if (wc <= 0) {
					debuglog("interact: write on spawn id %d failed (%s)\r\n",fdp->fd,Tcl_PosixError(interp));
					clean_up_after_child(interp,fdp->fd);
					action = outp->action_eof;
					change = (action && action->tty_reset);
					if (change && tty_changed)
						exp_tty_set(interp,&tty_old,was_raw,was_echo);
					te = inter_eval(interp,action,m);

					if (change && real_tty) tty_changed =
					   exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
					switch (te) {
					case TCL_BREAK:
					case TCL_CONTINUE:
						finish(te);
					case EXP_TCL_RETURN:
						finish(TCL_RETURN);
					case TCL_RETURN:
						finish(TCL_OK);
					case TCL_OK:
						/* god knows what the user might */
						/* have done to us in the way of */
						/* closed fds, so .... */
						action = 0;	/* reset action */
						continue;
					default:
						finish(te);
					}
				}
			    }
			}
			u->printed = print;
		}

		/* u->printed is now accurate with respect to the buffer */
		/* However, we're about to shift the old data out of the */
		/* buffer.  Thus, u->size, printed, and echoed must be */
		/* updated */

		/* first update size based on skip information */
		/* then set skip to the total amount skipped */


		if (rc == EXP_MATCH) {
			action = &km->action;

			skip += match_length;
			u->size -= skip;

			if (u->size)
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);

		} else {
			if (skip) {
				u->size -= skip;
				memcpy(u->buffer, u->buffer + skip, u->size);
				exp_lowmemcpy(u->lower,u->buffer+ skip, u->size);
			}
		}

		/* as long as buffer is still around, null terminate it */
		if (rc != EXP_EOF) {
			u->buffer[u->size] = '\0';
			u->lower [u->size] = '\0';
		}
		/* now update printed based on total amount skipped */

		u->printed -= skip;
		/* if more skipped than printed (i.e., keymap encountered) */
		/* for printed positive */
		if (u->printed < 0) u->printed = 0;








|




















<
<
|



|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|

|
|


>
|
|
|
|
|
|
|
>



|

|









<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|


<

<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<










<
|
|
|
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|





>

|

|
|
<
|
|
<
>

|
|
|
<
|

|
<
<
<
<
|







1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870


1871
1872
1873
1874
1875

1876



















1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913





1914

1915




1916


1917

1918






1919















1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930

1931

1932


1933











1934
1935
1936
1937
1938
1939
1940
1941
1942
1943

1944
1945
1946

1947






1948





1949

1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998

1999
2000

2001
2002
2003
2004
2005

2006
2007
2008




2009
2010
2011
2012
2013
2014
2015
2016
			/* possibility of slow actions */

			/* timeout can actually be EXP_TIME_INFINITY here if user */
			/* explicitly supplied it in a few cases (or */
			/* the count-down code is broken) */
		}

		rc = exp_get_next_event(interp,esPtrs,input_count,&u,timeout,key);
		if (!timeout_simple) {
			int time_diff;

			time(&current_time);
			time_diff = current_time - previous_time;

			/* update all timers */
			for (inp=input_base;inp;inp=inp->next) {
				if (inp->timeout_remaining != EXP_TIME_INFINITY) {
					inp->timeout_remaining -= time_diff;
					if (inp->timeout_remaining < 0)
						inp->timeout_remaining = 0;
				}
			}
		}

		/* at this point, we have some kind of event which can be */
		/* immediately processed - i.e. something that doesn't block */

		/* figure out who we are */


		inp = expStateToInput(esPtrToInput,u);

		switch (rc) {
		case EXP_DATA_NEW:
		        cc = intRead(interp,u,0,1,key);

		        if (cc > 0) {



















				break;
			} else if (cc == EXP_CHILD_EOF) {
				/* user could potentially have two outputs in which */
				/* case we might be looking at the wrong one, but */
				/* the likelihood of this is nil */
				action = inp->output->action_eof;
				attempt_match = FALSE;
				skip = expSizeGet(u);
				rc = EXP_EOF;
				expDiagLogU("interact: process died/eof\r\n");
				clean_up_after_child(interp,esPtrs[1]);
				break;
			}
			/*
			 * FALLTHRU
			 *
			 * Most systems have read() return 0, allowing
			 * control to fall thru and into this code.  On some
			 * systems (currently HP and new SGI), read() does
			 * see eof, and it must be detected earlier.  Then
			 * control jumps directly to this EXP_EOF label.
			 */
		case EXP_EOF:
			action = inp->action_eof;
			attempt_match = FALSE;
			skip = expSizeGet(u);
			rc = EXP_EOF;
			expDiagLogU("user sent EOF or disappeared\n\n");
			break;
		case EXP_DATA_OLD:
			cc = 0;
			break;
		}

		km = 0;

		if (attempt_match) {





		    rc = intMatch(u,inp->keymap,&km,&matchLen,&skip,&reInfo);

		    if ((rc == EXP_MATCH) && km && km->re) {




			intRegExpMatchProcess(interp,u,km,&reInfo,skip);


		    }

		} else {






		    attempt_match = TRUE;















		}

		/* dispose of chars that should be skipped */
		
		/* skip is chars not involved in match */
		/* print is with chars involved in match */

		if (km && km->writethru) {
			print = skip + matchLen;
		} else print = skip;


		if (km && km->echo) {

		    intEcho(u,skip,matchLen);


		}











		oldprinted = u->printed;

		/* If expect has left characters in buffer, it has */
		/* already echoed them to the screen, thus we must */
		/* prevent them being rewritten.  Unfortunately this */
		/* gives the possibility of matching chars that have */
		/* already been output, but we do so since the user */
		/* could have avoided it by flushing the output */
		/* buffers directly. */
		if (print > u->printed) {	/* usual case */

		    for (outp = inp->output;outp;outp=outp->next) {
			struct exp_state_list *fdp;
			for (fdp = outp->i_list->state_list;fdp;fdp=fdp->next) {

			    /* send to channel (and log if chan is stdout or devtty) */






			    int wc = expWriteBytesAndLogIfTtyU(fdp->esPtr,





				    Tcl_GetString(u->buffer) + u->printed,

				    print - u->printed);
			    if (wc <= 0) {
				expDiagLog("interact: write on spawn id %s failed (%s)\r\n",fdp->esPtr->name,Tcl_PosixError(interp));
				clean_up_after_child(interp,fdp->esPtr);
				action = outp->action_eof;
				change = (action && action->tty_reset);
				if (change && tty_changed)
				    exp_tty_set(interp,&tty_old,was_raw,was_echo);
				te = inter_eval(interp,action,u);

				if (change && real_tty) tty_changed =
							    exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
				switch (te) {
				    case TCL_BREAK:
				    case TCL_CONTINUE:
					finish(te);
				    case EXP_TCL_RETURN:
					finish(TCL_RETURN);
				    case TCL_RETURN:
					finish(TCL_OK);
				    case TCL_OK:
					/* god knows what the user might */
					/* have done to us in the way of */
					/* closed fds, so .... */
					action = 0;	/* reset action */
					continue;
				    default:
					finish(te);
				}
			    }
			}
		    }
		    u->printed = print;
		}

		/* u->printed is now accurate with respect to the buffer */
		/* However, we're about to shift the old data out of the */
		/* buffer.  Thus size, printed, and echoed must be */
		/* updated */

		/* first update size based on skip information */
		/* then set skip to the total amount skipped */

		size = expSizeGet(u);
		if (rc == EXP_MATCH) {
		    action = &km->action;

		    skip += matchLen;
		    size -= skip;

		    if (size) {
			memcpy(u->buffer, u->buffer + skip, size);

		    }
		} else {
		    if (skip) {
			size -= skip;
			memcpy(u->buffer, u->buffer + skip, size);

		    }
		}
		Tcl_SetObjLength(size);





		/* now update printed based on total amount skipped */

		u->printed -= skip;
		/* if more skipped than printed (i.e., keymap encountered) */
		/* for printed positive */
		if (u->printed < 0) u->printed = 0;

2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
		}

		if (action) {
			change = (action && action->tty_reset);
			if (change && tty_changed)
				exp_tty_set(interp,&tty_old,was_raw,was_echo);

			te = inter_eval(interp,action,m);

			if (change && real_tty) tty_changed =
			   exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
			switch (te) {
			case TCL_BREAK:
			case TCL_CONTINUE:
				finish(te);







|







2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
		}

		if (action) {
			change = (action && action->tty_reset);
			if (change && tty_changed)
				exp_tty_set(interp,&tty_old,was_raw,was_echo);

			te = inter_eval(interp,action,u);

			if (change && real_tty) tty_changed =
			   exp_tty_raw_noecho(interp,&tty_old,&was_raw,&was_echo);
			switch (te) {
			case TCL_BREAK:
			case TCL_CONTINUE:
				finish(te);
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
	    }
	}
}
#endif /* SIMPLE_EVENT */

 done:
#ifdef SIMPLE_EVENT
	/* force child to exit upon eof from master */
	if (pid == 0) {
		exit(SPAWNED_PROCESS_DIED);
	}
#endif /* SIMPLE_EVENT */

	if (need_to_close_master) exp_close(interp,master);

	if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
	if (oldargv) ckfree((char *)argv);
	if (fd_list) ckfree((char *)fd_list);
	if (fd_to_input) ckfree((char *)fd_to_input);
	free_input(interp,input_base);
	free_action(action_base);

	return(status);
}

/* version of Tcl_Eval for interact */ 
static int
inter_eval(interp,action,spawn_id)
Tcl_Interp *interp;
struct action *action;
int spawn_id;
{
	int status;
	char value[20];

	/* deprecated */
	if (action->timestamp) {
		time_t current_time;
		time(&current_time);
		exp_timestamp(interp,&current_time,INTER_OUT);
	}
	/* deprecated */

	if (action->iwrite) {
		sprintf(value,"%d",spawn_id);
		out("spawn_id",value);
	}

	if (action->statement) {
		status = Tcl_Eval(interp,action->statement);
	} else {
		exp_nflog("\r\n",1);
		status = exp_interpreter(interp);
	}

	return status;
}

static void
free_keymap(km)
struct keymap *km;
{
	if (km == 0) return;







|
|
|
|


|

|
|
<
|
|
|

|




|


|

|
<

<
<
<
<
<
<
<
<
|
<
|
|

|
|
|
|
|
|

|







2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084

2085








2086

2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
	    }
	}
}
#endif /* SIMPLE_EVENT */

 done:
#ifdef SIMPLE_EVENT
    /* force child to exit upon eof from master */
    if (pid == 0) {
	exit(SPAWNED_PROCESS_DIED);
    }
#endif /* SIMPLE_EVENT */

    if (need_to_close_master) exp_close(interp,u);

    if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
    if (esPtrs) ckfree((char *)esPtrs);

    if (esPtrToInput) Tcl_DeleteHashTable(esPtrToInput);
    free_input(interp,input_base);
    free_action(action_base);

    return(status);
}

/* version of Tcl_Eval for interact */ 
static int
inter_eval(interp,action,esPtr)
Tcl_Interp *interp;
struct action *action;
ExpState *esPtr;
{
    int status;










    if (action->iwrite) {

	out("spawn_id",esPtr->name);
    }

    if (action->statement) {
	status = Tcl_EvalObjEx(interp,action->statement,0);
    } else {
	expStdoutLogU("\r\n",1);
	status = exp_interpreter(interp,(Tcl_Obj *)0);
    }

    return status;
}

static void
free_keymap(km)
struct keymap *km;
{
	if (km == 0) return;
2239
2240
2241
2242
2243
2244
2245
2246

2247
2248
2249
2250
2251
2252
2253
2254


2255
2256







{
	if (o == 0) return;
	free_output(interp,o->next);
	exp_free_i(interp,o->i_list,inter_updateproc);

	ckfree((char *)o);
}


static struct exp_cmd_data cmd_data[]  = {
{"interact",	exp_proc(Exp_InteractCmd),	0,	0},
{0}};

void
exp_init_interact_cmds(interp)
Tcl_Interp *interp;
{


	exp_create_commands(interp,cmd_data);
}















>

|






>
>
|
|
>
>
>
>
>
>
>
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
{
	if (o == 0) return;
	free_output(interp,o->next);
	exp_free_i(interp,o->i_list,inter_updateproc);

	ckfree((char *)o);
}


static struct exp_cmd_data cmd_data[]  = {
{"interact",	Exp_InteractObjCmd,	0,	0,	0},
{0}};

void
exp_init_interact_cmds(interp)
Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    exp_create_commands(interp,cmd_data);

    tsdPtr->cmdObjReturn = Tcl_NewStringObj("return",6);
    Tcl_IncrRefCount(tsdPtr->cmdObjReturn);
#if 0
    tsdPtr->cmdObjInterpreter = Tcl_NewStringObj("interpreter",11);
    Tcl_IncrRefCount(tsdPtr->cmdObjInterpreter);
#endif
}

Changes to exp_log.c.

1
2
3
4
5
6
7
8
9
10
11







12
13
14

15
16




17




18
19

20


21

22





23

24














25
26
27
28
29
30
31












































































32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52

53



54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77


78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118

119

120
121
122
123
124
125
126
127
128
129
130
131


132





133











































































134






















































135


136

137


138







139












140





141

142













143












144





145



146






































147



















































































148
149




150


151




















152


153

















154










155
156
157

158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
/* exp_log.c - logging routines and other things common to both Expect
   program and library.  Note that this file must NOT have any
   references to Tcl except for including tclInt.h
*/

#include "expect_cf.h"
#include <stdio.h>
/*#include <varargs.h>		tclInt.h drags in varargs.h.  Since Pyramid */
/*				objects to including varargs.h twice, just */
/*				omit this one. */
#include "tclInt.h"







#include "expect_comm.h"
#include "exp_int.h"
#include "exp_rename.h"

#include "exp_log.h"





int loguser = TRUE;		/* if TRUE, expect/spawn may write to stdout */




int logfile_all = FALSE;	/* if TRUE, write log of all interactions */
				/* despite value of loguser. */

FILE *logfile = 0;


FILE *debugfile = 0;

int exp_is_debugging = FALSE;







/* Following this are several functions that log the conversation. */














/* Most of them have multiple calls to printf-style functions.  */
/* At first glance, it seems stupid to reformat the same arguments again */
/* but we have no way of telling how long the formatted output will be */
/* and hence cannot allocate a buffer to do so. */
/* Fortunately, in production code, most of the duplicate reformatting */
/* will be skipped, since it is due to handling errors and debugging. */













































































/* send to log if open */
/* send to stderr if debugging enabled */
/* use this for logging everything but the parent/child conversation */
/* (this turns out to be almost nothing) */
/* uppercase L differentiates if from math function of same name */
#define LOGUSER		(loguser || force_stdout)
/*VARARGS*/
void
exp_log TCL_VARARGS_DEF(int,arg1)
/*exp_log(va_alist)*/
/*va_dcl*/
{

	int force_stdout;
	char *fmt;
	va_list args;

	force_stdout = TCL_VARARGS_START(int,arg1,args);
	/*va_start(args);*/
	/*force_stdout = va_arg(args,int);*/
	fmt = va_arg(args,char *);
	if (debugfile) vfprintf(debugfile,fmt,args);

	if (logfile_all || (LOGUSER && logfile)) vfprintf(logfile,fmt,args);



	if (LOGUSER) vfprintf(stdout,fmt,args);
	va_end(args);
}

/* just like log but does no formatting */
/* send to log if open */
/* use this function for logging the parent/child conversation */
void
exp_nflog(buf,force_stdout)
char *buf;
int force_stdout;	/* override value of loguser */
{

	int length = strlen(buf);

	if (debugfile) fwrite(buf,1,length,debugfile);
	if (logfile_all || (LOGUSER && logfile)) fwrite(buf,1,length,logfile);
	if (LOGUSER) fwrite(buf,1,length,stdout);
#if 0
	if (logfile_all || (LOGUSER && logfile)) {
		int newlength = exp_copy_out(length);
		fwrite(exp_out_buffer,1,newlength,logfile);
	}
#endif
}


#undef LOGUSER

/* send to log if open and debugging enabled */
/* send to stderr if debugging enabled */
/* use this function for recording unusual things in the log */
/*VARARGS*/
void

debuglog TCL_VARARGS_DEF(char *,arg1)
/*debuglog(va_alist)*/
/*va_dcl*/
{
	char *fmt;
	va_list args;

	fmt = TCL_VARARGS_START(char *,arg1,args);
	/*va_start(args);*/
	/*fmt = va_arg(args,char *);*/
	if (debugfile) vfprintf(debugfile,fmt,args);
	if (is_debugging) {
		vfprintf(stderr,fmt,args);
		if (logfile) vfprintf(logfile,fmt,args);
	}

	va_end(args);
}

/* send to log if open */
/* send to stderr */
/* use this function for error conditions */
/*VARARGS*/
void
exp_errorlog TCL_VARARGS_DEF(char *,arg1)
/*exp_errorlog(va_alist)*/

/*va_dcl*/
{
	char *fmt;
	va_list args;

	fmt = TCL_VARARGS_START(char *,arg1,args);
	/*va_start(args);*/
	/*fmt = va_arg(args,char *);*/

	vfprintf(stderr,fmt,args);

	if (debugfile) vfprintf(debugfile,fmt,args);
	if (logfile) vfprintf(logfile,fmt,args);
	va_end(args);
}

/* just like errorlog but does no formatting */
/* send to log if open */
/* use this function for logging the parent/child conversation */
/*ARGSUSED*/
void
exp_nferrorlog(buf,force_stdout)
char *buf;


int force_stdout;	/* not used, only declared here for compat with */





			/* exp_nflog() */











































































{






















































	int length = strlen(buf);


	fwrite(buf,1,length,stderr);

	if (debugfile) fwrite(buf,1,length,debugfile);


	if (logfile) fwrite(buf,1,length,logfile);







}


















#if 0

static int out_buffer_size;













static char *outp_last;












static char *out_buffer;





static char *outp;	/* pointer into out_buffer - static in order */



			/* to update whenever out_buffer is enlarged */



























































































































void




exp_init_log()


{




















	out_buffer = ckalloc(BUFSIZ);


	out_buffer_size = BUFSIZ;

















	outp_last = out_buffer + BUFSIZ - 1;










}

char *

enlarge_out_buffer()
{
	int offset = outp - out_buffer;

	int new_out_buffer_size = out_buffer_size = BUFSIZ;
	realloc(out_buffer,new_out_buffer_size);

	out_buffer_size = new_out_buffer_size;
	outp = out_buffer + offset;

	outp_last = out_buffer + out_buffer_size - 1;


	return(out_buffer);
}

/* like sprintf, but uses a static buffer enlarged as necessary */
/* currently supported are %s, %d, and %#d where # is a single-digit */
void
exp_sprintf TCL_VARARGS_DEF(char *,arg1)
/* exp_sprintf(va_alist)*/
/*va_dcl*/
{
	char *fmt;
	va_list args;
	char int_literal[20];	/* big enough for an int literal? */
	char *int_litp;		/* pointer into int_literal */
	char *width;
	char *string_arg;
	int int_arg;
	char *int_fmt;

	fmt = TCL_VARARGS_START(char *,arg1,args);
	/*va_start(args);*/
	/*fmt = va_arg(args,char *);*/

	while (*fmt != '\0') {
		if (*fmt != '%') {
			*outp++ = *fmt++;
			continue;
		}

		/* currently, only single-digit widths are used */
		if (isdigit(*fmt)) {
			width = fmt++;
		} else width = 0;

		switch (*fmt) {
		case 's':	/* interpolate string */
			string_arg = va_arg(args,char *);

			while (*string_arg) {
				if (outp == outp_last) {
					if (enlarge_out_buffer() == 0) {
						/* FAIL */
						return;
					}
				}
				*outp++ = *string_arg++;
			}
			fmt++;
			break;
		case 'd':	/* interpolate int */
			int_arg = va_arg(args,int);

			if (width) int_fmt = width;
			else int_fmt = fmt;

			sprintf(int_literal,int_fmt,int_arg);

			int_litp = int_literal;
			for (int_litp;*int_litp;) {
				if (enlarge_out_buffer() == 0) return;
				*outp++ = *int_litp++;
			}
			fmt++;
			break;
		default:	/* anything else is literal */
			if (enlarge_out_buffer() == 0) return;	/* FAIL */
			*outp++ = *fmt++;
			break;
		}
	}
}

/* copy input string to exp_output, replacing \r\n sequences by \n */
/* return length of new string */
int
exp_copy_out(char *s)
{
	outp = out_buffer;
	int count = 0;


	while (*s) {
		if ((*s == '\r') && (*(s+1) =='\n')) s++;
		if (enlarge_out_buffer() == 0) {
			/* FAIL */
			break;
		}
		*outp = *s;
		count++;
	}
	return count;
}
#endif











>
>
>
>
>
>
>



>


>
>
>
>
|
>
>
>
>
|
|
>
|
>
>
|
>
|
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|


|
<
<

>
|
|
|

|
<
<
|
|
>
|
>
>
>
|
|






|

|

>
|

<
|
<
<
<
<
<
|
|
<
>
>
|
|
<
<
<
<
<
>
|
<
|
<
<
<
|
<
<
<
<
|
<
<
|
<
<







|
<
>
|
|
|
|

|
|
|
>
|
>
|
<
|







|

>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>



>
|

<
|
<
<

<
<
|
<
>

|

|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
|
<
<
|
<
<
<
|

<
<
>

|
<
|
|
<
<
|
<
|
<
<
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156


157
158
159
160
161
162
163


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186





187
188

189
190
191
192





193
194

195



196




197


198


199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

634


635


636

637
638
639
640
641


642












643



644





645














646







647


648

649




650






651


652



653
654


655
656
657

658
659


660

661



/* exp_log.c - logging routines and other things common to both Expect
   program and library.  Note that this file must NOT have any
   references to Tcl except for including tclInt.h
*/

#include "expect_cf.h"
#include <stdio.h>
/*#include <varargs.h>		tclInt.h drags in varargs.h.  Since Pyramid */
/*				objects to including varargs.h twice, just */
/*				omit this one. */
#include "tclInt.h"
#ifdef NO_STDLIB_H
#include "../compat/stdlib.h"
#else
#include <stdlib.h>		/* for malloc */
#endif
#include <ctype.h>

#include "expect_comm.h"
#include "exp_int.h"
#include "exp_rename.h"
#include "exp_command.h"
#include "exp_log.h"

typedef struct ThreadSpecificData {
    Tcl_Channel diagChannel;
    Tcl_DString diagFilename;
    int diagToStderr;

    Tcl_Channel logChannel;
    Tcl_DString logFilename;	/* if no name, then it came from -open or -leaveopen */
    int logAppend;
    int logLeaveOpen;
    int logAll;			/* if TRUE, write log of all interactions
				 * despite value of logUser - i.e., even if
				 * user is not seeing it (via stdout)
				 */
    int logUser;		/* TRUE if user sees interactions on stdout */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * create a reasonably large buffer for the bulk of the output routines
 * that are not too large
 */
static char bigbuf[2000];

/*
 * Following this are several functions that log the conversation.  Some
 * general notes on all of them:
 */

/*
 * ignore sprintf return value ("character count") because it's not
 * defined in terms of UTF so it would be misinterpreted if we passed
 * it on.
 */

/*
 * if necessary, they could be made more efficient by skipping vsprintf based
 * on booleans
 */

/* Most of them have multiple calls to printf-style functions.  */
/* At first glance, it seems stupid to reformat the same arguments again */
/* but we have no way of telling how long the formatted output will be */
/* and hence cannot allocate a buffer to do so. */
/* Fortunately, in production code, most of the duplicate reformatting */
/* will be skipped, since it is due to handling errors and debugging. */

/*
 * Name: expWriteBytesAndLogIfTtyU
 *
 * Output to channel (and log if channel is stdout or devtty)
 *
 * Returns: TCL_OK or TCL_ERROR;
 */

int
expWriteBytesAndLogIfTtyU(esPtr,buf,lenBytes)
    ExpState *esPtr;
    char *buf;
    int lenBytes;
{
    int wc;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (esPtr->valid)
	wc = Tcl_WriteChars(esPtr->channel,buf,lenBytes);

    if (tsdPtr->logChannel && ((esPtr->fdout == 1) || expDevttyIs(esPtr))) {
	Tcl_WriteChars(tsdPtr->logChannel,buf,lenBytes);
    }
    return wc;
}

/*
 * Name: expLogDiagU
 *
 * Send to the Log (and Diag if open).  This is for writing to the log.
 * (In contrast, expDiagLog... is for writing diagnostics.)
 */

void
expLogDiagU(buf)
char *buf;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    expDiagWriteChars(buf,-1);
    if (tsdPtr->logChannel) {
	Tcl_WriteChars(tsdPtr->logChannel, buf, -1);
    }
}

/*
 * Name: expLogInteractionU
 *
 * Show chars to user if they've requested it, UNLESS they're seeing it
 * already because they're typing it and tty driver is echoing it.
 * Also send to Diag and Log if appropriate.
 */
void
expLogInteractionU(esPtr,buf)
    ExpState *esPtr;
    char *buf;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->logAll || (tsdPtr->logUser && tsdPtr->logChannel)) {
	Tcl_WriteChars(tsdPtr->logChannel,buf,-1);
    }

    /* hmm.... if stdout is closed such as by disconnect, loguser
       should be forced FALSE */

    /* don't write to user if they're seeing it already, i.e., typing it! */
    if (tsdPtr->logUser && (!expStdinoutIs(esPtr)) && (!expDevttyIs(esPtr))) {
	ExpState *stdinout = expStdinoutGet();
	if (stdinout->valid) {
	    Tcl_WriteChars(stdinout->channel,buf,-1);
	}
    }
    expDiagWriteChars(buf,-1);
}

/* send to log if open */
/* send to stderr if debugging enabled */
/* use this for logging everything but the parent/child conversation */
/* (this turns out to be almost nothing) */
/* uppercase L differentiates if from math function of same name */
#define LOGUSER		(tsdPtr->logUser || force_stdout)
/*VARARGS*/
void
expStdoutLog TCL_VARARGS_DEF(int,arg1)


{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int force_stdout;
    char *fmt;
    va_list args;

    force_stdout = TCL_VARARGS_START(int,arg1,args);


    fmt = va_arg(args,char *);

    if ((!tsdPtr->logUser) && (!force_stdout) && (!tsdPtr->logAll)) return;

    (void) vsprintf(bigbuf,fmt,args);
    expDiagWriteBytes(bigbuf,-1);
    if (tsdPtr->logAll || (LOGUSER && tsdPtr->logChannel)) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1);
    if (LOGUSER) fprintf(stdout,"%s",bigbuf);
    va_end(args);
}

/* just like log but does no formatting */
/* send to log if open */
/* use this function for logging the parent/child conversation */
void
expStdoutLogU(buf,force_stdout)
char *buf;
int force_stdout;	/* override value of logUser */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int length;


    if ((!tsdPtr->logUser) && (!force_stdout) && (!tsdPtr->logAll)) return;






    length = strlen(buf);

    expDiagWriteBytes(buf,length);
    if (tsdPtr->logAll || (LOGUSER && tsdPtr->logChannel)) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1);
    if (LOGUSER) {
#if (TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1))





      Tcl_WriteChars (Tcl_GetStdChannel (TCL_STDOUT), buf, length);
      Tcl_Flush      (Tcl_GetStdChannel (TCL_STDOUT));

#else



      fwrite(buf,1,length,stdout);




#endif


    }


}

/* send to log if open */
/* send to stderr */
/* use this function for error conditions */
/*VARARGS*/
void
expErrorLog TCL_VARARGS_DEF(char *,arg1)

{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    char *fmt;
    va_list args;

    fmt = TCL_VARARGS_START(char *,arg1,args);
    (void) vsprintf(bigbuf,fmt,args);

    expDiagWriteChars(bigbuf,-1);
    fprintf(stderr,"%s",bigbuf);
    if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1);
    

    va_end(args);
}

/* just like errorlog but does no formatting */
/* send to log if open */
/* use this function for logging the parent/child conversation */
/*ARGSUSED*/
void
expErrorLogU(buf)
char *buf;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    int length = strlen(buf);
    fwrite(buf,1,length,stderr);
    expDiagWriteChars(buf,-1);
    if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,buf,-1);
}



/* send diagnostics to Diag, Log, and stderr */
/* use this function for recording unusual things in the log */
/*VARARGS*/
void
expDiagLog TCL_VARARGS_DEF(char *,arg1)
{
    char *fmt;
    va_list args;

    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if ((tsdPtr->diagToStderr == 0) && (tsdPtr->diagChannel == 0)) return;

    fmt = TCL_VARARGS_START(char *,arg1,args);

    (void) vsprintf(bigbuf,fmt,args);

    expDiagWriteBytes(bigbuf,-1);
    if (tsdPtr->diagToStderr) {
	fprintf(stderr,"%s",bigbuf);
	if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,bigbuf,-1);
    }

    va_end(args);
}


/* expDiagLog for unformatted strings
   this also takes care of arbitrary large strings */
void
expDiagLogU(str)
    char *str;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if ((tsdPtr->diagToStderr == 0) && (tsdPtr->diagChannel == 0)) return;

    expDiagWriteBytes(str,-1);

    if (tsdPtr->diagToStderr) {
	fprintf(stderr,"%s",str);
	if (tsdPtr->logChannel) Tcl_WriteChars(tsdPtr->logChannel,str,-1);
    }
}

void
expDiagToStderrSet(val)
    int val;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tsdPtr->diagToStderr = val;
}
    

int
expDiagToStderrGet() {
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->diagToStderr;
}

Tcl_Channel
expDiagChannelGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->diagChannel;
}

void
expDiagChannelClose(interp)
    Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->diagChannel) return;
    Tcl_UnregisterChannel(interp,tsdPtr->diagChannel);
    Tcl_DStringFree(&tsdPtr->diagFilename);
    tsdPtr->diagChannel = 0;
}

/* currently this registers the channel, however the exp_internal
   command doesn't currently give the channel name to the user so
   this is kind of useless - but we might change this someday */
int
expDiagChannelOpen(interp,filename)
    Tcl_Interp *interp;
    char *filename;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    char *newfilename;

    Tcl_ResetResult(interp);
    newfilename = Tcl_TranslateFileName(interp,filename,&tsdPtr->diagFilename);
    if (!newfilename) return TCL_ERROR;

    /* Tcl_TildeSubst doesn't store into dstring */
    /* if no ~, so force string into dstring */
    /* this is only needed so that next time around */
    /* we can get dstring for -info if necessary */
    if (Tcl_DStringValue(&tsdPtr->diagFilename)[0] == '\0') {
	Tcl_DStringAppend(&tsdPtr->diagFilename,filename,-1);
    }

    tsdPtr->diagChannel = Tcl_OpenFileChannel(interp,newfilename,"a",0777);
    if (!tsdPtr->diagChannel) {
	Tcl_DStringFree(&tsdPtr->diagFilename);
	return TCL_ERROR;
    }
    Tcl_RegisterChannel(interp,tsdPtr->diagChannel);
    Tcl_SetChannelOption(interp,tsdPtr->diagChannel,"-buffering","none");
    return TCL_OK;
}

void
expDiagWriteObj(obj)
    Tcl_Obj *obj;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->diagChannel) return;

    Tcl_WriteObj(tsdPtr->diagChannel,obj);
}

/* write 8-bit bytes */
void
expDiagWriteBytes(str,len)
    char *str;
    int len;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->diagChannel) return;

    Tcl_Write(tsdPtr->diagChannel,str,len);
}

/* write UTF chars */
void
expDiagWriteChars(str,len)
    char *str;
    int len;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->diagChannel) return;

    Tcl_WriteChars(tsdPtr->diagChannel,str,len);
}

char *
expDiagFilename()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    return Tcl_DStringValue(&tsdPtr->diagFilename);
}

void
expLogChannelClose(interp)
    Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!tsdPtr->logChannel) return;

    if (Tcl_DStringLength(&tsdPtr->logFilename)) {
	/* it's a channel that we created */
	Tcl_UnregisterChannel(interp,tsdPtr->logChannel);
	Tcl_DStringFree(&tsdPtr->logFilename);
    } else {
	/* it's a channel that tcl::open created */
	if (!tsdPtr->logLeaveOpen) {
	    Tcl_UnregisterChannel(interp,tsdPtr->logChannel);
	}
    }
    tsdPtr->logChannel = 0;
    tsdPtr->logAll = 0; /* can't write to log if none open! */
}

/* currently this registers the channel, however the exp_log_file
   command doesn't currently give the channel name to the user so
   this is kind of useless - but we might change this someday */
int
expLogChannelOpen(interp,filename,append)
    Tcl_Interp *interp;
    char *filename;
    int append;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    char *newfilename;
    char mode[2];

    if (append) {
      strcpy(mode,"a");
    } else {
      strcpy(mode,"w");
    }

    Tcl_ResetResult(interp);
    newfilename = Tcl_TranslateFileName(interp,filename,&tsdPtr->logFilename);
    if (!newfilename) return TCL_ERROR;

    /* Tcl_TildeSubst doesn't store into dstring */
    /* if no ~, so force string into dstring */
    /* this is only needed so that next time around */
    /* we can get dstring for -info if necessary */
    if (Tcl_DStringValue(&tsdPtr->logFilename)[0] == '\0') {
	Tcl_DStringAppend(&tsdPtr->logFilename,filename,-1);
    }

    tsdPtr->logChannel = Tcl_OpenFileChannel(interp,newfilename,mode,0777);
    if (!tsdPtr->logChannel) {
	Tcl_DStringFree(&tsdPtr->logFilename);
	return TCL_ERROR;
    }
    Tcl_RegisterChannel(interp,tsdPtr->logChannel);
    Tcl_SetChannelOption(interp,tsdPtr->logChannel,"-buffering","none");
    return TCL_OK;
}

int
expLogAppendGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->logAppend;
}

void
expLogAppendSet(app)
    int app;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->logAppend = app;
}

int
expLogAllGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->logAll;
}

void
expLogAllSet(app)
    int app;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->logAll = app;
    /* should probably confirm logChannel != 0 */
}

int
expLogToStdoutGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->logUser;
}

void
expLogToStdoutSet(app)
    int app;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->logUser = app;
}

int
expLogLeaveOpenGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->logLeaveOpen;
}

void
expLogLeaveOpenSet(app)
    int app;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    tsdPtr->logLeaveOpen = app;
}

Tcl_Channel
expLogChannelGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    return tsdPtr->logChannel;
}

/* to set to a pre-opened channel (presumably by tcl::open) */
int
expLogChannelSet(interp,name)
    Tcl_Interp *interp;
    char *name;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    int mode;
    
    if (0 == (tsdPtr->logChannel = Tcl_GetChannel(interp,name,&mode))) {
	return TCL_ERROR;
    }
    if (!(mode & TCL_WRITABLE)) {
	tsdPtr->logChannel = 0;
	Tcl_SetResult(interp,"channel is not writable",TCL_VOLATILE);
	return TCL_ERROR;
    }
    return TCL_OK;
}

char *
expLogFilenameGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    return Tcl_DStringValue(&tsdPtr->logFilename);
}

int
expLogUserGet()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    return tsdPtr->logUser;
}

void
expLogUserSet(logUser)
    int logUser;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tsdPtr->logUser = logUser;
}



/* generate printable versions of random ASCII strings.  Primarily used */
/* in diagnostic mode, "expect -d" */
static char *
expPrintifyReal(s)
char *s;
{
	static int destlen = 0;
	static char *dest = 0;
	char *d;		/* ptr into dest */
	unsigned int need;
	Tcl_UniChar ch;

	if (s == 0) return("<null>");

	/* worst case is every character takes 4 to printify */
	need = strlen(s)*6 + 1;
	if (need > destlen) {
		if (dest) ckfree(dest);
		dest = ckalloc(need);
		destlen = need;
	}

	for (d = dest;*s;) {
	    s += Tcl_UtfToUniChar(s, &ch);
	    if (ch == '\r') {
		strcpy(d,"\\r");		d += 2;
	    } else if (ch == '\n') {
		strcpy(d,"\\n");		d += 2;
	    } else if (ch == '\t') {
		strcpy(d,"\\t");		d += 2;
	    } else if ((ch < 0x80) && isprint(UCHAR(ch))) {
		*d = (char)ch;			d += 1;
	    } else {
		sprintf(d,"\\u%04x",ch);	d += 6;
	    }
	}
	*d = '\0';
	return(dest);
}

char *
expPrintifyObj(obj)
    Tcl_Obj *obj;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /* don't bother writing into bigbuf if we're not going to ever use it */
    if ((!tsdPtr->diagToStderr) && (!tsdPtr->diagChannel)) return((char *)0);
    
    return expPrintifyReal(Tcl_GetString(obj));
}

char *
expPrintify(s) /* INTL */
char *s;
{

    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);





    /* don't bother writing into bigbuf if we're not going to ever use it */

    if ((!tsdPtr->diagToStderr) && (!tsdPtr->diagChannel)) return((char *)0);

    return expPrintifyReal(s);
}
 


void












expDiagInit()



{





    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);






















    Tcl_DStringInit(&tsdPtr->diagFilename);


    tsdPtr->diagChannel = 0;

    tsdPtr->diagToStderr = 0;




}









void



expLogInit()
{


    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_DStringInit(&tsdPtr->logFilename);

    tsdPtr->logChannel = 0;
    tsdPtr->logAll = FALSE;


    tsdPtr->logUser = TRUE;

}



Changes to exp_log.h.

1
2
3

4
5
6
7
8
9
10












11
12
13
14
15
16
17
18





19



20
21


22

23
24
25
26

27
28

/* exp_log.h */

#include "exp_printify.h"


/* special version of log for non-null-terminated strings which */
/* never need printf-style formatting. */
#define logn(buf,length)  { \
			  if (logfile) fwrite(buf,1,length,logfile); \
			  if (debugfile) fwrite(buf,1,length,debugfile); \
			  }













#define dprintify(x)	((is_debugging || debugfile)?exp_printify(x):0)
/* in circumstances where "debuglog(printify(...))" is written, call */
/* dprintify instead.  This will avoid doing any formatting that would */
/* occur before debuglog got control and decided not to do anything */
/* because (is_debugging || debugfile) was false. */

extern void exp_errorlog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));





extern void exp_log _ANSI_ARGS_(TCL_VARARGS(int,force_stdout));



extern void exp_debuglog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
extern void exp_nflog _ANSI_ARGS_((char *buf, int force_stdout));


extern void exp_nferrorlog _ANSI_ARGS_((char *buf, int force_stdout));


extern FILE *debugfile;
extern FILE *logfile;
extern int logfile_all;


extern int is_debugging;	/* useful to know for avoid debug calls */



|
>

<
|
|
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>

|
<
|
<
<

|
>
>
>
>
>
|
>
>
>
|
|
>
>
|
>

<
<
|
>

<
>
1
2
3
4
5

6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41


42
43
44

45
/* exp_log.h */

extern void		expErrorLog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
extern void		expErrorLogU _ANSI_ARGS_((char *));


extern void		expStdoutLog _ANSI_ARGS_(TCL_VARARGS(int,force_stdout));
extern void		expStdoutLogU _ANSI_ARGS_((char *buf, int force_stdout));



EXTERN void		expDiagInit _ANSI_ARGS_((void));
EXTERN int		expDiagChannelOpen _ANSI_ARGS_((Tcl_Interp *,char *));
EXTERN Tcl_Channel	expDiagChannelGet _ANSI_ARGS_((void));
EXTERN void		expDiagChannelClose _ANSI_ARGS_((Tcl_Interp *));
EXTERN char *		expDiagFilename _ANSI_ARGS_((void));
EXTERN int		expDiagToStderrGet _ANSI_ARGS_((void));
EXTERN void		expDiagToStderrSet _ANSI_ARGS_((int));
EXTERN void		expDiagWriteBytes _ANSI_ARGS_((char *,int));
EXTERN void		expDiagWriteChars _ANSI_ARGS_((char *,int));
EXTERN void		expDiagWriteObj _ANSI_ARGS_((Tcl_Obj *));
EXTERN void		expDiagLog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
EXTERN void		expDiagLogU _ANSI_ARGS_((char *));

EXTERN char *		expPrintify _ANSI_ARGS_((char *));

EXTERN char *		expPrintifyObj _ANSI_ARGS_((Tcl_Obj *));



EXTERN void		expLogInit _ANSI_ARGS_((void));
EXTERN int		expLogChannelOpen _ANSI_ARGS_((Tcl_Interp *,char *,int));
EXTERN Tcl_Channel 	expLogChannelGet _ANSI_ARGS_((void));
EXTERN int		expLogChannelSet _ANSI_ARGS_((Tcl_Interp *,char *));
EXTERN void		expLogChannelClose _ANSI_ARGS_((Tcl_Interp *));
EXTERN char *		expLogFilenameGet _ANSI_ARGS_((void));
EXTERN void		expLogAppendSet _ANSI_ARGS_((int));
EXTERN int		expLogAppendGet _ANSI_ARGS_((void));
EXTERN void		expLogLeaveOpenSet _ANSI_ARGS_((int));
EXTERN int		expLogLeaveOpenGet _ANSI_ARGS_((void));
EXTERN void		expLogAllSet _ANSI_ARGS_((int));
EXTERN int		expLogAllGet _ANSI_ARGS_((void));
EXTERN void		expLogToStdoutSet _ANSI_ARGS_((int));
EXTERN int		expLogToStdoutGet _ANSI_ARGS_((void));
EXTERN void		expLogDiagU _ANSI_ARGS_((char *));
EXTERN int		expWriteBytesAndLogIfTtyU _ANSI_ARGS_((ExpState *,char *,int));



EXTERN int		expLogUserGet _ANSI_ARGS_((void));
EXTERN void		expLogUserSet _ANSI_ARGS_((int));


EXTERN void		expLogInteractionU _ANSI_ARGS_((ExpState *,char *));

Changes to exp_main_exp.c.

14
15
16
17
18
19
20


21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44




45
46
47
48
49

int
main(argc, argv)
int argc;
char *argv[];
{
	int rc = 0;


	Tcl_Interp *interp = Tcl_CreateInterp();


	if (Tcl_Init(interp) == TCL_ERROR) {
		fprintf(stderr,"Tcl_Init failed: %s\n",interp->result);
		exit(1);
	}

	if (Expect_Init(interp) == TCL_ERROR) {
		fprintf(stderr,"Expect_Init failed: %s\n",interp->result);
		exit(1);
	}

	exp_parse_argv(interp,argc,argv);

	/* become interactive if requested or "nothing to do" */
	if (exp_interactive)
		(void) exp_interpreter(interp);
	else if (exp_cmdfile)
		rc = exp_interpret_cmdfile(interp,exp_cmdfile);
	else if (exp_cmdfilename)
		rc = exp_interpret_cmdfilename(interp,exp_cmdfilename);

	/* assert(exp_cmdlinecmds != 0) */





	exp_exit(interp,rc);
	/*NOTREACHED*/
	return 0;		/* Needed only to prevent compiler warning. */
}








>
>

>


|
|



|
|






|







>
>
>
>
|




14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

int
main(argc, argv)
int argc;
char *argv[];
{
	int rc = 0;
	char buffer [30];

	Tcl_Interp *interp = Tcl_CreateInterp();
	Tcl_FindExecutable(argv[0]);

	if (Tcl_Init(interp) == TCL_ERROR) {
	    fprintf(stderr,"Tcl_Init failed: %s\n",interp->result);
	    (void) exit(1);
	}

	if (Expect_Init(interp) == TCL_ERROR) {
	    fprintf(stderr,"Expect_Init failed: %s\n",interp->result);
	    (void) exit(1);
	}

	exp_parse_argv(interp,argc,argv);

	/* become interactive if requested or "nothing to do" */
	if (exp_interactive)
		(void) exp_interpreter(interp,(Tcl_Obj *)0);
	else if (exp_cmdfile)
		rc = exp_interpret_cmdfile(interp,exp_cmdfile);
	else if (exp_cmdfilename)
		rc = exp_interpret_cmdfilename(interp,exp_cmdfilename);

	/* assert(exp_cmdlinecmds != 0) */

	/* SF #439042 -- Allow overide of "exit" by user / script
	 */

	sprintf(buffer, "exit %d", rc);
	Tcl_Eval(interp, buffer); 
	/*NOTREACHED*/
	return 0;		/* Needed only to prevent compiler warning. */
}

Changes to exp_main_sub.c.

61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

int exp_getpid;

static void
usage(interp)
Tcl_Interp *interp;
{

	errorlog("usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]\r\n");
	exp_exit(interp,1);
}

/*ARGSUSED*/
void
exp_exit(interp,status)
Tcl_Interp *interp;     /* historic */
int status;
{
	Tcl_Exit(status);
}

/* this clumsiness because pty routines don't know Tcl definitions */

static
void
exp_pty_exit_for_tcl(clientData)
ClientData clientData;
{
	exp_pty_exit();
}

static
void
exp_init_pty_exit()
{
	Tcl_CreateExitHandler(exp_pty_exit_for_tcl,(ClientData)0);
}

/* This can be called twice or even recursively - it's safe. */
void
exp_exit_handlers(clientData)
ClientData clientData;
{
	extern int exp_forked;

	Tcl_Interp *interp = (Tcl_Interp *)clientData;

	/* use following checks to prevent recursion in exit handlers */
	/* if this code ever supports multiple interps, these should */
	/* become interp-specific */

	static int did_app_exit = FALSE;
	static int did_expect_exit = FALSE;

	/* don't think this code is relevant any longer, but not positive! */
	if (!interp) {
		/* if no interp handy (i.e., called from interrupt handler) */
		/* use last one created - it's a hack but we're exiting */
		/* ungracefully to begin with */
		interp = exp_interp;
	}

	if (!did_expect_exit) {
		did_expect_exit = TRUE;
		/* called user-defined exit routine if one exists */
		if (exp_onexit_action) {
			int result = Tcl_GlobalEval(interp,exp_onexit_action);
			if (result != TCL_OK) Tcl_BackgroundError(interp);
		}
	} else {
		debuglog("onexit handler called recursively - forcing exit\r\n");
	}

	if (exp_app_exit) {
		if (!did_app_exit) {
			did_app_exit = TRUE;
			(*exp_app_exit)(interp);
		} else {
			debuglog("application exit handler called recursively - forcing exit\r\n");
		}
	}

	if (!exp_disconnected
	    && !exp_forked
	    && (exp_dev_tty != -1)
	    && isatty(exp_dev_tty)







>
|
<
|
|
|
<
|
<
<
<
<



>





|






|


















<
<
<
<
<
<
<
<








|







|







61
62
63
64
65
66
67
68
69

70
71
72

73




74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108








109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

int exp_getpid;

static void
usage(interp)
Tcl_Interp *interp;
{
  char buffer [] = "exit 1";
  expErrorLog("usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]\r\n");


  /* SF #439042 -- Allow overide of "exit" by user / script
   */

  Tcl_Eval(interp, buffer); 




}

/* this clumsiness because pty routines don't know Tcl definitions */
/*ARGSUSED*/
static
void
exp_pty_exit_for_tcl(clientData)
ClientData clientData;
{
  exp_pty_exit();
}

static
void
exp_init_pty_exit()
{
  Tcl_CreateExitHandler(exp_pty_exit_for_tcl,(ClientData)0);
}

/* This can be called twice or even recursively - it's safe. */
void
exp_exit_handlers(clientData)
ClientData clientData;
{
	extern int exp_forked;

	Tcl_Interp *interp = (Tcl_Interp *)clientData;

	/* use following checks to prevent recursion in exit handlers */
	/* if this code ever supports multiple interps, these should */
	/* become interp-specific */

	static int did_app_exit = FALSE;
	static int did_expect_exit = FALSE;









	if (!did_expect_exit) {
		did_expect_exit = TRUE;
		/* called user-defined exit routine if one exists */
		if (exp_onexit_action) {
			int result = Tcl_GlobalEval(interp,exp_onexit_action);
			if (result != TCL_OK) Tcl_BackgroundError(interp);
		}
	} else {
		expDiagLogU("onexit handler called recursively - forcing exit\r\n");
	}

	if (exp_app_exit) {
		if (!did_app_exit) {
			did_app_exit = TRUE;
			(*exp_app_exit)(interp);
		} else {
			expDiagLogU("application exit handler called recursively - forcing exit\r\n");
		}
	}

	if (!exp_disconnected
	    && !exp_forked
	    && (exp_dev_tty != -1)
	    && isatty(exp_dev_tty)
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192


193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
	exp_close_all(interp);
}

static int
history_nextid(interp)
Tcl_Interp *interp;
{
	Interp *iPtr = (Interp *)interp;

#if TCL_MAJOR_VERSION < 8
	return iPtr->curEventNum+1;
#else
	/* unncessarily tricky coding - if nextid isn't defined,
	   maintain our own static version */

	static int nextid = 0;
	char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0);
	if (nextidstr) {
		/* intentionally ignore failure */
		(void) sscanf(nextidstr,"%d",&nextid);
	}
	return ++nextid;
#endif
}

/* this stupidity because Tcl needs commands in writable space */
static char prompt1[] = "prompt1";
static char prompt2[] = "prompt2";

static char *prompt2_default = "+> ";
static char prompt1_default[] = "expect%d.%d> ";

/*ARGSUSED*/
int
Exp_Prompt1Cmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;


char **argv;
{
	Interp *iPtr = (Interp *)interp;

	sprintf(interp->result,prompt1_default,
		iPtr->numLevels,history_nextid(interp));

	return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_Prompt2Cmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	strcpy(interp->result,prompt2_default);
	return(TCL_OK);
}

/*ARGSUSED*/
static int
ignore_procs(interp,s)
Tcl_Interp *interp;
char *s;		/* function name */







<
<
<
<
<
|
|

|
|
|
|
|
|
|
<











|


|
>
>
|
|
|

<
|
>
|




|


|
|

|
|







143
144
145
146
147
148
149





150
151
152
153
154
155
156
157
158
159

160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
	exp_close_all(interp);
}

static int
history_nextid(interp)
Tcl_Interp *interp;
{





    /* unncessarily tricky coding - if nextid isn't defined,
       maintain our own static version */

    static int nextid = 0;
    char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0);
    if (nextidstr) {
	/* intentionally ignore failure */
	(void) sscanf(nextidstr,"%d",&nextid);
    }
    return ++nextid;

}

/* this stupidity because Tcl needs commands in writable space */
static char prompt1[] = "prompt1";
static char prompt2[] = "prompt2";

static char *prompt2_default = "+> ";
static char prompt1_default[] = "expect%d.%d> ";

/*ARGSUSED*/
int
Exp_Prompt1Cmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    static char buffer[200];

    Interp *iPtr = (Interp *)interp;


    sprintf(buffer,prompt1_default,iPtr->numLevels,history_nextid(interp));
    Tcl_SetResult(interp,buffer,TCL_STATIC);
    return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_Prompt2Cmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
    Tcl_SetResult(interp,prompt2_default,TCL_STATIC);
    return(TCL_OK);
}

/*ARGSUSED*/
static int
ignore_procs(interp,s)
Tcl_Interp *interp;
char *s;		/* function name */
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275
276
277
278

279

280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297

298
299
300
301
302
303




304
305
306
307
308
309
310
311


312
313
314
315
316


317
318
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334
335


336

337


338

339

340
341
342
343
344
345


346
347
348









349
350

351
352
353
354
355

356
357
358
359
360
361


362

363
364


365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381


382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
			return;
		}
	}

	/* no \n at end, since ccmd will already have one. */
	/* Actually, this is not true if command is last in */
	/* file and has no newline after it, oh well */
	errorlog("%s\r\n",exp_cook(msg,(int *)0));

}

/* user has pressed escape char from interact or somehow requested expect.
If a user-supplied command returns:

TCL_ERROR,	assume user is experimenting and reprompt
TCL_OK,		ditto
TCL_RETURN,	return TCL_OK (assume user just wants to escape() to return)
EXP_TCL_RETURN,	return TCL_RETURN
anything else	return it
*/
int
exp_interpreter(interp)
Tcl_Interp *interp;

{

	int rc;
	char *ccmd;		/* pointer to complete command */
	char line[BUFSIZ+1];	/* space for partial command */
	int newcmd = TRUE;
	Tcl_DString dstring;
	Interp *iPtr = (Interp *)interp;
	int tty_changed = FALSE;

	exp_tty tty_old;
	int was_raw, was_echo;

	int dummy;
	Tcl_Channel outChannel;

	int fd = fileno(stdin);
	
	expect_key++;

	Tcl_DStringInit(&dstring);


	newcmd = TRUE;
	while (TRUE) {
		outChannel = Tcl_GetStdChannel(TCL_STDOUT);
		if (outChannel) {
			Tcl_Flush(outChannel);




		}

		/* force terminal state */
		tty_changed = exp_tty_cooked_echo(interp,&tty_old,&was_raw,&was_echo);

		if (newcmd) {
			rc = Tcl_Eval(interp,prompt1);
			if (rc == TCL_OK) exp_log(1,"%s",interp->result);


			else exp_log(1,prompt1_default,iPtr->numLevels,
				     history_nextid(interp));
		} else {
			rc = Tcl_Eval(interp,prompt2);
			if (rc == TCL_OK) exp_log(1,"%s",interp->result);


			else exp_log(1,prompt2_default,1);
		}

		exp_fs[fd].force_read = 1;
		rc = exp_get_next_event(interp,&fd,1,&dummy,EXP_TIME_INFINITY,
			exp_fs[fd].key);
		/*  check for rc == EXP_TCLERROR? */

		if (rc != EXP_EOF) {
			rc = read(0,line,BUFSIZ);

#ifdef SIMPLE_EVENT
			if (rc == -1 && errno == EINTR) {
				if (Tcl_AsyncReady()) {
					(void) Tcl_AsyncInvoke(interp,TCL_OK);
				}
				continue;
			}
#endif
			if (rc <= 0) {


				if (!newcmd) line[0] = 0;

				else rc = EXP_EOF;


			} else line[rc] = '\0';

		}


		if (rc == EXP_EOF) exp_exit(interp,0);

		if (debugfile) fwrite(line,1,strlen(line),debugfile);
		/* intentionally always write to logfile */
		if (logfile) fwrite(line,1,strlen(line),logfile);


		/* no need to write to stdout, since they will see */
		/* it just from it having been echoed as they are */
		/* typing it */










		ccmd = Tcl_DStringAppend(&dstring,line,rc);

		if (!Tcl_CommandComplete(ccmd)) {
			newcmd = FALSE;
			continue;	/* continue collecting command */
		}
		newcmd = TRUE;


		if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);

		rc = Tcl_RecordAndEval(interp,ccmd,0);
		Tcl_DStringFree(&dstring);
		switch (rc) {


		case TCL_OK:

			if (*interp->result != 0)
				exp_log(1,"%s\r\n",exp_cook(interp->result,(int *)0));


			continue;
		case TCL_ERROR:
			handle_eval_error(interp,1);
			/* since user is typing by hand, we expect lots */
			/* of errors, and want to give another chance */
			continue;
#define finish(x)	{rc = x; goto done;}
		case TCL_BREAK:
		case TCL_CONTINUE:
			finish(rc);
		case EXP_TCL_RETURN:
			finish(TCL_RETURN);
		case TCL_RETURN:
			finish(TCL_OK);
		default:
			/* note that ccmd has trailing newline */
			errorlog("error %d: %s\r\n",rc,ccmd);


			continue;
		}
	}
	/* cannot fall thru here, must jump to label */
 done:
	if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);

	Tcl_DStringFree(&dstring);

	return(rc);
}

/*ARGSUSED*/
int
Exp_ExpVersionCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;







|
>












|

>

>
|
<
<
|
<
|
|
<
|
|

<
|
>
|

|

|
>

|
|
|
|
|
>
>
>
>
|

|
|

|
|
|
>
>
|
<
|
|
|
>
>
|
|

|
|
|
|

|
|
>

|
|
|
|
|
|

|
>
>
|
>
|
>
>
|
>
|
>
|
<

|
|
|
>
>
|
|
|
>
>
>
>
>
>
>
>
>
|
|
>
|
|
|
|
|
>

|

|
|
|
>
>
|
>
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|

|

<
|
|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267


268

269
270

271
272
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414
415
			return;
		}
	}

	/* no \n at end, since ccmd will already have one. */
	/* Actually, this is not true if command is last in */
	/* file and has no newline after it, oh well */
	expErrorLogU(exp_cook(msg,(int *)0));
	expErrorLogU("\r\n");
}

/* user has pressed escape char from interact or somehow requested expect.
If a user-supplied command returns:

TCL_ERROR,	assume user is experimenting and reprompt
TCL_OK,		ditto
TCL_RETURN,	return TCL_OK (assume user just wants to escape() to return)
EXP_TCL_RETURN,	return TCL_RETURN
anything else	return it
*/
int
exp_interpreter(interp,eofObj)
Tcl_Interp *interp;
Tcl_Obj *eofObj;
{
    Tcl_Obj *commandPtr = NULL;
    int code;


    int gotPartial;

    Interp *iPtr = (Interp *)interp;
    int tty_changed = FALSE;

    exp_tty tty_old;
    int was_raw, was_echo;


    Tcl_Channel inChannel, outChannel;
    ExpState *esPtr = expStdinoutGet();
    /*	int fd = fileno(stdin);*/
	
    expect_key++;

    commandPtr = Tcl_NewObj();
    Tcl_IncrRefCount(commandPtr);

    gotPartial = 0;
    while (TRUE) {
	outChannel = expStdinoutGet()->channel;
	if (outChannel) {
	    Tcl_Flush(outChannel);
	}
	if (!esPtr->open) {
	  code = EXP_EOF;
	  goto eof;
	}

	/* force terminal state */
	tty_changed = exp_tty_cooked_echo(interp,&tty_old,&was_raw,&was_echo);

	if (!gotPartial) {
	    code = Tcl_Eval(interp,prompt1);
	    if (code == TCL_OK) {
		expStdoutLogU(Tcl_GetStringResult(interp),1);
	    }
	    else expStdoutLog(1,prompt1_default,iPtr->numLevels,history_nextid(interp));

	} else {
	    code = Tcl_Eval(interp,prompt2);
	    if (code == TCL_OK) {
		expStdoutLogU(Tcl_GetStringResult(interp),1);
	    }
	    else expStdoutLogU(prompt2_default,1);
	}

	esPtr->force_read = 1;
	code = exp_get_next_event(interp,&esPtr,1,&esPtr,EXP_TIME_INFINITY,
		esPtr->key);
	/*  check for code == EXP_TCLERROR? */

	if (code != EXP_EOF) {
	    inChannel = expStdinoutGet()->channel;
	    code = Tcl_GetsObj(inChannel, commandPtr);
#ifdef SIMPLE_EVENT
	    if (code == -1 && errno == EINTR) {
		if (Tcl_AsyncReady()) {
		    (void) Tcl_AsyncInvoke(interp,TCL_OK);
		}
		continue;
	    }
#endif
	    if (code < 0) code = EXP_EOF;
	    if ((code == 0) && Tcl_Eof(inChannel) && !gotPartial) code = EXP_EOF;
	}

    eof:
	if (code == EXP_EOF) {
	    if (eofObj) {
		code = Tcl_EvalObjEx(interp,eofObj,0);
	    } else {
		code = TCL_OK;
	    }
	    goto done;
	}


	expDiagWriteObj(commandPtr);
	/* intentionally always write to logfile */
	if (expLogChannelGet()) {
	    Tcl_WriteObj(expLogChannelGet(),commandPtr);
	}
	/* no need to write to stdout, since they will see */
	/* it just from it having been echoed as they are */
	/* typing it */

        /*
         * Add the newline removed by Tcl_GetsObj back to the string.
         */

	Tcl_AppendToObj(commandPtr, "\n", 1);
	if (!TclObjCommandComplete(commandPtr)) {
	    gotPartial = 1;
	    continue;
	}	

	Tcl_AppendToObj(commandPtr, "\n", 1);
	if (!TclObjCommandComplete(commandPtr)) {
	    gotPartial = 1;
	    continue;
	}

	gotPartial = 0;

	if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);

	code = Tcl_RecordAndEvalObj(interp, commandPtr, 0);
	Tcl_SetObjLength(commandPtr, 0);
	switch (code) {
	    char *str;

	    case TCL_OK:
	        str = Tcl_GetStringResult(interp);
		if (*str != 0) {
		    expStdoutLogU(exp_cook(str,(int *)0),1);
		    expStdoutLogU("\r\n",1);
		}
		continue;
	    case TCL_ERROR:
		handle_eval_error(interp,1);
		/* since user is typing by hand, we expect lots */
		/* of errors, and want to give another chance */
		continue;
#define finish(x)	{code = x; goto done;}
	    case TCL_BREAK:
	    case TCL_CONTINUE:
		finish(code);
	    case EXP_TCL_RETURN:
		finish(TCL_RETURN);
	    case TCL_RETURN:
		finish(TCL_OK);
	    default:
		/* note that ccmd has trailing newline */
		expErrorLog("error %d: ",code);
		expErrorLogU(Tcl_GetString(Tcl_GetObjResult(interp)));
		expErrorLogU("\r\n");
		continue;
	}
    }
    /* cannot fall thru here, must jump to label */
 done:
    if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);


    Tcl_DecrRefCount(commandPtr);
    return(code);
}

/*ARGSUSED*/
int
Exp_ExpVersionCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
433
434
435
436
437
438
439
440
441





442

443
444
445
446






447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

468
469
470
471
472
473
474




475
476
477
478
479
480
481
482
483
484
485





486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502

503

504









505


506


507


508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
	}

	if (argc == 2) {
		exp_error(interp,"%s requires Expect version %s (but using %s)",
			exp_argv0,user_version,exp_version);
		return(TCL_ERROR);
	}
	errorlog("%s: requires Expect version %s (but using %s)\r\n",
		exp_argv0,user_version,exp_version);





	exp_exit(interp,1);

	/*NOTREACHED*/
}

static char init_auto_path[] = "lappend auto_path $exp_library $exp_exec_library";







int
Expect_Init(interp)
Tcl_Interp *interp;
{
	static int first_time = TRUE;

	if (first_time) {
		int tcl_major = atoi(TCL_VERSION);
		char *dot = strchr(TCL_VERSION,'.');
		int tcl_minor = atoi(dot+1);

		if (tcl_major < NEED_TCL_MAJOR || 
		    (tcl_major == NEED_TCL_MAJOR && tcl_minor < NEED_TCL_MINOR)) {
			sprintf(interp->result,
			   "%s compiled with Tcl %d.%d but needs at least Tcl %d.%d\n",
				exp_argv0,tcl_major,tcl_minor,
				NEED_TCL_MAJOR,NEED_TCL_MINOR);
			return TCL_ERROR;
		}


		if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
			return TCL_ERROR;
		}
		if (Tcl_PkgProvide(interp, "Expect", EXP_VERSION) != TCL_OK) {
			return TCL_ERROR;
		}





		exp_getpid = getpid();
		exp_init_pty();
		exp_init_pty_exit();
		exp_init_tty(); /* do this only now that we have looked at */
				/* original tty state */
		exp_init_stdio();
		exp_init_sig();
		exp_init_event();
		exp_init_trap();
		exp_init_unit_random();
		exp_init_spawn_ids();






		Tcl_CreateExitHandler(exp_exit_handlers,(ClientData)interp);

		first_time = FALSE;
	}

	/* save last known interp for emergencies */
	exp_interp = interp;

	/* initialize commands */
	exp_init_most_cmds(interp);	/* add misc     cmds to interpreter */
	exp_init_expect_cmds(interp);	/* add expect   cmds to interpreter */
	exp_init_main_cmds(interp);	/* add main     cmds to interpreter */
	exp_init_trap_cmds(interp);	/* add trap     cmds to interpreter */
	exp_init_tty_cmds(interp);	/* add tty      cmds to interpreter */
	exp_init_interact_cmds(interp);	/* add interact cmds to interpreter */


	exp_init_spawn_id_vars(interp);











	Tcl_SetVar(interp,"expect_library",SCRIPTDIR,0);/* deprecated */


	Tcl_SetVar(interp,"exp_library",SCRIPTDIR,0);


	Tcl_SetVar(interp,"exp_exec_library",EXECSCRIPTDIR,0);


	Tcl_Eval(interp,init_auto_path);
	Tcl_ResetResult(interp);

#ifdef TCL_DEBUGGER
	Dbg_IgnoreFuncs(interp,ignore_procs);
#endif

	return TCL_OK;
}

static char sigexit_init_default[] = "trap exit {SIGINT SIGTERM}";
static char debug_init_default[] = "trap {exp_debug 1} SIGINT";

void
exp_parse_argv(interp,argc,argv)







|

>
>
>
>
>
|
>



|
>
>
>
>
>
>





|

|
|
|
|

|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|

>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>

|

|
|

|
|

|
|
|
|
|
|
|

>
|
>

>
>
>
>
>
>
>
>
>

>
>

>
>

>
>
|
|


|


|







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
	}

	if (argc == 2) {
		exp_error(interp,"%s requires Expect version %s (but using %s)",
			exp_argv0,user_version,exp_version);
		return(TCL_ERROR);
	}
	expErrorLog("%s: requires Expect version %s (but using %s)\r\n",
		exp_argv0,user_version,exp_version);

	/* SF #439042 -- Allow overide of "exit" by user / script
	 */
	{
	  char buffer [] = "exit 1";
	  Tcl_Eval(interp, buffer); 
	}
	/*NOTREACHED*/
}

static char init_auto_path[] = "\
if {$exp_library != \"\"} {\n\
    lappend auto_path $exp_library\n\
}\n\
if {$exp_exec_library != \"\"} {\n\
    lappend auto_path $exp_exec_library\n\
}";

int
Expect_Init(interp)
Tcl_Interp *interp;
{
    static int first_time = TRUE;

    if (first_time) {
	int tcl_major = atoi(TCL_VERSION);
	char *dot = strchr(TCL_VERSION,'.');
	int tcl_minor = atoi(dot+1);

	if (tcl_major < NEED_TCL_MAJOR || 
	    (tcl_major == NEED_TCL_MAJOR && tcl_minor < NEED_TCL_MINOR)) {
	    sprintf(interp->result,
		    "%s compiled with Tcl %d.%d but needs at least Tcl %d.%d\n",
		    exp_argv0,tcl_major,tcl_minor,
		    NEED_TCL_MAJOR,NEED_TCL_MINOR);
	    return TCL_ERROR;
	}
    }

    if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
      return TCL_ERROR;
    }
    if (Tcl_PkgProvide(interp, "Expect", EXP_VERSION) != TCL_OK) {
      return TCL_ERROR;
    }

    Tcl_Preserve(interp);
    Tcl_CreateExitHandler(Tcl_Release,(ClientData)interp);

    if (first_time) {
	exp_getpid = getpid();
	exp_init_pty();
	exp_init_pty_exit();
	exp_init_tty(); /* do this only now that we have looked at */
	/* original tty state */
	exp_init_stdio();
	exp_init_sig();
	exp_init_event();
	exp_init_trap();
	exp_init_unit_random();
	exp_init_spawn_ids(interp);
	expChannelInit();
	expDiagInit();
	expLogInit();
	expDiagLogPtrSet(expDiagLogU);
	expErrnoMsgSet(Tcl_ErrnoMsg);

	Tcl_CreateExitHandler(exp_exit_handlers,(ClientData)interp);

	first_time = FALSE;
    }

    /* save last known interp for emergencies */
    exp_interp = interp;

    /* initialize commands */
    exp_init_most_cmds(interp);		/* add misc     cmds to interpreter */
    exp_init_expect_cmds(interp);	/* add expect   cmds to interpreter */
    exp_init_main_cmds(interp);		/* add main     cmds to interpreter */
    exp_init_trap_cmds(interp);		/* add trap     cmds to interpreter */
    exp_init_tty_cmds(interp);		/* add tty      cmds to interpreter */
    exp_init_interact_cmds(interp);	/* add interact cmds to interpreter */

    /* initialize variables */
    exp_init_spawn_id_vars(interp);
    expExpectVarsInit();

    /*
     * For each of the the Tcl variables, "expect_library",
     *"exp_library", and "exp_exec_library", set the variable
     * if it does not already exist.  This mechanism allows the
     * application calling "Expect_Init()" to set these varaibles
     * to alternate locations from where Expect was built.
     */

    if (Tcl_GetVar(interp, "expect_library", TCL_GLOBAL_ONLY) == NULL) {
	Tcl_SetVar(interp,"expect_library",SCRIPTDIR,0);/* deprecated */
    }
    if (Tcl_GetVar(interp, "exp_library", TCL_GLOBAL_ONLY) == NULL) {
	Tcl_SetVar(interp,"exp_library",SCRIPTDIR,0);
    }
    if (Tcl_GetVar(interp, "exp_exec_library", TCL_GLOBAL_ONLY) == NULL) {
	Tcl_SetVar(interp,"exp_exec_library",EXECSCRIPTDIR,0);
    }

    Tcl_Eval(interp,init_auto_path);
    Tcl_ResetResult(interp);

#ifdef TCL_DEBUGGER
    Dbg_IgnoreFuncs(interp,ignore_procs);
#endif

    return TCL_OK;
}

static char sigexit_init_default[] = "trap exit {SIGINT SIGTERM}";
static char debug_init_default[] = "trap {exp_debug 1} SIGINT";

void
exp_parse_argv(interp,argc,argv)
546
547
548
549
550
551
552









553
554
555
556
557
558
559
560
561
562
563
564
565

566
567
568
569
570
571
572
573
574
575
576




577

578
579
580
581
582
583
584
	/* initially, we must assume we are not interactive */
	/* this prevents interactive weirdness courtesy of unknown via -c */
	/* after handling args, we can change our mind */
	Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);

	Tcl_Eval(interp,sigexit_init_default);










	while ((c = getopt(argc, argv, "b:c:dD:f:inN-v")) != EOF) {
		switch(c) {
		case '-':
			/* getopt already handles -- internally, however */
			/* this allows us to abort getopt when dash is at */
			/* the end of another option which is required */
			/* in order to allow things like -n- on #! line */
			goto abort_getopt;
		case 'c': /* command */
			exp_cmdlinecmds = TRUE;
			rc = Tcl_Eval(interp,optarg);
			if (rc != TCL_OK) {
			    errorlog("%s\r\n",exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));

			}
			break;
		case 'd': exp_is_debugging = TRUE;
			debuglog("expect version %s\r\n",exp_version);
			break;
#ifdef TCL_DEBUGGER
		case 'D':
			exp_tcl_debugger_available = TRUE;
			if (Tcl_GetInt(interp,optarg,&rc) != TCL_OK) {
				errorlog("%s: -D argument must be 0 or 1\r\n",
					exp_argv0);




				exp_exit(interp,1);

			}

			/* set up trap handler before Dbg_On so user does */
			/* not have to see it at first debugger prompt */
			if (0 == (debug_init = getenv("EXPECT_DEBUG_INIT"))) {
				debug_init = debug_init_default;
			}







>
>
>
>
>
>
>
>
>
|











|
>


|
|





|
|
>
>
>
>
|
>







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
	/* initially, we must assume we are not interactive */
	/* this prevents interactive weirdness courtesy of unknown via -c */
	/* after handling args, we can change our mind */
	Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);

	Tcl_Eval(interp,sigexit_init_default);

	/*
	 * [#418892]. The '+' character in front of every other option
         * declaration causes 'GNU getopt' to deactivate its
         * non-standard behaviour and switch to POSIX. Other
         * implementations of 'getopt' might recognize the option '-+'
         * because of this, but the following switch will catch this
         * and generate a usage message.
	 */

	while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) {
		switch(c) {
		case '-':
			/* getopt already handles -- internally, however */
			/* this allows us to abort getopt when dash is at */
			/* the end of another option which is required */
			/* in order to allow things like -n- on #! line */
			goto abort_getopt;
		case 'c': /* command */
			exp_cmdlinecmds = TRUE;
			rc = Tcl_Eval(interp,optarg);
			if (rc != TCL_OK) {
			    expErrorLogU(exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));
			    expErrorLogU("\r\n");
			}
			break;
		case 'd': expDiagToStderrSet(TRUE);
			expDiagLog("expect version %s\r\n",exp_version);
			break;
#ifdef TCL_DEBUGGER
		case 'D':
			exp_tcl_debugger_available = TRUE;
			if (Tcl_GetInt(interp,optarg,&rc) != TCL_OK) {
			    expErrorLog("%s: -D argument must be 0 or 1\r\n",exp_argv0);

			    /* SF #439042 -- Allow overide of "exit" by user / script
			     */
			    {
			      char buffer [] = "exit 1";
			      Tcl_Eval(interp, buffer); 
			    }
			}

			/* set up trap handler before Dbg_On so user does */
			/* not have to see it at first debugger prompt */
			if (0 == (debug_init = getenv("EXPECT_DEBUG_INIT"))) {
				debug_init = debug_init_default;
			}
600
601
602
603
604
605
606





607

608
609
610
611
612
613
614
615
616


617
618
619
620
621
622
623
624
625
626














627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647





648

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680


681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707






708

709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728






729

730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
			my_rc = FALSE;
			break;
		case 'N': /* don't read system-wide rc file */
			sys_rc = FALSE;
			break;
		case 'v':
			printf("expect version %s\n", exp_version);





			exp_exit (interp, 0);

			break;
		default: usage(interp);
		}
	}

 abort_getopt:

	for (c = 0;c<argc;c++) {
		debuglog("argv[%d] = %s  ",c,argv[c]);


	}
	debuglog("\r\n");

	/* if user hasn't explicitly requested we be interactive */
	/* look for a file or some other source of commands */
	if (!exp_interactive) {
		/* get cmd file name, if we haven't got it already */
		if (!exp_cmdfilename && (optind < argc)) {
			exp_cmdfilename = argv[optind];
			optind++;














		}

		if (exp_cmdfilename) {
			if (streq(exp_cmdfilename,"-")) {
				exp_cmdfile = stdin;
				exp_cmdfilename = 0;
			} else if (exp_buffer_command_input) {
				errno = 0;
				exp_cmdfile = fopen(exp_cmdfilename,"r");
				if (exp_cmdfile) {
					exp_cmdfilename = 0;
					exp_close_on_exec(fileno(exp_cmdfile));
				} else {
					char *msg;

					if (errno == 0) {
						msg = "could not read - odd file name?";
					} else {
						msg = Tcl_ErrnoMsg(errno);
					}
					errorlog("%s: %s\r\n",exp_cmdfilename,msg);





					exp_exit(interp,1);

				}
			}
		} else if (!exp_cmdlinecmds) {
			if (isatty(0)) {
				/* no other source of commands, force interactive */
				exp_interactive = TRUE;
			} else {
				/* read cmds from redirected stdin */
				exp_cmdfile = stdin;
			}
		}
	}

	if (exp_interactive) {
		Tcl_SetVar(interp, "tcl_interactive","1",TCL_GLOBAL_ONLY);
	}

	/* collect remaining args and make into argc, argv0, and argv */
	sprintf(argc_rep,"%d",argc-optind);
	Tcl_SetVar(interp,"argc",argc_rep,0);
	debuglog("set argc %s\r\n",argc_rep);

	if (exp_cmdfilename) {
		Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
		debuglog("set argv0 \"%s\"\r\n",exp_cmdfilename);
	} else {
		Tcl_SetVar(interp,"argv0",exp_argv0,0);
		debuglog("set argv0 \"%s\"\r\n",exp_argv0);
	}

	args = Tcl_Merge(argc-optind,argv+optind);
	debuglog("set argv \"%s\"\r\n",args);


	Tcl_SetVar(interp,"argv",args,0);
	ckfree(args);

	exp_interpret_rcfiles(interp,my_rc,sys_rc);
}

/* read rc files */
void
exp_interpret_rcfiles(interp,my_rc,sys_rc)
Tcl_Interp *interp;
int my_rc;
int sys_rc;
{
	int rc;

	if (sys_rc) {
	    char file[200];
	    int fd;

	    sprintf(file,"%s/expect.rc",SCRIPTDIR);
	    if (-1 != (fd = open(file,0))) {
		if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
		    errorlog("error executing system initialization file: %s\r\n",file);
		    if (rc != TCL_ERROR)
				errorlog("Tcl_Eval = %d\r\n",rc);
		    if (*interp->result != 0)
				errorlog("%s\r\n",interp->result);






		    exp_exit(interp,1);

		}
		close(fd);
	    }
	}
	if (my_rc) {
	    char file[200];
	    char *home;
	    int fd;
	    char *getenv();

	    if ((NULL != (home = getenv("DOTDIR"))) ||
		(NULL != (home = getenv("HOME")))) {
		sprintf(file,"%s/.expect.rc",home);
		if (-1 != (fd = open(file,0))) {
		    if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
			errorlog("error executing file: %s\r\n",file);
			if (rc != TCL_ERROR)
				errorlog("Tcl_Eval = %d\r\n",rc);
			if (*interp->result != 0)
				errorlog("%s\r\n",interp->result);






			exp_exit(interp,1);

		    }
		    close(fd);
	        }
	    }
	}
}

int
exp_interpret_cmdfilename(interp,filename)
Tcl_Interp *interp;
char *filename;
{
	int rc;

	debuglog("executing commands from command file %s\r\n",filename);

	Tcl_ResetResult(interp);
	if (TCL_OK != (rc = Tcl_EvalFile(interp,filename))) {
		/* EvalFile doesn't bother to copy error to errorInfo */
		/* so force it */
		Tcl_AddErrorInfo(interp, "");
		handle_eval_error(interp,0);
	}
	return rc;
}

int
exp_interpret_cmdfile(interp,fp)
Tcl_Interp *interp;
FILE *fp;
{
	int rc = 0;
	int newcmd;
	int eof;

	Tcl_DString dstring;
	Tcl_DStringInit(&dstring);

	debuglog("executing commands from command file\r\n");

	newcmd = TRUE;
	eof = FALSE;
	while (1) {
		char line[BUFSIZ];/* buffer for partial Tcl command */
		char *ccmd;	/* pointer to complete Tcl command */

		if (fgets(line,BUFSIZ,fp) == NULL) {
			if (newcmd) break;
			eof = TRUE;
		}
		ccmd = Tcl_DStringAppend(&dstring,line,-1);
		if (!Tcl_CommandComplete(ccmd) && !eof) {
			newcmd = FALSE;
			continue;	/* continue collecting command */
		}
		newcmd = TRUE;

		rc = Tcl_Eval(interp,ccmd);
		Tcl_DStringFree(&dstring);
		if (rc != TCL_OK) {
			handle_eval_error(interp,0);
			break;
		}
		if (eof) break;
	}
	Tcl_DStringFree(&dstring);
	return rc;
}

#ifdef SHARE_CMD_BUFFER
/* fgets that shared input buffer with expect_user */
int
exp_fgets(interp,buf,max)
Tcl_Interp *interp;
char *buf;
int max;
{
	char *nl;	/* position of newline which signifies end of line */
	int write_count;/* length of first line of incoming data */

	int m = fileno(stdin);
	struct exp_f *f;
	int cc;

	int dummy;

	/* avoid returning no data, just because someone else read it in by */
	/* passing most recent key */
	cc = exp_get_next_event(interp,&m,1,&dummy,EXP_TIME_INFINITY,exp_fs[m].key);

	if (cc == EXP_DATA_NEW) {
		/* try to read it */

		cc = exp_i_read(m,EXP_TIME_INFINITY);

		/* the meaning of 0 from i_read means eof.  Muck with it a */
		/* little, so that from now on it means "no new data arrived */
		/* but it should be looked at again anyway". */
		if (cc == 0) {
			cc = EXP_EOF;
		} else if (cc > 0) {
			f = exp_fs + m;
			f->buffer[f->size += cc] = '\0';
		}
	} else if (cc == EXP_DATA_OLD) {
		f = exp_fs + m;
		cc = 0;
	}

	/* EOF and TIMEOUT return here */
	/* In such cases, there is no need to update screen since, if there */
	/* was prior data read, it would have been sent to the screen when */
	/* it was read. */
	if (cc < 0) return (cc);

	/* copy up to end of first line */

	/* calculate end of first line */
	nl = strchr(f->buffer,'\n');
	if (nl) write_count = 1+nl-f->buffer;
	else write_count = f->size;

	/* make sure line fits in buffer area */
	if (write_count > max) write_count = max;

	/* copy it */
	memcpy(buf,f->buffer,write_count);
	buf[write_count] = '\0';

	/* update display and f */

	f->printed = 0;
	/* for simplicity force f->printed = 0.  This way, the user gets */
	/* to see the commands that are about to be executed.  Not seeing */
	/* commands you are supposedly typing sounds very uncomfortable! */

	if (logfile_all || (loguser && logfile)) {
		fwrite(f->buffer,1,write_count,logfile);
	}
	if (debugfile) fwrite(f->buffer,1,write_count,debugfile);

	f->size -= write_count;
	memcpy(f->buffer,f->buffer+write_count,1+f->size);
	/* copy to lowercase buffer */
	exp_lowmemcpy(f->lower,f->buffer,1+f->size);

	return(write_count);
}
#endif /*SHARE_CMD_BUFFER*/

static struct exp_cmd_data cmd_data[]  = {
{"expect_version",exp_proc(Exp_ExpVersionCmd),	0,	0},	/* deprecated */
{"exp_version",	exp_proc(Exp_ExpVersionCmd),	0,	0},
{"prompt1",	exp_proc(Exp_Prompt1Cmd),		0,	EXP_NOPREFIX},
{"prompt2",	exp_proc(Exp_Prompt2Cmd),		0,	EXP_NOPREFIX},
{0}};

void
exp_init_main_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);
}







>
>
>
>
>
|
>








|
>
>

|








>
>
>
>
>
>
>
>
>
>
>
>
>
>











|








|
>
>
>
>
>
|
>




















|



|


|



|
>
>

|




















|

|
|
|
>
>
>
>
>
>
|
>















|

|
|
|
>
>
>
>
>
>
|
>














|

















|





|

|






|




|


|













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<

|
|








671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913

















































































914

915
916
917
918
919
920
921
922
923
924
925
			my_rc = FALSE;
			break;
		case 'N': /* don't read system-wide rc file */
			sys_rc = FALSE;
			break;
		case 'v':
			printf("expect version %s\n", exp_version);

			/* SF #439042 -- Allow overide of "exit" by user / script
			 */
			{
			  char buffer [] = "exit 0";
			  Tcl_Eval(interp, buffer); 
			}
			break;
		default: usage(interp);
		}
	}

 abort_getopt:

	for (c = 0;c<argc;c++) {
	    expDiagLog("argv[%d] = ",c);
	    expDiagLogU(argv[c]);
	    expDiagLogU("  ");
	}
	expDiagLogU("\r\n");

	/* if user hasn't explicitly requested we be interactive */
	/* look for a file or some other source of commands */
	if (!exp_interactive) {
		/* get cmd file name, if we haven't got it already */
		if (!exp_cmdfilename && (optind < argc)) {
			exp_cmdfilename = argv[optind];
			optind++;

			/*
			 * [#418892]. Skip a "--" found immediately
			 * behind the name of the script to
			 * execute. Don't try this if there are no
			 * arguments behind the "--" anymore. All
			 * other appearances of "--" are handled by
			 * the "getopt"-loop above.
			 */

			if ((optind < argc) &&
			    (0 == strcmp ("--", argv[optind]))) {
			    optind++;
			}
		}

		if (exp_cmdfilename) {
			if (streq(exp_cmdfilename,"-")) {
				exp_cmdfile = stdin;
				exp_cmdfilename = 0;
			} else if (exp_buffer_command_input) {
				errno = 0;
				exp_cmdfile = fopen(exp_cmdfilename,"r");
				if (exp_cmdfile) {
					exp_cmdfilename = 0;
					expCloseOnExec(fileno(exp_cmdfile));
				} else {
					char *msg;

					if (errno == 0) {
						msg = "could not read - odd file name?";
					} else {
						msg = Tcl_ErrnoMsg(errno);
					}
					expErrorLog("%s: %s\r\n",exp_cmdfilename,msg);

					/* SF #439042 -- Allow overide of "exit" by user / script
					 */
					{
					  char buffer [] = "exit 1";
					  Tcl_Eval(interp, buffer); 
					}
				}
			}
		} else if (!exp_cmdlinecmds) {
			if (isatty(0)) {
				/* no other source of commands, force interactive */
				exp_interactive = TRUE;
			} else {
				/* read cmds from redirected stdin */
				exp_cmdfile = stdin;
			}
		}
	}

	if (exp_interactive) {
		Tcl_SetVar(interp, "tcl_interactive","1",TCL_GLOBAL_ONLY);
	}

	/* collect remaining args and make into argc, argv0, and argv */
	sprintf(argc_rep,"%d",argc-optind);
	Tcl_SetVar(interp,"argc",argc_rep,0);
	expDiagLog("set argc %s\r\n",argc_rep);

	if (exp_cmdfilename) {
		Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
		expDiagLog("set argv0 \"%s\"\r\n",exp_cmdfilename);
	} else {
		Tcl_SetVar(interp,"argv0",exp_argv0,0);
		expDiagLog("set argv0 \"%s\"\r\n",exp_argv0);
	}

	args = Tcl_Merge(argc-optind,argv+optind);
	expDiagLogU("set argv \"");
	expDiagLogU(args);
	expDiagLogU("\"\r\n");
	Tcl_SetVar(interp,"argv",args,0);
	Tcl_Free(args);

	exp_interpret_rcfiles(interp,my_rc,sys_rc);
}

/* read rc files */
void
exp_interpret_rcfiles(interp,my_rc,sys_rc)
Tcl_Interp *interp;
int my_rc;
int sys_rc;
{
	int rc;

	if (sys_rc) {
	    char file[200];
	    int fd;

	    sprintf(file,"%s/expect.rc",SCRIPTDIR);
	    if (-1 != (fd = open(file,0))) {
		if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
		    expErrorLog("error executing system initialization file: %s\r\n",file);
		    if (rc != TCL_ERROR)
			expErrorLog("Tcl_Eval = %d\r\n",rc);
		    if (*interp->result != 0) {
			expErrorLogU(interp->result);
			expErrorLogU("\r\n");
		    }
		    /* SF #439042 -- Allow overide of "exit" by user / script
		     */
		    {
		      char buffer [] = "exit 1";
		      Tcl_Eval(interp, buffer); 
		    }
		}
		close(fd);
	    }
	}
	if (my_rc) {
	    char file[200];
	    char *home;
	    int fd;
	    char *getenv();

	    if ((NULL != (home = getenv("DOTDIR"))) ||
		(NULL != (home = getenv("HOME")))) {
		sprintf(file,"%s/.expect.rc",home);
		if (-1 != (fd = open(file,0))) {
		    if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
			expErrorLog("error executing file: %s\r\n",file);
			if (rc != TCL_ERROR)
				expErrorLog("Tcl_Eval = %d\r\n",rc);
			if (*interp->result != 0) {
			    expErrorLogU(interp->result);
			    expErrorLogU("\r\n");
			}
			/* SF #439042 -- Allow overide of "exit" by user / script
			 */
			{
			  char buffer [] = "exit 1";
			  Tcl_Eval(interp, buffer); 
			}
		    }
		    close(fd);
	        }
	    }
	}
}

int
exp_interpret_cmdfilename(interp,filename)
Tcl_Interp *interp;
char *filename;
{
	int rc;

	expDiagLog("executing commands from command file %s\r\n",filename);

	Tcl_ResetResult(interp);
	if (TCL_OK != (rc = Tcl_EvalFile(interp,filename))) {
		/* EvalFile doesn't bother to copy error to errorInfo */
		/* so force it */
		Tcl_AddErrorInfo(interp, "");
		handle_eval_error(interp,0);
	}
	return rc;
}

int
exp_interpret_cmdfile(interp,fp)
Tcl_Interp *interp;
FILE *fp;
{
	int rc = 0;
	int gotPartial;
	int eof;

	Tcl_DString dstring;
	Tcl_DStringInit(&dstring);

	expDiagLogU("executing commands from command file\r\n");

	gotPartial = 0;
	eof = FALSE;
	while (1) {
		char line[BUFSIZ];/* buffer for partial Tcl command */
		char *ccmd;	/* pointer to complete Tcl command */

		if (fgets(line,BUFSIZ,fp) == NULL) {
			if (!gotPartial) break;
			eof = TRUE;
		}
		ccmd = Tcl_DStringAppend(&dstring,line,-1);
		if (!Tcl_CommandComplete(ccmd) && !eof) {
			gotPartial = 1;
			continue;	/* continue collecting command */
		}
		gotPartial = 0;

		rc = Tcl_Eval(interp,ccmd);
		Tcl_DStringFree(&dstring);
		if (rc != TCL_OK) {
			handle_eval_error(interp,0);
			break;
		}
		if (eof) break;
	}
	Tcl_DStringFree(&dstring);
	return rc;
}


















































































static struct exp_cmd_data cmd_data[]  = {

{"exp_version",	exp_proc(Exp_ExpVersionCmd),	0,	0},
{"prompt1",	exp_proc(Exp_Prompt1Cmd),	0,	EXP_NOPREFIX},
{"prompt2",	exp_proc(Exp_Prompt2Cmd),	0,	EXP_NOPREFIX},
{0}};

void
exp_init_main_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);
}

Changes to exp_main_tk.c.

164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180
static char *colormap;
static char *visual;
static int rest = 0;

/* for Expect */
int my_rc = 1;
int sys_rc = 1;
int optcmd_eval();

#ifdef TCL_DEBUGGER
int optcmd_debug();
#endif
int print_version = 0;

static Tk_ArgvInfo argTable[] = {
    {"-colormap", TK_ARGV_STRING, (char *) NULL, (char *) &colormap,
	"Colormap for main window"},
    {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,







|
>

|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
static char *colormap;
static char *visual;
static int rest = 0;

/* for Expect */
int my_rc = 1;
int sys_rc = 1;
static int optcmd_eval();
static int optcmd_diagToStderr();
#ifdef TCL_DEBUGGER
static int optcmd_debug();
#endif
int print_version = 0;

static Tk_ArgvInfo argTable[] = {
    {"-colormap", TK_ARGV_STRING, (char *) NULL, (char *) &colormap,
	"Colormap for main window"},
    {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display,
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    {"-visual", TK_ARGV_STRING, (char *) NULL, (char *) &visual,
	"Visual for main window"},
    {"--", TK_ARGV_REST, (char *) 1, (char *) &rest,
	"Pass all remaining arguments through to script"},
/* for Expect */
    {"-command", TK_ARGV_GENFUNC, (char *) optcmd_eval, (char *)0,
	"Command(s) to execute immediately"},
    {"-diag", TK_ARGV_CONSTANT, (char *) 1, (char *) &exp_is_debugging,
	"Enable diagnostics"},
    {"-norc", TK_ARGV_CONSTANT, (char *) 0, (char *) &my_rc,
	"Don't read ~/.expect.rc"},
    {"-NORC", TK_ARGV_CONSTANT, (char *) 0, (char *) &sys_rc,
	"Don't read system-wide expect.rc"},
    {"-version", TK_ARGV_CONSTANT, (char *) 1, (char *) &print_version,
	"Print version and exit"},







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    {"-visual", TK_ARGV_STRING, (char *) NULL, (char *) &visual,
	"Visual for main window"},
    {"--", TK_ARGV_REST, (char *) 1, (char *) &rest,
	"Pass all remaining arguments through to script"},
/* for Expect */
    {"-command", TK_ARGV_GENFUNC, (char *) optcmd_eval, (char *)0,
	"Command(s) to execute immediately"},
    {"-diag", TK_ARGV_CONSTANT, (char *) optcmd_diagToStderr, (char *)0,
	"Enable diagnostics"},
    {"-norc", TK_ARGV_CONSTANT, (char *) 0, (char *) &my_rc,
	"Don't read ~/.expect.rc"},
    {"-NORC", TK_ARGV_CONSTANT, (char *) 0, (char *) &sys_rc,
	"Don't read system-wide expect.rc"},
    {"-version", TK_ARGV_CONSTANT, (char *) 1, (char *) &print_version,
	"Print version and exit"},
265
266
267
268
269
270
271





272

273
274
275
276
277
278
279
	    ckfree((char *) argv);
	    goto argError;
	}

	if (print_version) {
	    extern char exp_version[];
	    printf ("expectk version %s\n", exp_version);





	    exp_exit (interp, 0);

	}

	p = Tcl_Merge(argc, argv);
	Tcl_SetVar2(interp, "argv", (char *) NULL, p, TCL_GLOBAL_ONLY);
	sprintf(buffer, "%d", argc);
	Tcl_SetVar2(interp, "argc", (char *) NULL, buffer, TCL_GLOBAL_ONLY);
	ckfree(p);







>
>
>
>
>
|
>







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
	    ckfree((char *) argv);
	    goto argError;
	}

	if (print_version) {
	    extern char exp_version[];
	    printf ("expectk version %s\n", exp_version);

	    /* SF #439042 -- Allow overide of "exit" by user / script
	     */
	    {
	      char buffer [] = "exit 0";
	      Tcl_Eval(interp, buffer); 
	    }
	}

	p = Tcl_Merge(argc, argv);
	Tcl_SetVar2(interp, "argv", (char *) NULL, p, TCL_GLOBAL_ONLY);
	sprintf(buffer, "%d", argc);
	Tcl_SetVar2(interp, "argc", (char *) NULL, buffer, TCL_GLOBAL_ONLY);
	ckfree(p);
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
	goto done;
    }

    /*
     * Invoke platform-specific initialization.
     */

#if TCL_MAJOR_VERSION < 8
    code = TkPlatformInit(interp);
#else
    code = TkpInit(interp, 0);
#endif

    done:
    if (argv != NULL) {
	ckfree((char *) argv);
    }
    return code;
}

/*ARGSUSED*/
int
optcmd_eval(dst,interp,key,argc,argv)
char *dst;
Tcl_Interp *interp;
char *key;
int argc;
char **argv;
{







<
<
<

<









|







375
376
377
378
379
380
381



382

383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
	goto done;
    }

    /*
     * Invoke platform-specific initialization.
     */




    code = TkpInit(interp, 0);


    done:
    if (argv != NULL) {
	ckfree((char *) argv);
    }
    return code;
}

/*ARGSUSED*/
static int
optcmd_eval(dst,interp,key,argc,argv)
char *dst;
Tcl_Interp *interp;
char *key;
int argc;
char **argv;
{
405
406
407
408
409
410
411












412
413
414
415
416
417
418
419
420
421
422
	argc--;
	for (i=0;i<argc;i++) {
		argv[i] = argv[i+1];
	}

	return argc;
}













#ifdef TCL_DEBUGGER
/*ARGSUSED*/
int
optcmd_debug(dst,interp,key,argc,argv)
char *dst;
Tcl_Interp *interp;
char *key;
int argc;
char **argv;
{







>
>
>
>
>
>
>
>
>
>
>
>



|







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
	argc--;
	for (i=0;i<argc;i++) {
		argv[i] = argv[i+1];
	}

	return argc;
}

static int
optcmd_diagToStderr(dst,interp,key,argc,argv)
    char *dst;
    Tcl_Interp *interp;
    char *key;
    int argc;
    char **argv;
{
    expDiagToStderrSet(1);
    return --argc;  /* what the heck is the convention here!! */
}

#ifdef TCL_DEBUGGER
/*ARGSUSED*/
static int
optcmd_debug(dst,interp,key,argc,argv)
char *dst;
Tcl_Interp *interp;
char *key;
int argc;
char **argv;
{

Changes to exp_noevent.c.

26
27
28
29
30
31
32
33
34
35
36
37
38



39




40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for struct exp_f defs */
#include "exp_event.h"

/*ARGSUSED*/
void
exp_arm_background_filehandler(m)



int m;




{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler_force(m)
int m;
{
}

/*ARGSUSED*/
void
exp_unblock_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_block_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_event_disarm(fd)
int fd;
{
}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event(interp,masters, n,master_out,timeout,key)
Tcl_Interp *interp;
int *masters;
int n;			/* # of masters */
int *master_out;	/* 1st event master, not set if none */
int timeout;		/* seconds */
int key;
{
	int m;
	struct exp_f *f;

	if (n > 1) {
		exp_error(interp,"expect not compiled with multiprocess support");
		/* select a different INTERACT_TYPE in Makefile */
		return(TCL_ERROR);
	}

	m = *master_out = masters[0];
	f = exp_fs + m;

	if (f->key != key) {
		f->key = key;
		f->force_read = FALSE;
		return(EXP_DATA_OLD);
	} else if ((!f->force_read) && (f->size != 0)) {
		return(EXP_DATA_OLD);
	}

	return(EXP_DATA_NEW);
}

/*ARGSUSED*/
int
exp_get_next_event_info(interp,fd,ready_mask)
Tcl_Interp *interp;
int fd;

int ready_mask;
{
}

/* There is no portable way to do sub-second sleeps on such a system, so */
/* do the next best thing (without a busy loop) and fake it: sleep the right */
/* amount of time over the long run.  Note that while "subtotal" isn't */







|




|
>
>
>
|
>
>
>
>





|
|





|
|





|
<
<
<
|
<
<
<
<













|

|
|
|



<
<
<
|
|
|
|
|

|
<

|
|
|
|
|
|
|

|




|

<
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66



67




68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for struct ExpState defs */
#include "exp_event.h"

/*ARGSUSED*/
void
exp_arm_background_filehandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler_force(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_unblock_background_filehandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_block_background_filehandler(esPtr)



ExpState *esPtr;




{
}

/*ARGSUSED*/
void
exp_event_disarm(fd)
int fd;
{
}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key)
Tcl_Interp *interp;
ExpState (*esPtrs)[];
int n;			/* # of esPtrs */
ExpState **esPtrOut;	/* 1st event master, not set if none */
int timeout;		/* seconds */
int key;
{



    if (n > 1) {
	exp_error(interp,"expect not compiled with multiprocess support");
	/* select a different INTERACT_TYPE in Makefile */
	return(TCL_ERROR);
    }

    esPtr = *esPtrOut = esPtrs[0];


    if (esPtr->key != key) {
	esPtr->key = key;
	esPtr->force_read = FALSE;
	return(EXP_DATA_OLD);
    } else if ((!esPtr->force_read) && (esPtr->size != 0)) {
	return(EXP_DATA_OLD);
    }

    return(EXP_DATA_NEW);
}

/*ARGSUSED*/
int
exp_get_next_event_info(interp,esPtr,ready_mask)
Tcl_Interp *interp;

ExpState *esPtr;
int ready_mask;
{
}

/* There is no portable way to do sub-second sleeps on such a system, so */
/* do the next best thing (without a busy loop) and fake it: sleep the right */
/* amount of time over the long run.  Note that while "subtotal" isn't */

Changes to exp_poll.c.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 */

static struct pollfd initialFdArray;
static struct pollfd *fdArray = &initialFdArray;
static int fdsInUse = 0;	/* space in use */
static int fdsMaxSpace = 1;	/* space that has actually been allocated */

#if TCL_MAJOR_VERSION >= 8

/*
 * tclUnixNotify.c --
 *
 *	This file contains the implementation of the select-based
 *	Unix-specific notifier, which is the lowest-level part of the
 *	Tcl event loop.  This file works together with
 *	../generic/tclNotify.c.







<
<







29
30
31
32
33
34
35


36
37
38
39
40
41
42
 */

static struct pollfd initialFdArray;
static struct pollfd *fdArray = &initialFdArray;
static int fdsInUse = 0;	/* space in use */
static int fdsMaxSpace = 1;	/* space that has actually been allocated */



/*
 * tclUnixNotify.c --
 *
 *	This file contains the implementation of the select-based
 *	Unix-specific notifier, which is the lowest-level part of the
 *	Tcl event loop.  This file works together with
 *	../generic/tclNotify.c.
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = notifier.firstFileHandlerPtr;
	notifier.firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;
#if NOTUSED
    /* remaining junk is left over from select implementation - DEL */

    filePtr->mask = mask;

    /*
     * Update the check masks for this file.
     */

    index = fd/(NBBY*sizeof(fd_mask));
    bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
    if (mask & TCL_READABLE) {
	notifier.checkMasks[index] |= bit;
    } else {
	notifier.checkMasks[index] &= ~bit;
    } 
    if (mask & TCL_WRITABLE) {
	(notifier.checkMasks+MASK_SIZE)[index] |= bit;
    } else {
	(notifier.checkMasks+MASK_SIZE)[index] &= ~bit;
    }
    if (mask & TCL_EXCEPTION) {
	(notifier.checkMasks+2*(MASK_SIZE))[index] |= bit;
    } else {
	(notifier.checkMasks+2*(MASK_SIZE))[index] &= ~bit;
    }
    if (notifier.numFdBits <= fd) {
	notifier.numFdBits = fd+1;
    }
#endif /* notused */

    filePtr->pollArrayIndex = fdsInUse;
    cur_fd_index = fdsInUse;

    fdsInUse++;
    if (fdsInUse > fdsMaxSpace) {
	if (fdArray != &initialFdArray) ckfree((char *)fdArray);
	fdArray = (struct pollfd *)ckalloc(fdsInUse*sizeof(struct pollfd));







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







245
246
247
248
249
250
251































252
253
254
255
256
257
258
	filePtr->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = notifier.firstFileHandlerPtr;
	notifier.firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;































    filePtr->pollArrayIndex = fdsInUse;
    cur_fd_index = fdsInUse;

    fdsInUse++;
    if (fdsInUse > fdsMaxSpace) {
	if (fdArray != &initialFdArray) ckfree((char *)fdArray);
	fdArray = (struct pollfd *)ckalloc(fdsInUse*sizeof(struct pollfd));
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	    return;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

#if NOTUSED
    /* remaining junk is left over from select implementation - DEL */

    /*
     * Update the check masks for this file.
     */

    index = fd/(NBBY*sizeof(fd_mask));
    bit = 1 << (fd%(NBBY*sizeof(fd_mask)));

    if (filePtr->mask & TCL_READABLE) {
	notifier.checkMasks[index] &= ~bit;
    }
    if (filePtr->mask & TCL_WRITABLE) {
	(notifier.checkMasks+MASK_SIZE)[index] &= ~bit;
    }
    if (filePtr->mask & TCL_EXCEPTION) {
	(notifier.checkMasks+2*(MASK_SIZE))[index] &= ~bit;
    }

    /*
     * Find current max fd.
     */

    if (fd+1 == notifier.numFdBits) {
	for (notifier.numFdBits = 0; index >= 0; index--) {
	    mask = notifier.checkMasks[index]
		| (notifier.checkMasks+MASK_SIZE)[index]
		| (notifier.checkMasks+2*(MASK_SIZE))[index];
	    if (mask) {
		for (i = (NBBY*sizeof(fd_mask)); i > 0; i--) {
		    if (mask & (1 << (i-1))) {
			break;
		    }
		}
		notifier.numFdBits = index * (NBBY*sizeof(fd_mask)) + i;
		break;
	    }
	}
    }
#endif /* notused */

    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	notifier.firstFileHandlerPtr = filePtr->nextPtr;
    } else {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







316
317
318
319
320
321
322










































323
324
325
326
327
328
329
	    return;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }











































    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	notifier.firstFileHandlerPtr = filePtr->nextPtr;
    } else {
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

int
Tcl_WaitForEvent(timePtr)
    Tcl_Time *timePtr;		/* Maximum block time, or NULL. */
{
    FileHandler *filePtr;
    FileHandlerEvent *fileEvPtr;
#if 0
    struct timeval timeout, *timeoutPtr;
#endif
    int timeout;
    struct timeval *timeoutPtr;

    int bit, index, mask, numFound;

    if (!initialized) {
	InitNotifier();
    }

    /*
     * Set up the timeout structure.  Note that if there are no events to
     * check for, we return with a negative result rather than blocking
     * forever.
     */

    if (timePtr) {
#if 0
	timeout.tv_sec = timePtr->sec;
	timeout.tv_usec = timePtr->usec;
	timeoutPtr = &timeout;
#endif
        timeout = timePtr->sec*1000 + timePtr->usec/1000;

    } else if (notifier.numFdBits == 0) {
	return -1;
    } else {
	timeoutPtr = NULL;
    }

    numFound = poll(fdArray,fdsInUse,timeout);
#if 0
    memcpy((VOID *) notifier.readyMasks, (VOID *) notifier.checkMasks,
	    3*MASK_SIZE*sizeof(fd_mask));
    numFound = select(notifier.numFdBits,
	    (SELECT_MASK *) &notifier.readyMasks[0],
	    (SELECT_MASK *) &notifier.readyMasks[MASK_SIZE],
	    (SELECT_MASK *) &notifier.readyMasks[2*MASK_SIZE], timeoutPtr);

    /*
     * Some systems don't clear the masks after an error, so
     * we have to do it here.
     */

    if (numFound == -1) {
	memset((VOID *) notifier.readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask));
    }
#endif

    /*
     * Queue all detected file events before returning.
     */

    for (filePtr = notifier.firstFileHandlerPtr;
	    (filePtr != NULL) && (numFound > 0);







<
<
<
















<
<
<
<
<









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







450
451
452
453
454
455
456



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472





473
474
475
476
477
478
479
480
481

















482
483
484
485
486
487
488

int
Tcl_WaitForEvent(timePtr)
    Tcl_Time *timePtr;		/* Maximum block time, or NULL. */
{
    FileHandler *filePtr;
    FileHandlerEvent *fileEvPtr;



    int timeout;
    struct timeval *timeoutPtr;

    int bit, index, mask, numFound;

    if (!initialized) {
	InitNotifier();
    }

    /*
     * Set up the timeout structure.  Note that if there are no events to
     * check for, we return with a negative result rather than blocking
     * forever.
     */

    if (timePtr) {





        timeout = timePtr->sec*1000 + timePtr->usec/1000;

    } else if (notifier.numFdBits == 0) {
	return -1;
    } else {
	timeoutPtr = NULL;
    }

    numFound = poll(fdArray,fdsInUse,timeout);


















    /*
     * Queue all detected file events before returning.
     */

    for (filePtr = notifier.firstFileHandlerPtr;
	    (filePtr != NULL) && (numFound > 0);
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
	    mask |= TCL_WRITABLE;
        }
        /* I have no idea if this is right ... */
        if (fdArray[index].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) {
	    mask |= TCL_EXCEPTION;
        }

#if 0
	index = filePtr->fd / (NBBY*sizeof(fd_mask));
	bit = 1 << (filePtr->fd % (NBBY*sizeof(fd_mask)));
	mask = 0;

	if (notifier.readyMasks[index] & bit) {
	    mask |= TCL_READABLE;
	}
	if ((notifier.readyMasks+MASK_SIZE)[index] & bit) {
	    mask |= TCL_WRITABLE;
	}
	if ((notifier.readyMasks+2*(MASK_SIZE))[index] & bit) {
	    mask |= TCL_EXCEPTION;
	}
#endif

	if (!mask) {
	    continue;
	} else {
	    numFound--;
	}

	/*







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







497
498
499
500
501
502
503
















504
505
506
507
508
509
510
	    mask |= TCL_WRITABLE;
        }
        /* I have no idea if this is right ... */
        if (fdArray[index].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) {
	    mask |= TCL_EXCEPTION;
        }

















	if (!mask) {
	    continue;
	} else {
	    numFound--;
	}

	/*
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
    return 0;
}

#else /* TCL_MAJOR_VERSION < 8 */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WatchFile --
 *
 *	Arrange for Tcl_DoOneEvent to include this file in the masks
 *	for the next call to select.  This procedure is invoked by
 *	event sources, which are in turn invoked by Tcl_DoOneEvent
 *	before it invokes select.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	
 *	The notifier will generate a file event when the I/O channel
 *	given by fd next becomes ready in the way indicated by mask.
 *	If fd is already registered then the old mask will be replaced
 *	with the new one.  Once the event is sent, the notifier will
 *	not send any more events about the fd until the next call to
 *	Tcl_NotifyFile. 
 *
 * Assumption for poll implementation: Tcl_WatchFile is presumed NOT
 * to be called on the same file descriptior without intervening calls
 * to Tcl_DoOneEvent.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_WatchFile(file, mask)
    Tcl_File file;	/* Generic file handle for a stream. */
    int mask;			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION:
				 * indicates conditions to wait for
				 * in select. */
{
    int fd, type;
    int cur_fd_index = fdsInUse;

    fd = (int) Tcl_GetFileInfo(file, &type);

    if (type != TCL_UNIX_FD) {
	panic("Tcl_WatchFile: unexpected file type");
    }

    fdsInUse++;
    if (fdsInUse > fdsMaxSpace) {
	if (fdArray != &initialFdArray) ckfree((char *)fdArray);
	fdArray = (struct pollfd *)ckalloc(fdsInUse*sizeof(struct pollfd));
	fdsMaxSpace = fdsInUse;
    }

    fdArray[cur_fd_index].fd = fd;

    /* I know that POLLIN/OUT is right.  But I have no idea if POLLPRI
     * corresponds well to TCL_EXCEPTION.
     */

    if (mask & TCL_READABLE) {
        fdArray[cur_fd_index].events = POLLIN;
    }
    if (mask & TCL_WRITABLE) {
        fdArray[cur_fd_index].events = POLLOUT;
    }
    if (mask & TCL_EXCEPTION) {
        fdArray[cur_fd_index].events = POLLPRI;
    }
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_FileReady --
 *
 *	Indicates what conditions (readable, writable, etc.) were
 *	present on a file the last time the notifier invoked select.
 *	This procedure is typically invoked by event sources to see
 *	if they should queue events.
 *
 * Results:
 *	The return value is 0 if none of the conditions specified by mask
 *	was true for fd the last time the system checked.  If any of the
 *	conditions were true, then the return value is a mask of those
 *	that were true.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FileReady(file, mask)
    Tcl_File file;	/* Generic file handle for a stream. */
    int mask;			/* OR'ed combination of TCL_READABLE,
				 * TCL_WRITABLE, and TCL_EXCEPTION:
				 * indicates conditions caller cares about. */
{
    int index, result, type, fd;
    fd_mask bit;

    fd = (int) Tcl_GetFileInfo(file, &type);
    if (type != TCL_UNIX_FD) {
	panic("Tcl_FileReady: unexpected file type");
    }

    result = 0;
    if ((mask & TCL_READABLE) && (fdArray[fd].revents & POLLIN)) {
	result |= TCL_READABLE;
    }
    if ((mask & TCL_WRITABLE) && (fdArray[fd].revents & POLLOUT)) {
	result |= TCL_WRITABLE;
    }
    /* I have no idea if this is right ... */
    if ((mask & TCL_EXCEPTION) &&
		(fdArray[fd].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL))) {
	result |= TCL_EXCEPTION;
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	This procedure does the lowest level wait for events in a
 *	platform-specific manner.  It uses information provided by
 *	previous calls to Tcl_WatchFile, plus the timePtr argument,
 *	to determine what to wait for and how long to wait.
 *
 * Results:
 * 7.6  The return value is normally TCL_OK.  However, if there are
 *      no events to wait for (e.g. no files and no timers) so that
 *      the procedure would block forever, then it returns TCL_ERROR.
 *
 * Side effects:
 *	May put the process to sleep for a while, depending on timePtr.
 *	When this procedure returns, an event of interest to the application
 *	has probably, but not necessarily, occurred.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(timePtr)
    Tcl_Time *timePtr;		/* Specifies the maximum amount of time
				 * that this procedure should block before
				 * returning.  The time is given as an
				 * interval, not an absolute wakeup time.
				 * NULL means block forever. */
{
    int timeout;
    struct timeval *timeoutPtr;

    /* no need to clear revents */
    if (timePtr == NULL) {
	if (!fdsInUse) return (TCL_ERROR);
	timeout = -1;
    } else {
        timeout = timePtr->sec*1000 + timePtr->usec/1000;
    }

    poll(fdArray,fdsInUse,timeout);

    fdsInUse = 0;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Sleep --
 *
 *	Delay execution for the specified number of milliseconds.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Time passes.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Sleep(ms)
    int ms;			/* Number of milliseconds to sleep. */
{
    static struct timeval delay;
    Tcl_Time before, after;

    /*
     * The only trick here is that select appears to return early
     * under some conditions, so we have to check to make sure that
     * the right amount of time really has elapsed.  If it's too
     * early, go back to sleep again.
     */

    TclGetTime(&before);
    after = before;
    after.sec += ms/1000;
    after.usec += (ms%1000)*1000;
    if (after.usec > 1000000) {
	after.usec -= 1000000;
	after.sec += 1;
    }
    while (1) {
	delay.tv_sec = after.sec - before.sec;
	delay.tv_usec = after.usec - before.usec;
	if (delay.tv_usec < 0) {
	    delay.tv_usec += 1000000;
	    delay.tv_sec -= 1;
	}

	/*
	 * Special note:  must convert delay.tv_sec to int before comparing
	 * to zero, since delay.tv_usec is unsigned on some platforms.
	 */

	if ((((int) delay.tv_sec) < 0)
		|| ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
	    break;
	}

	/* poll understands milliseconds, sigh */
	poll(fdArray,0,delay.tv_sec*1000 + delay.tv_usec/1000);
	TclGetTime(&before);
    }
}

#endif /* TCL_MAJOR_VERSION < 8 */








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
520
521
522
523
524
525
526














































































































































































































































	    Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	}
	filePtr->readyMask = mask;
    }
    return 0;
}















































































































































































































































Deleted exp_printify.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/* exp_printify - printable versions of random ASCII strings

Written by: Don Libes, NIST, 2/6/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.

*/

#include "expect_cf.h"
#include "tcl.h"
#ifdef NO_STDLIB_H
#include "../compat/stdlib.h"
#else
#include <stdlib.h>		/* for malloc */
#endif
#include <ctype.h>

/* generate printable versions of random ASCII strings.  Primarily used */
/* by cmdExpect when -d forces it to print strings it is examining. */
char *
exp_printify(s)
char *s;
{
	static int destlen = 0;
	static char *dest = 0;
	char *d;		/* ptr into dest */
	unsigned int need;

	if (s == 0) return("<null>");

	/* worst case is every character takes 4 to printify */
	need = strlen(s)*4 + 1;
	if (need > destlen) {
		if (dest) ckfree(dest);
		dest = ckalloc(need);
		destlen = need;
	}

	for (d = dest;*s;s++) {
		if (*s == '\r') {
			strcpy(d,"\\r");		d += 2;
		} else if (*s == '\n') {
			strcpy(d,"\\n");		d += 2;
		} else if (*s == '\t') {
			strcpy(d,"\\t");		d += 2;
		} else if (isascii(*s) && isprint(*s)) {
			*d = *s;			d += 1;
		} else {
			sprintf(d,"\\x%02x",*s & 0xff);	d += 4;
		}
	}
	*d = '\0';
	return(dest);
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































Deleted exp_printify.h.

1
2
3
4
5
6
#ifndef __EXP_PRINTIFY_H__
#define __EXP_PRINTIFY_H__

char *exp_printify();

#endif /* __EXP_PRINTIFY_H__ */
<
<
<
<
<
<












Changes to exp_pty.c.

30
31
32
33
34
35
36
37

38
39
40
41
42
43

44



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63



64


65
66
67
68
69
70
71
#  include <time.h>
# endif
#endif

#include <signal.h>
#include <setjmp.h>
#include <sys/file.h>
#define EXP_AVOID_INCLUDING_TCL_H 1

#include "expect_comm.h"
#include "exp_rename.h"
#include "exp_pty.h"

#include <errno.h>


void debuglog();




#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#ifdef O_NOCTTY
#define RDWR ((O_RDWR)|(O_NOCTTY))
#else
#define RDWR O_RDWR
#endif

static int locked = FALSE;
static char lock[] = "/tmp/ptylock.XXXX";	/* XX is replaced by pty id */
static char locksrc[50] = "/tmp/expect.pid"; /* pid is replaced by real pid */
	/* locksrc is used as the link source, i.e., something to link from */

static int i_read_errno;/* place to save errno, if i_read() == -1, so it
			   doesn't get overwritten before we get to read it */



static jmp_buf env;		/* for interruptable read() */


static int env_valid = FALSE;	/* whether we can longjmp or not */

/* sigalarm_handler and i_read are here just for supporting the sanity */
/* checking of pty slave devices.  I have only seen this happen on BSD */
/* systems, but it may need to be done to the other pty implementations */
/* as well. */








|
>






>
|
>
>
>



















>
>
>

>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#  include <time.h>
# endif
#endif

#include <signal.h>
#include <setjmp.h>
#include <sys/file.h>
#include "tcl.h"
#include "exp_int.h"
#include "expect_comm.h"
#include "exp_rename.h"
#include "exp_pty.h"

#include <errno.h>

#if 0
void expDiagLog();
void expDiagLogU();
void expDiagLogPtrSet();
#endif

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#ifdef O_NOCTTY
#define RDWR ((O_RDWR)|(O_NOCTTY))
#else
#define RDWR O_RDWR
#endif

static int locked = FALSE;
static char lock[] = "/tmp/ptylock.XXXX";	/* XX is replaced by pty id */
static char locksrc[50] = "/tmp/expect.pid"; /* pid is replaced by real pid */
	/* locksrc is used as the link source, i.e., something to link from */

static int i_read_errno;/* place to save errno, if i_read() == -1, so it
			   doesn't get overwritten before we get to read it */
#ifdef HAVE_SIGLONGJMP
static sigjmp_buf env;                /* for interruptable read() */
#else
static jmp_buf env;		/* for interruptable read() */
#endif  /* HAVE_SIGLONGJMP */

static int env_valid = FALSE;	/* whether we can longjmp or not */

/* sigalarm_handler and i_read are here just for supporting the sanity */
/* checking of pty slave devices.  I have only seen this happen on BSD */
/* systems, but it may need to be done to the other pty implementations */
/* as well. */

80
81
82
83
84
85
86



87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107



108

109
110
111
112
113
114
115
{
#ifdef REARM_SIG
	signal(SIGALRM,sigalarm_handler);
#endif

	/* check env_valid first to protect us from the alarm occurring */
	/* in the window between i_read and alarm(0) */



	if (env_valid) longjmp(env,1);

}

/* interruptable read */
static int
i_read(fd,buffer,length,timeout)
int fd;
char *buffer;
int length;
int timeout;
{
	int cc = -2;

	/* since setjmp insists on returning 1 upon longjmp(,0), */
	/* longjmp(,2) instead. */

	/* restart read if setjmp returns 0 (first time) or 2. */
	/* abort if setjmp returns 1. */

	alarm(timeout);




	if (1 != setjmp(env)) {

		env_valid = TRUE;
		cc = read(fd,buffer,length);
	}
	env_valid = FALSE;
	i_read_errno = errno;	/* errno can be overwritten by the */
				/* time we return */
	alarm(0);







>
>
>

>




















>
>
>

>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{
#ifdef REARM_SIG
	signal(SIGALRM,sigalarm_handler);
#endif

	/* check env_valid first to protect us from the alarm occurring */
	/* in the window between i_read and alarm(0) */
#ifdef HAVE_SIGLONGJMP
	if (env_valid) siglongjmp(env,1);
#else
	if (env_valid) longjmp(env,1);
#endif  /* HAVE_SIGLONGJMP */
}

/* interruptable read */
static int
i_read(fd,buffer,length,timeout)
int fd;
char *buffer;
int length;
int timeout;
{
	int cc = -2;

	/* since setjmp insists on returning 1 upon longjmp(,0), */
	/* longjmp(,2) instead. */

	/* restart read if setjmp returns 0 (first time) or 2. */
	/* abort if setjmp returns 1. */

	alarm(timeout);

#ifdef HAVE_SIGLONGJMP
	if (1 != sigsetjmp(env,1)) {
#else
	if (1 != setjmp(env)) {
#endif  /* HAVE_SIGLONGJMP */
		env_valid = TRUE;
		cc = read(fd,buffer,length);
	}
	env_valid = FALSE;
	i_read_errno = errno;	/* errno can be overwritten by the */
				/* time we return */
	alarm(0);
138
139
140
141
142
143
144



145

146
147
148
149
150
151
152

	time(&current_time);

	/* recreate locksrc to prevent locks from 'looking old', so */
	/* that they are not deleted (later on in this code) */
	sprintf(locksrc,"/tmp/expect.%d",getpid());
	(void) unlink(locksrc);



	if (-1 == (lfd = creat(locksrc,0777))) {

		static char buf[256];
		exp_pty_error = buf;
		sprintf(exp_pty_error,"can't create %s, errno = %d\n",locksrc, errno);
		return(-1);
	}
	close(lfd);
	return 0;







>
>
>
|
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

	time(&current_time);

	/* recreate locksrc to prevent locks from 'looking old', so */
	/* that they are not deleted (later on in this code) */
	sprintf(locksrc,"/tmp/expect.%d",getpid());
	(void) unlink(locksrc);
	/* stanislav shalunov <[email protected]> notes that creat allows */
	/* race - someone could link to important file which root could then */
	/* smash. */
/*	if (-1 == (lfd = creat(locksrc,0777))) { */
       if (-1 == (lfd = open(locksrc,O_RDWR|O_CREAT|O_EXCL,0777))) {
		static char buf[256];
		exp_pty_error = buf;
		sprintf(exp_pty_error,"can't create %s, errno = %d\n",locksrc, errno);
		return(-1);
	}
	close(lfd);
	return 0;
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
}

/* returns non-negative if successful */
int
exp_pty_test(master_name,slave_name,bank,num)
char *master_name;
char *slave_name;
int bank;
char *num;	/* string representation of number */
{
	int master, slave;
	int cc;
	char c;

	/* make a lock file to prevent others (for now only */
	/* expects) from allocating pty while we are playing */
	/* with it.  This allows us to rigorously test the */
	/* pty is usable. */
	if (exp_pty_lock(bank,num) == 0) {
		debuglog("pty master (%s) is locked...skipping\r\n",master_name);
		return(-1);
	}
	/* verify no one else is using slave by attempting */
	/* to read eof from master side */
	if (0 > (master = open(master_name,RDWR))) return(-1);

#ifdef __QNX__

	/* QNX ptys don't have a lot of the same properties such as
           read 0 at EOF, etc */
	/* if 1 should pacify C compiler without using nested ifdefs */
 	if (1) return master;
#endif

#ifdef HAVE_PTYTRAP
	if (access(slave_name, R_OK|W_OK) != 0) {
		debuglog("could not open slave for pty master (%s)...skipping\r\n",
			master_name);
		(void) close(master);
		return -1;
	}
	return(master);
#else
	if (0 > (slave = open(slave_name,RDWR))) {
		(void) close(master);
		return -1;
	}
	(void) close(slave);
	cc = i_read(master,&c,1,10);
	(void) close(master);
	if (!(cc == 0 || cc == -1)) {
		debuglog("%s slave open, skipping\r\n",slave_name);
		locked = FALSE;	/* leave lock file around so Expect's avoid */
				/* retrying this pty for near future */
		return -1;
	}

	/* verify no one else is using master by attempting */
	/* to read eof from slave side */
	if (0 > (master = open(master_name,RDWR))) return(-1);
	if (0 > (slave = open(slave_name,RDWR))) {
		(void) close(master);
		return -1;
	}
	(void) close(master);
	cc = i_read(slave,&c,1,10);
	(void) close(slave);
	if (!(cc == 0 || cc == -1)) {
		debuglog("%s master open, skipping\r\n",master_name);
		return -1;
	}

	/* seems ok, let's use it */
	debuglog("using master pty %s\n",master_name);
	return(open(master_name,RDWR));
#endif
}

void
exp_pty_unlock()
{
	if (locked) {
		(void) unlink(lock);
		locked = FALSE;
	}
}

/* returns 1 if successfully locked, 0 otherwise */
int
exp_pty_lock(bank,num)
int bank;
char *num;	/* string representation of number */
{
	struct stat statbuf;

	if (locked) {
		unlink(lock);
		locked = FALSE;







|











|
















|














|
















|




|
















|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
}

/* returns non-negative if successful */
int
exp_pty_test(master_name,slave_name,bank,num)
char *master_name;
char *slave_name;
char bank;
char *num;	/* string representation of number */
{
	int master, slave;
	int cc;
	char c;

	/* make a lock file to prevent others (for now only */
	/* expects) from allocating pty while we are playing */
	/* with it.  This allows us to rigorously test the */
	/* pty is usable. */
	if (exp_pty_lock(bank,num) == 0) {
		expDiagLogPtrStr("pty master (%s) is locked...skipping\r\n",master_name);
		return(-1);
	}
	/* verify no one else is using slave by attempting */
	/* to read eof from master side */
	if (0 > (master = open(master_name,RDWR))) return(-1);

#ifdef __QNX__

	/* QNX ptys don't have a lot of the same properties such as
           read 0 at EOF, etc */
	/* if 1 should pacify C compiler without using nested ifdefs */
 	if (1) return master;
#endif

#ifdef HAVE_PTYTRAP
	if (access(slave_name, R_OK|W_OK) != 0) {
		expDiagLogPtrStr("could not open slave for pty master (%s)...skipping\r\n",
			master_name);
		(void) close(master);
		return -1;
	}
	return(master);
#else
	if (0 > (slave = open(slave_name,RDWR))) {
		(void) close(master);
		return -1;
	}
	(void) close(slave);
	cc = i_read(master,&c,1,10);
	(void) close(master);
	if (!(cc == 0 || cc == -1)) {
		expDiagLogPtrStr("%s slave open, skipping\r\n",slave_name);
		locked = FALSE;	/* leave lock file around so Expect's avoid */
				/* retrying this pty for near future */
		return -1;
	}

	/* verify no one else is using master by attempting */
	/* to read eof from slave side */
	if (0 > (master = open(master_name,RDWR))) return(-1);
	if (0 > (slave = open(slave_name,RDWR))) {
		(void) close(master);
		return -1;
	}
	(void) close(master);
	cc = i_read(slave,&c,1,10);
	(void) close(slave);
	if (!(cc == 0 || cc == -1)) {
		expDiagLogPtrStr("%s master open, skipping\r\n",master_name);
		return -1;
	}

	/* seems ok, let's use it */
	expDiagLogPtrStr("using master pty %s\n",master_name);
	return(open(master_name,RDWR));
#endif
}

void
exp_pty_unlock()
{
	if (locked) {
		(void) unlink(lock);
		locked = FALSE;
	}
}

/* returns 1 if successfully locked, 0 otherwise */
int
exp_pty_lock(bank,num)
char bank;
char *num;	/* string representation of number */
{
	struct stat statbuf;

	if (locked) {
		unlink(lock);
		locked = FALSE;
269
270
271
272
273
274
275








































































	if (-1 == (link(locksrc,lock))) locked = FALSE;
	else locked = TRUE;

	return locked;
}















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368

	if (-1 == (link(locksrc,lock))) locked = FALSE;
	else locked = TRUE;

	return locked;
}

/* 
 * expDiagLog needs a different definition, depending on whether its
 * called inside of Expect or the clib.  Allow it to be set using this
 * function.  It's done here because this file (and pty_XXX.c) are the 
 * ones that call expDiagLog from the two different environments.
 */

static void		(*expDiagLogPtrVal) _ANSI_ARGS_((char *));

void
expDiagLogPtrSet(fn)
     void (*fn) _ANSI_ARGS_((char *));
{
  expDiagLogPtrVal = fn;
}

void
expDiagLogPtr(str)
     char *str;
{
  (*expDiagLogPtrVal)(str);
}



void
expDiagLogPtrX(fmt,num)
     char *fmt;
     int num;
{
  static char buf[1000];
  sprintf(buf,fmt,num);
  (*expDiagLogPtrVal)(buf);
}


void
expDiagLogPtrStr(fmt,str1)
     char *fmt;
     char *str1;
{
  static char buf[1000];
  sprintf(buf,fmt,str1);
  (*expDiagLogPtrVal)(buf);
}

void
expDiagLogPtrStrStr(fmt,str1,str2)
     char *fmt;
     char *str1, *str2;
{
  static char buf[1000];
  sprintf(buf,fmt,str1,str2);
  (*expDiagLogPtrVal)(buf);
}

static char *		(*expErrnoMsgVal) _ANSI_ARGS_((int));

char *
expErrnoMsg(errorNo)
int errorNo;
{
  return (*expErrnoMsgVal)(errorNo);
}

void
expErrnoMsgSet(fn)
     char * (*fn) _ANSI_ARGS_((int));
{
  expErrnoMsgVal = fn;
}

Changes to exp_regexp.c.



1
2
3
4
5
6
7


/*
 * regcomp and regexec -- regsub and regerror are elsewhere
 *
 *	Copyright (c) 1986 by University of Toronto.
 *	Written by Henry Spencer.  Not derived from licensed software.
 *
 *	Permission is granted to anyone to use this software for any
>
>







1
2
3
4
5
6
7
8
9
#if 0 /*WHOLE FILE*/

/*
 * regcomp and regexec -- regsub and regerror are elsewhere
 *
 *	Copyright (c) 1986 by University of Toronto.
 *	Written by Henry Spencer.  Not derived from licensed software.
 *
 *	Permission is granted to anyone to use this software for any
949
950
951
952
953
954
955


956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983
984
985




986


987
988
989
990
991
992
993
		case PLUS: {
				register char nextch;
				register int no;
				register char *save;
				register int min;
				int match_status;



				/*
				 * Lookahead to avoid useless match attempts
				 * when we know what character comes next.
				 */
				match_status = EXP_CANTMATCH;
				nextch = '\0';
				if (OP(next) == EXACTLY)
					nextch = *OPERAND(next);
				min = (OP(scan) == STAR) ? 0 : 1;
				save = reginput;
				no = regrepeat(OPERAND(scan));
				while (no >= min) {
					/* If it could work, try it. */
					/* 3rd condition allows for CAN_MATCH */
					if (nextch == '\0' || *reginput == nextch || *reginput == '\0') {
						int r = regmatch(next);
						if (r == EXP_MATCH)
							return(EXP_MATCH);
						if (r == EXP_CANMATCH)
							match_status = r;

					}
					/* Couldn't or didn't -- back up. */
					no--;
					reginput = save + no;
				}
				return(match_status);
			}
			/* NOTREACHED */
			break;
		case END:




			return(EXP_MATCH);	/* Success! */


			/* NOTREACHED */
			break;
		default:
			if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) {
				goto doOpen;
			} else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) {
				goto doClose;







>
>



















|
>










>
>
>
>
|
>
>







951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
		case PLUS: {
				register char nextch;
				register int no;
				register char *save;
				register int min;
				int match_status;

				if (*reginput == '\0') return EXP_CANMATCH;

				/*
				 * Lookahead to avoid useless match attempts
				 * when we know what character comes next.
				 */
				match_status = EXP_CANTMATCH;
				nextch = '\0';
				if (OP(next) == EXACTLY)
					nextch = *OPERAND(next);
				min = (OP(scan) == STAR) ? 0 : 1;
				save = reginput;
				no = regrepeat(OPERAND(scan));
				while (no >= min) {
					/* If it could work, try it. */
					/* 3rd condition allows for CAN_MATCH */
					if (nextch == '\0' || *reginput == nextch || *reginput == '\0') {
						int r = regmatch(next);
						if (r == EXP_MATCH)
							return(EXP_MATCH);
						if (r == EXP_CANMATCH)
/*							match_status = r;*/
							return(EXP_CANMATCH);
					}
					/* Couldn't or didn't -- back up. */
					no--;
					reginput = save + no;
				}
				return(match_status);
			}
			/* NOTREACHED */
			break;
		case END:
			/* Success! */
			if (*reginput == '\0') {
				return(EXP_CANMATCH);
			} else {
				return(EXP_MATCH);
			}
			/* return(EXP_CANMATCH);  Success! */
			/* NOTREACHED */
			break;
		default:
			if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) {
				goto doOpen;
			} else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) {
				goto doClose;
1247
1248
1249
1250
1251
1252
1253

			if (*scan1 == *scan2++)
				return(count);
		count++;
	}
	return(count);
}
#endif








>
1258
1259
1260
1261
1262
1263
1264
1265
			if (*scan1 == *scan2++)
				return(count);
		count++;
	}
	return(count);
}
#endif
#endif /* 0 WHOLE FILE */

Changes to exp_regexp.h.


1
2
3
4
5
6
7
8


/* access to regexp internals */
#define regbol		exp_regbol
#define regtry		exp_regtry
#define regexec		exp_regexec
#define regerror	TclRegError
extern char *regbol;
int regtry();


>








>
1
2
3
4
5
6
7
8
9
10
#if 0 /* WHOLE FILE */
/* access to regexp internals */
#define regbol		exp_regbol
#define regtry		exp_regtry
#define regexec		exp_regexec
#define regerror	TclRegError
extern char *regbol;
int regtry();

#endif /*0 WHOLE FILE */

Changes to exp_rename.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* translate.h - preface globals that appear in the expect library
with "exp_" so we don't conflict with the user.  This saves me having
to use exp_XXX throughout the expect program itself, which was written
well before the library when I didn't have to worry about name conflicts.

Written by: Don Libes, NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#define errorlog	exp_errorlog
#define debuglog	exp_debuglog
#define is_debugging	exp_is_debugging
#define logfile		exp_logfile
#define debugfile	exp_debugfile
#define loguser		exp_loguser
#define logfile_all	exp_logfile_all

#define getptymaster	exp_getptymaster
#define getptyslave	exp_getptyslave
|
|
|
|





|
<

<
<
<
<
<
<
<
<
<
<
1
2
3
4
5
6
7
8
9
10

11










/* exp_rename.h - preface globals that appear in the expect library with "exp_"
so we don't conflict with the user.  This saves me having to use exp_XXX
throughout the expect program itself, which was written well before the library
when I didn't have to worry about name conflicts.

Written by: Don Libes, NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.  */












Changes to exp_select.c.

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		} else if (FD_ISSET(masters[rr], &excep)) {
#ifndef HAVE_PTYTRAP
			*master_out = masters[rr];
			return(EXP_EOF);
#else
			struct request_info ioctl_info;
			if (ioctl(masters[rr],TIOCREQCHECK,&ioctl_info) < 0) {
				exp_debuglog("ioctl error on TIOCREQCHECK: %s",Tcl_ErrnoMsg(errno));
				break;
			}
			if (ioctl_info.request == TIOCCLOSE) {
				/* eof */
				*master_out = masters[rr];
				return(EXP_EOF);
			}
			if (ioctl(masters[rr], TIOCREQSET, &ioctl_info) < 0)
				exp_debuglog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
			/* presumably, we trapped an open here */
			goto restart;
#endif /* HAVE_PTYTRAP */
		}
	}
	return(EXP_TIMEOUT);
}







|








|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
		} else if (FD_ISSET(masters[rr], &excep)) {
#ifndef HAVE_PTYTRAP
			*master_out = masters[rr];
			return(EXP_EOF);
#else
			struct request_info ioctl_info;
			if (ioctl(masters[rr],TIOCREQCHECK,&ioctl_info) < 0) {
				exp_DiagLog("ioctl error on TIOCREQCHECK: %s",Tcl_ErrnoMsg(errno));
				break;
			}
			if (ioctl_info.request == TIOCCLOSE) {
				/* eof */
				*master_out = masters[rr];
				return(EXP_EOF);
			}
			if (ioctl(masters[rr], TIOCREQSET, &ioctl_info) < 0)
				expDiagLog("ioctl error on TIOCREQSET after ioctl or open on slave: %s", Tcl_ErrnoMsg(errno));
			/* presumably, we trapped an open here */
			goto restart;
#endif /* HAVE_PTYTRAP */
		}
	}
	return(EXP_TIMEOUT);
}

Changes to exp_simple.c.

311
312
313
314
315
316
317
318
319







320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for struct exp_f defs */
#include "exp_event.h"








/*ARGSUSED*/
void
exp_arm_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_disarm_background_filehandler_force(m)
int m;
{
}

/*ARGSUSED*/
void
exp_unblock_background_filehandler(m)
int m;
{
}

/*ARGSUSED*/
void
exp_block_background_filehandler(m)
int m;

{
}

/*ARGSUSED*/
void
exp_event_disarm(fd)
int fd;
{
}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event(interp,masters, n,master_out,timeout,key)
Tcl_Interp *interp;
int *masters;
int n;			/* # of masters */
int *master_out;	/* 1st event master, not set if none */
int timeout;		/* seconds */
int key;
{
	int m;
	struct exp_f *f;

	if (n > 1) {
		exp_error(interp,"expect not compiled with multiprocess support");
		/* select a different INTERACT_TYPE in Makefile */
		return(TCL_ERROR);
	}

	m = *master_out = masters[0];
	f = exp_fs + m;

	if (f->key != key) {
		f->key = key;
		f->force_read = FALSE;
		return(EXP_DATA_OLD);
	} else if ((!f->force_read) && (f->size != 0)) {
		return(EXP_DATA_OLD);
	}

	return(EXP_DATA_NEW);
}

/*ARGSUSED*/
int
exp_get_next_event_info(interp,fd,ready_mask)
Tcl_Interp *interp;
int fd;

int ready_mask;
{
}

/* There is no portable way to do sub-second sleeps on such a system, so */
/* do the next best thing (without a busy loop) and fake it: sleep the right */
/* amount of time over the long run.  Note that while "subtotal" isn't */







|

>
>
>
>
>
>
>



|
|





|
|





|
|





<
<
<
<
<
<
<
|
<
>













|

|
|
|



<
|

|
|
|
|
|

|
<

|
|
|
|
|
|
|

|




|

<
>







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350







351

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for struct ExpState defs */
#include "exp_event.h"

/*ARGSUSED*/
void
exp_arm_background_channelhandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_disarm_background_channelhandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_disarm_background_channelhandler_force(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_unblock_background_channelhandler(esPtr)
ExpState *esPtr;
{
}

/*ARGSUSED*/
void







exp_block_background_channelhandler(esPtr)

ExpState *esPtr;
{
}

/*ARGSUSED*/
void
exp_event_disarm(fd)
int fd;
{
}

/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
/*ARGSUSED*/
int
exp_get_next_event(interp,esPtrs, n,esPtrOut,timeout,key)
Tcl_Interp *interp;
ExpState (*esPtrs)[];
int n;			/* # of esPtrs */
ExpState **esPtrOut;	/* 1st event master, not set if none */
int timeout;		/* seconds */
int key;
{

    ExpState *esPtr;

    if (n > 1) {
	exp_error(interp,"expect not compiled with multiprocess support");
	/* select a different INTERACT_TYPE in Makefile */
	return(TCL_ERROR);
    }

    esPtr = *esPtrOut = esPtrs[0];


    if (esPtr->key != key) {
	esPtr->key = key;
	esPtr->force_read = FALSE;
	return(EXP_DATA_OLD);
    } else if ((!esPtr->force_read) && (esPtr->size != 0)) {
	return(EXP_DATA_OLD);
    }

    return(EXP_DATA_NEW);
}

/*ARGSUSED*/
int
exp_get_next_event_info(interp,esPtr,ready_mask)
Tcl_Interp *interp;

ExpState *esPtr;
int ready_mask;
{
}

/* There is no portable way to do sub-second sleeps on such a system, so */
/* do the next best thing (without a busy loop) and fake it: sleep the right */
/* amount of time over the long run.  Note that while "subtotal" isn't */

Changes to exp_strf.c.

94
95
96
97
98
99
100

101


102

103
104
105
106
107
108
109
#define const

extern char *getenv();
static int weeknumber();
adddecl(static int iso8601wknum();)
#else


extern char *strchr(const char *str, int ch);


extern char *getenv(const char *v);

static int weeknumber(const struct tm *timeptr, int firstweekday);
adddecl(static int iso8601wknum(const struct tm *timeptr);)
#endif

/* attempt to use strftime to compute timezone, else fallback to */
/* less portable ways */
#if !defined(HAVE_STRFTIME)







>

>
>

>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#define const

extern char *getenv();
static int weeknumber();
adddecl(static int iso8601wknum();)
#else

#ifndef strchr
extern char *strchr(const char *str, int ch);
#endif

extern char *getenv(const char *v);

static int weeknumber(const struct tm *timeptr, int firstweekday);
adddecl(static int iso8601wknum(const struct tm *timeptr);)
#endif

/* attempt to use strftime to compute timezone, else fallback to */
/* less portable ways */
#if !defined(HAVE_STRFTIME)
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
	 * ADR: This means if Jan 1 was Monday through Thursday,
	 *	it was week 1, otherwise week 53.
	 * 
	 * XPG4 erroneously included POSIX.2 rationale text in the
	 * main body of the standard. Thus it requires week 53.
	 */

	int weeknum, jan1day, diff;

	/* get week number, Monday as first day of the week */
	weeknum = weeknumber(timeptr, 1);

	/*
	 * With thanks and tip of the hatlo to [email protected]
	 *







|







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
	 * ADR: This means if Jan 1 was Monday through Thursday,
	 *	it was week 1, otherwise week 53.
	 * 
	 * XPG4 erroneously included POSIX.2 rationale text in the
	 * main body of the standard. Thus it requires week 53.
	 */

	int weeknum, jan1day;

	/* get week number, Monday as first day of the week */
	weeknum = weeknumber(timeptr, 1);

	/*
	 * With thanks and tip of the hatlo to [email protected]
	 *

Changes to exp_trap.c.

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
Tcl_Interp *interp;
int code;
{
	struct trap *trap;	/* last trap processed */
	int rc;
	int i;
	Tcl_Interp *sig_interp;
/*	extern Tcl_Interp *exp_interp;*/

	exp_debuglog("sighandler: handling signal(%d)\r\n",got_sig);

	if (got_sig <= 0 || got_sig >= NSIG) {
		errorlog("caught impossible signal %d\r\n",got_sig);
		abort();
	}

	/* start to work on this sig.  got_sig can now be overwritten */
	/* and it won't cause a problem */
	current_sig = got_sig;
	trap = &traps[current_sig];

	trap->mark = FALSE;

	/* decrement below looks dangerous */
	/* Don't we need to temporarily block bottomhalf? */
	if (current_sig == SIGCHLD) {
		sigchld_count--;
		exp_debuglog("sigchld_count-- == %d\n",sigchld_count);
	}

	if (!trap->action) {
		/* In this one case, we let ourselves be called when no */
		/* signaler predefined, since we are calling explicitly */
		/* from another part of the program, and it is just simpler */
		if (current_sig == 0) return code;
		errorlog("caught unexpected signal: %s (%d)\r\n",
			signal_to_string(current_sig),current_sig);
		abort();
	}

	if (trap->interp) {
		/* if trap requested original interp, use it */
		sig_interp = trap->interp;







<

|


|














|







|







83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Tcl_Interp *interp;
int code;
{
	struct trap *trap;	/* last trap processed */
	int rc;
	int i;
	Tcl_Interp *sig_interp;


	expDiagLog("sighandler: handling signal(%d)\r\n",got_sig);

	if (got_sig <= 0 || got_sig >= NSIG) {
		expErrorLog("caught impossible signal %d\r\n",got_sig);
		abort();
	}

	/* start to work on this sig.  got_sig can now be overwritten */
	/* and it won't cause a problem */
	current_sig = got_sig;
	trap = &traps[current_sig];

	trap->mark = FALSE;

	/* decrement below looks dangerous */
	/* Don't we need to temporarily block bottomhalf? */
	if (current_sig == SIGCHLD) {
		sigchld_count--;
		expDiagLog("sigchld_count-- == %d\n",sigchld_count);
	}

	if (!trap->action) {
		/* In this one case, we let ourselves be called when no */
		/* signaler predefined, since we are calling explicitly */
		/* from another part of the program, and it is just simpler */
		if (current_sig == 0) return code;
		expErrorLog("caught unexpected signal: %s (%d)\r\n",
			signal_to_string(current_sig),current_sig);
		abort();
	}

	if (trap->interp) {
		/* if trap requested original interp, use it */
		sig_interp = trap->interp;
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
	}
	return rc;
}

#ifdef REARM_SIG
int sigchld_sleep;
static int rearm_sigchld = FALSE;	/* TRUE if sigchld needs to be */
					/* rearmed (i.e., because it has
					/* just gone off) */
static int rearming_sigchld = FALSE;
#endif

/* called upon receipt of a user-declared signal */
static void
bottomhalf(sig)







|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
	}
	return rc;
}

#ifdef REARM_SIG
int sigchld_sleep;
static int rearm_sigchld = FALSE;	/* TRUE if sigchld needs to be */
					/* rearmed (i.e., because it has */
					/* just gone off) */
static int rearming_sigchld = FALSE;
#endif

/* called upon receipt of a user-declared signal */
static void
bottomhalf(sig)
194
195
196
197
198
199
200
201
202
203
204



205

206
207
208
209
210
211
212
213
	/* is recalled, it will see that nothing was left to do */

	/* In case of SIGCHLD though, we must recall it as many times as
	 * we have received it.
	 */
	if (sig == SIGCHLD) {
		sigchld_count++;
/*		exp_debuglog(stderr,"sigchld_count++ == %d\n",sigchld_count);*/
	}
#if 0
	/* if we are doing an i_read, restart it */



	if (env_valid && (sig != 0)) longjmp(env,2);

#endif
}

/*ARGSUSED*/
void
exp_rearm_sigchld(interp)
Tcl_Interp *interp;
{







<



>
>
>
|
>
|







193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
	/* is recalled, it will see that nothing was left to do */

	/* In case of SIGCHLD though, we must recall it as many times as
	 * we have received it.
	 */
	if (sig == SIGCHLD) {
		sigchld_count++;

	}
#if 0
	/* if we are doing an i_read, restart it */
#ifdef HAVE_SIGLONGJMP
      if (env_valid && (sig != 0)) siglongjmp(env,2);
#else
      if (env_valid && (sig != 0)) longjmp(env,2);
#endif  /* HAVE_SIGLONGJMP */
#endif /* 0 */
}

/*ARGSUSED*/
void
exp_rearm_sigchld(interp)
Tcl_Interp *interp;
{
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313
314
315
316


317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355




356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

375
376
377





378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421


422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445


446
447
448
449
450
451
452
453
454
455
456
457
458
459


460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489
490
491

492
493
494

495
496
497
498
499
500
501
502
503
504
505
506
507


508
509



510
511

512
513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
	exp_error(interp,"invalid signal %s",s);
	
	return -1;
}

/*ARGSUSED*/
int
Exp_TrapCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	char *action = 0;
	int n;		/* number of signals in list */
	char **list;	/* list of signals */

	int len;	/* length of action */
	int i;
	int show_name = FALSE;	/* if user asked for current sig by name */
	int show_number = FALSE;/* if user asked for current sig by number */
	int show_max = FALSE;	/* if user asked for NSIG-1 */
	int rc = TCL_OK;
	int new_code = FALSE;	/* if action result should overwrite orig */
	Tcl_Interp *new_interp = interp;/* interp in which to evaluate */
					/* action when signal occurs */

	argc--; argv++;

	while (*argv) {


		if (streq(*argv,"-code")) {
			argc--; argv++; 
			new_code = TRUE;
		} else if (streq(*argv,"-interp")) {
			argc--; argv++; 
			new_interp = 0;
		} else if (streq(*argv,"-name")) {
			argc--; argv++;
			show_name = TRUE;
		} else if (streq(*argv,"-number")) {
			argc--; argv++;
			show_number = TRUE;
		} else if (streq(*argv,"-max")) {
			argc--; argv++;
			show_max = TRUE;
		} else break;
	}

	if (show_name || show_number || show_max) {
		if (argc > 0) goto usage_error;
		if (show_max) {
			sprintf(interp->result,"%d",NSIG-1);
			return TCL_OK;
		}

		if (current_sig == NO_SIG) {
			exp_error(interp,"no signal in progress");
			return TCL_ERROR;
		}
		if (show_name) {
			/* skip over "SIG" */
			interp->result = signal_to_string(current_sig) + 3;
		} else {
			sprintf(interp->result,"%d",current_sig);
		}
		return TCL_OK;
	}

	if (argc == 0 || argc > 2) goto usage_error;





	if (argc == 1) {
		int sig = exp_string_to_signal(interp,*argv);
		if (sig == -1) return TCL_ERROR;

		if (traps[sig].action) {
			Tcl_AppendResult(interp,traps[sig].action,(char *)0);
		} else {
			interp->result = "SIG_DFL";
		}
		return TCL_OK;
	}

	action = *argv;

	/* argv[1] is the list of signals - crack it open */
	if (TCL_OK != Tcl_SplitList(interp,argv[1],&n,&list)) {
		errorlog("%s\r\n",interp->result);
		goto usage_error;

	}

	for (i=0;i<n;i++) {





		int sig = exp_string_to_signal(interp,list[i]);
		if (sig == -1) {
			rc = TCL_ERROR;
			break;
		}

		if (traps[sig].reserved) {
			exp_error(interp,"cannot trap %s",signal_to_string(sig));
			rc = TCL_ERROR;
			break;
		}

#if 0
#ifdef TCL_DEBUGGER
		if (sig == SIGINT && exp_tcl_debugger_available) {
			exp_debuglog("trap: cannot trap SIGINT while using debugger\r\n");
			continue;
		}
#endif /* TCL_DEBUGGER */
#endif

		exp_debuglog("trap: setting up signal %d (\"%s\")\r\n",sig,list[i]);

		if (traps[sig].action) ckfree(traps[sig].action);

		if (streq(action,"SIG_DFL")) {
			/* should've been free'd by now if nec. */
			traps[sig].action = 0;
			signal(sig,SIG_DFL);
#ifdef REARM_SIG
			if (sig == SIGCHLD)
				rearm_sigchld = FALSE;
#endif /*REARM_SIG*/
		} else {
			len = 1 + strlen(action);
			traps[sig].action = ckalloc(len);
			memcpy(traps[sig].action,action,len);
			traps[sig].interp = new_interp;
			traps[sig].code = new_code;
			if (streq(action,"SIG_IGN")) {
				signal(sig,SIG_IGN);
			} else signal(sig,bottomhalf);
		}
	}


	ckfree((char *)list);
	return(rc);
 usage_error:
	exp_error(interp,"usage: trap [command or SIG_DFL or SIG_IGN] {list of signals}");
	return TCL_ERROR;
}

/* called by tophalf() to process the given signal */
static int
eval_trap_action(interp,sig,trap,oldcode)
Tcl_Interp *interp;
int sig;
struct trap *trap;
int oldcode;
{
	int code_flag;
	int newcode;
	Tcl_DString ei;	/* errorInfo */
	char *eip;
	Tcl_DString ec;	/* errorCode */
	char *ecp;
	Tcl_DString ir;	/* interp->result */

	exp_debuglog("async event handler: Tcl_Eval(%s)\r\n",trap->action);



	/* save to prevent user from redefining trap->code while trap */
	/* is executing */
	code_flag = trap->code;

	if (!code_flag) {
		/* 
		 * save return values
		 */
		eip = Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY);
		if (eip) {
			Tcl_DStringInit(&ei);
			eip = Tcl_DStringAppend(&ei,eip,-1);
		}


		ecp = Tcl_GetVar(interp,"errorCode",TCL_GLOBAL_ONLY);
		if (ecp) {
			Tcl_DStringInit(&ec);
			ecp = Tcl_DStringAppend(&ec,ecp,-1);
		}
		/* I assume interp->result is always non-zero, right? */
		Tcl_DStringInit(&ir);
		Tcl_DStringAppend(&ir,interp->result,-1);
	}

	newcode = Tcl_GlobalEval(interp,trap->action);

	/*
	 * if new code is to be ignored (usual case - see "else" below)
	 *	allow only OK/RETURN from trap, otherwise complain
	 */

	if (code_flag) {
		exp_debuglog("return value = %d for trap %s, action %s\r\n",
				newcode,signal_to_string(sig),trap->action);
		if (*interp->result != 0) {
			errorlog("%s\r\n",interp->result);


			/*
			 * Check errorinfo and see if it contains -nostack.
			 * This shouldn't be necessary, but John changed the
			 * top level interp so that it distorts arbitrary
			 * return values into TCL_ERROR, so by the time we
			 * get back, we'll have lost the value of errorInfo
			 */

			eip = Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY);

			exp_nostack_dump =
				(eip && (0 == strncmp("-nostack",eip,8)));
		}

	} else if (newcode != TCL_OK && newcode != TCL_RETURN) {
		if (newcode != TCL_ERROR) {
			exp_error(interp,"return value = %d for trap %s, action %s\r\n",newcode,signal_to_string(sig),trap->action);
		}
		Tcl_BackgroundError(interp);
	}

	if (!code_flag) {
		/*
		 * restore values
		 */
		Tcl_ResetResult(interp);	/* turns off Tcl's internal */
				/* flags: ERR_IN_PROGRESS, ERROR_CODE_SET */



		if (eip) {



			Tcl_AddErrorInfo(interp,eip);
			Tcl_DStringFree(&ei);

		} else {
			Tcl_UnsetVar(interp,"errorInfo",0);
		}

		/* restore errorCode.  Note that Tcl_AddErrorInfo (above) */
		/* resets it to NONE.  If the previous value is NONE, it's */
		/* important to avoid calling Tcl_SetErrorCode since this */
		/* with cause Tcl to set its internal ERROR_CODE_SET flag. */
		if (ecp) {
			if (!streq("NONE",ecp))
				Tcl_SetErrorCode(interp,ecp,(char *)0);

			Tcl_DStringFree(&ec);
		} else {
			Tcl_UnsetVar(interp,"errorCode",0);
		}

		Tcl_DStringResult(interp,&ir);
		Tcl_DStringFree(&ir);

		newcode = oldcode;

		/* note that since newcode gets overwritten here by old code */
		/* it is possible to return in the middle of a trap by using */
		/* "return" (or "continue" for that matter)! */
	}
	return newcode;
}

static struct exp_cmd_data
cmd_data[]  = {
{"trap",	exp_proc(Exp_TrapCmd),	(ClientData)EXP_SPAWN_ID_BAD,	0},
{0}};

void
exp_init_trap_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);
}








|


|
|



|
>










|

|
>
>
|
|

|
|

|
|

|
|

|
|





|

|
<



|
|


|
|

|




|
>
>
>
>

<
<
<
<

|

|




|

|
|
<
<
>



>
>
>
>
>
|











<
<
<
<
<
<
<
<
<
|
<

<



















>
>
|
















|
<
|
<
|

|
>
>









<
<
<
<
|
>
>
|
|
<
|
<
<
|
<










|
|
<
|
>









|
>
|
<
|
>

|
|
|
|







|
>
>


>
>
>
|
|
>

|







|
|
>
|

|


<
<
<











|









290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364




365
366
367
368
369
370
371
372
373
374
375
376


377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397









398

399

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

439

440
441
442
443
444
445
446
447
448
449
450
451
452
453




454
455
456
457
458

459


460

461
462
463
464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528



529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
	exp_error(interp,"invalid signal %s",s);
	
	return -1;
}

/*ARGSUSED*/
int
Exp_TrapObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
	char *action = 0;
	int n;		/* number of signals in list */
	Tcl_Obj **list;	/* list of signals */
	char *arg;
	int len;	/* length of action */
	int i;
	int show_name = FALSE;	/* if user asked for current sig by name */
	int show_number = FALSE;/* if user asked for current sig by number */
	int show_max = FALSE;	/* if user asked for NSIG-1 */
	int rc = TCL_OK;
	int new_code = FALSE;	/* if action result should overwrite orig */
	Tcl_Interp *new_interp = interp;/* interp in which to evaluate */
					/* action when signal occurs */

	objc--; objv++;

	while (objc) {
	  arg = Tcl_GetString(*objv);

		if (streq(arg,"-code")) {
			objc--; objv++; 
			new_code = TRUE;
		} else if (streq(arg,"-interp")) {
			objc--; objv++; 
			new_interp = 0;
		} else if (streq(arg,"-name")) {
			objc--; objv++;
			show_name = TRUE;
		} else if (streq(arg,"-number")) {
			objc--; objv++;
			show_number = TRUE;
		} else if (streq(arg,"-max")) {
			objc--; objv++;
			show_max = TRUE;
		} else break;
	}

	if (show_name || show_number || show_max) {
		if (objc > 0) goto usage_error;
		if (show_max) {
		  Tcl_SetObjResult(interp,Tcl_NewIntObj(NSIG-1));

		}

		if (current_sig == NO_SIG) {
		  Tcl_SetResult(interp,"no signal in progress",TCL_STATIC);
		  return TCL_ERROR;
		}
		if (show_name) {
		  /* skip over "SIG" */
		  Tcl_SetResult(interp,signal_to_string(current_sig) + 3,TCL_STATIC);
		} else {
		  Tcl_SetObjResult(interp,Tcl_NewIntObj(current_sig));
		}
		return TCL_OK;
	}

	if (objc == 0 || objc > 2) goto usage_error;

	if (objc == 1) {
		int sig = exp_string_to_signal(interp,arg);
		if (sig == -1) return TCL_ERROR;





		if (traps[sig].action) {
			Tcl_SetResult(interp,traps[sig].action,TCL_STATIC);
		} else {
			Tcl_SetResult(interp,"SIG_DFL",TCL_STATIC);
		}
		return TCL_OK;
	}

	action = arg;

	/* objv[1] is the list of signals - crack it open */
	if (TCL_OK != Tcl_ListObjGetElements(interp,objv[1],&n,&list)) {


	  return TCL_ERROR;
	}

	for (i=0;i<n;i++) {
	  char *s;
	  int sig;

	  s = Tcl_GetString(list[i]);

		sig = exp_string_to_signal(interp,s);
		if (sig == -1) {
			rc = TCL_ERROR;
			break;
		}

		if (traps[sig].reserved) {
			exp_error(interp,"cannot trap %s",signal_to_string(sig));
			rc = TCL_ERROR;
			break;
		}










		expDiagLog("trap: setting up signal %d (\"%s\")\r\n",sig,s);

		if (traps[sig].action) ckfree(traps[sig].action);

		if (streq(action,"SIG_DFL")) {
			/* should've been free'd by now if nec. */
			traps[sig].action = 0;
			signal(sig,SIG_DFL);
#ifdef REARM_SIG
			if (sig == SIGCHLD)
				rearm_sigchld = FALSE;
#endif /*REARM_SIG*/
		} else {
			len = 1 + strlen(action);
			traps[sig].action = ckalloc(len);
			memcpy(traps[sig].action,action,len);
			traps[sig].interp = new_interp;
			traps[sig].code = new_code;
			if (streq(action,"SIG_IGN")) {
				signal(sig,SIG_IGN);
			} else signal(sig,bottomhalf);
		}
	}
	/* It is no longer necessary to free the split list since it */
	/* is still owned by Tcl, yes? */
	/*	ckfree((char *)list); */
	return(rc);
 usage_error:
	exp_error(interp,"usage: trap [command or SIG_DFL or SIG_IGN] {list of signals}");
	return TCL_ERROR;
}

/* called by tophalf() to process the given signal */
static int
eval_trap_action(interp,sig,trap,oldcode)
Tcl_Interp *interp;
int sig;
struct trap *trap;
int oldcode;
{
	int code_flag;
	int newcode;
	Tcl_Obj *eip;   /* errorInfo */

	Tcl_Obj *ecp;	/* errorCode */

	Tcl_Obj *irp;	/* interp->result */

	expDiagLogU("async event handler: Tcl_Eval(");
	expDiagLogU(trap->action);
	expDiagLogU(")\r\n");

	/* save to prevent user from redefining trap->code while trap */
	/* is executing */
	code_flag = trap->code;

	if (!code_flag) {
		/* 
		 * save return values
		 */





		eip = Tcl_GetVar2Ex(interp,"errorInfo","",TCL_GLOBAL_ONLY);
		if (eip) eip = Tcl_DuplicateObj(eip);
		ecp = Tcl_GetVar2Ex(interp,"errorCode","",TCL_GLOBAL_ONLY);
		if (ecp) ecp = Tcl_DuplicateObj(ecp);

		irp = Tcl_GetObjResult(interp);


		if (irp) irp = Tcl_DuplicateObj(irp);

	}

	newcode = Tcl_GlobalEval(interp,trap->action);

	/*
	 * if new code is to be ignored (usual case - see "else" below)
	 *	allow only OK/RETURN from trap, otherwise complain
	 */

	if (code_flag) {
		expDiagLog("return value = %d for trap %s, action ",newcode,signal_to_string(sig));
		expDiagLogU(trap->action);

		expDiagLogU("\r\n");
		if (0 != strcmp(Tcl_GetStringResult(interp),"")) {

			/*
			 * Check errorinfo and see if it contains -nostack.
			 * This shouldn't be necessary, but John changed the
			 * top level interp so that it distorts arbitrary
			 * return values into TCL_ERROR, so by the time we
			 * get back, we'll have lost the value of errorInfo
			 */

			eip = Tcl_GetVar2Ex(interp,"errorInfo","",TCL_GLOBAL_ONLY);
			if (eip) {
			  exp_nostack_dump = (0 == strncmp("-nostack",Tcl_GetString(eip),8));

			}
		}
	} else if (newcode != TCL_OK && newcode != TCL_RETURN) {
	  if (newcode != TCL_ERROR) {
	    exp_error(interp,"return value = %d for trap %s, action %s\r\n",newcode,signal_to_string(sig),trap->action);
	  }
	  Tcl_BackgroundError(interp);
	}

	if (!code_flag) {
		/*
		 * restore values
		 */
		Tcl_ResetResult(interp);	/* turns off Tcl's internal */
		   /* flags: ERR_IN_PROGRESS, ERROR_CODE_SET */
		   /* This also wipes clean errorInfo/Code/result which is why */
		   /* all the calls to Tcl_Dup earlier */

		if (eip) {
		  /* odd that Tcl doesn't have a call that does all this at once */
		  int len;
		  char *s = Tcl_GetStringFromObj(eip,&len);
		  Tcl_AddObjErrorInfo(interp,s,len);
		  Tcl_DecrRefCount(eip);
		  /* we never incr'd it, but the code allows this */
		} else {
		  Tcl_UnsetVar(interp,"errorInfo",0);
		}

		/* restore errorCode.  Note that Tcl_AddErrorInfo (above) */
		/* resets it to NONE.  If the previous value is NONE, it's */
		/* important to avoid calling Tcl_SetErrorCode since this */
		/* with cause Tcl to set its internal ERROR_CODE_SET flag. */
		if (ecp) {
		  if (!streq("NONE",Tcl_GetString(ecp)))
		    Tcl_SetErrorCode(interp,ecp);
		  /* we're just passing on the errorcode obj */
		  /* presumably, Tcl will incr ref count */
		} else {
		  Tcl_UnsetVar(interp,"errorCode",0);
		}




		newcode = oldcode;

		/* note that since newcode gets overwritten here by old code */
		/* it is possible to return in the middle of a trap by using */
		/* "return" (or "continue" for that matter)! */
	}
	return newcode;
}

static struct exp_cmd_data
cmd_data[]  = {
{"trap",	Exp_TrapObjCmd, 0,	(ClientData)EXP_SPAWN_ID_BAD,	0},
{0}};

void
exp_init_trap_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);
}

Changes to exp_tty.c.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define SIGCHLD SIGCLD
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_rename.h"
#include "exp_tty_in.h"
#include "exp_log.h"
#include "exp_command.h"

static int is_raw = FALSE;
static int is_noecho = FALSE;

int exp_ioctled_devtty = FALSE;
int exp_stdin_is_tty;
int exp_stdout_is_tty;







|
|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#define SIGCHLD SIGCLD
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_rename.h"
#include "exp_tty_in.h"
#include "exp_command.h"
#include "exp_log.h"

static int is_raw = FALSE;
static int is_noecho = FALSE;

int exp_ioctled_devtty = FALSE;
int exp_stdin_is_tty;
int exp_stdout_is_tty;
145
146
147
148
149
150
151
152
153
154
155
156
157
158





159

160
161
162
163
164
165
166
	if (exp_disconnected) return(0);
	if (is_raw && is_noecho) return(0);
	if (exp_dev_tty == -1) return(0);

	*tty_old = tty_current;		/* save old parameters */
	*was_raw = is_raw;
	*was_echo = !is_noecho;
	debuglog("tty_raw_noecho: was raw = %d  echo = %d\r\n",is_raw,!is_noecho);

	exp_tty_raw(1);
	exp_tty_echo(-1);

	if (exp_tty_set_simple(&tty_current) == -1) {
		errorlog("ioctl(raw): %s\r\n",Tcl_PosixError(interp));





		exp_exit(interp,1);

	}

	exp_ioctled_devtty = TRUE;
	return(1);
}

/* returns 0 if nothing changed */







|





|
>
>
>
>
>
|
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
	if (exp_disconnected) return(0);
	if (is_raw && is_noecho) return(0);
	if (exp_dev_tty == -1) return(0);

	*tty_old = tty_current;		/* save old parameters */
	*was_raw = is_raw;
	*was_echo = !is_noecho;
	expDiagLog("tty_raw_noecho: was raw = %d  echo = %d\r\n",is_raw,!is_noecho);

	exp_tty_raw(1);
	exp_tty_echo(-1);

	if (exp_tty_set_simple(&tty_current) == -1) {
		expErrorLog("ioctl(raw): %s\r\n",Tcl_PosixError(interp));

		/* SF #439042 -- Allow overide of "exit" by user / script
		 */
		{
		  char buffer [] = "exit 1";
		  Tcl_Eval(interp, buffer); 
		}
	}

	exp_ioctled_devtty = TRUE;
	return(1);
}

/* returns 0 if nothing changed */
174
175
176
177
178
179
180
181
182
183
184
185
186
187





188

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203





204

205
206
207
208
209
210
211
212
213
214
215
216
	if (exp_disconnected) return(0);
	if (!is_raw && !is_noecho) return(0);
	if (exp_dev_tty == -1) return(0);

	*tty_old = tty_current;		/* save old parameters */
	*was_raw = is_raw;
	*was_echo = !is_noecho;
	debuglog("tty_cooked_echo: was raw = %d  echo = %d\r\n",is_raw,!is_noecho);

	exp_tty_raw(-1);
	exp_tty_echo(1);

	if (exp_tty_set_simple(&tty_current) == -1) {
		errorlog("ioctl(noraw): %s\r\n",Tcl_PosixError(interp));





		exp_exit(interp,1);

	}
	exp_ioctled_devtty = TRUE;

	return(1);
}

void
exp_tty_set(interp,tty,raw,echo)
Tcl_Interp *interp;
exp_tty *tty;
int raw;
int echo;
{
	if (exp_tty_set_simple(tty) == -1) {
		errorlog("ioctl(set): %s\r\n",Tcl_PosixError(interp));





		exp_exit(interp,1);

	}
	is_raw = raw;
	is_noecho = !echo;
	tty_current = *tty;
	debuglog("tty_set: raw = %d, echo = %d\r\n",is_raw,!is_noecho);
	exp_ioctled_devtty = TRUE;
}	

#if 0
/* avoids scoping problems */
void
exp_update_cooked_from_current() {







|





|
>
>
>
>
>
|
>














|
>
>
>
>
>
|
>




|







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	if (exp_disconnected) return(0);
	if (!is_raw && !is_noecho) return(0);
	if (exp_dev_tty == -1) return(0);

	*tty_old = tty_current;		/* save old parameters */
	*was_raw = is_raw;
	*was_echo = !is_noecho;
	expDiagLog("tty_cooked_echo: was raw = %d  echo = %d\r\n",is_raw,!is_noecho);

	exp_tty_raw(-1);
	exp_tty_echo(1);

	if (exp_tty_set_simple(&tty_current) == -1) {
		expErrorLog("ioctl(noraw): %s\r\n",Tcl_PosixError(interp));

		/* SF #439042 -- Allow overide of "exit" by user / script
		 */
		{
		  char buffer [] = "exit 1";
		  Tcl_Eval(interp, buffer); 
		}
	}
	exp_ioctled_devtty = TRUE;

	return(1);
}

void
exp_tty_set(interp,tty,raw,echo)
Tcl_Interp *interp;
exp_tty *tty;
int raw;
int echo;
{
	if (exp_tty_set_simple(tty) == -1) {
		expErrorLog("ioctl(set): %s\r\n",Tcl_PosixError(interp));

		/* SF #439042 -- Allow overide of "exit" by user / script
		 */
		{
		  char buffer [] = "exit 1";
		  Tcl_Eval(interp, buffer); 
		}
	}
	is_raw = raw;
	is_noecho = !echo;
	tty_current = *tty;
	expDiagLog("tty_set: raw = %d, echo = %d\r\n",is_raw,!is_noecho);
	exp_ioctled_devtty = TRUE;
}	

#if 0
/* avoids scoping problems */
void
exp_update_cooked_from_current() {
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

332
333
334


335
336
337
338

339
340
341
342
343
344
345
char **argv;
int devtty;		/* if true, redirect to /dev/tty */
{
	char **new_argv;
	int i;
	int rc;

	/* insert "system" at front, null at end, */
	/* and optional redirect in middle, hence "+3" */
	new_argv = (char **)ckalloc((3+argc)*sizeof(char *));
	new_argv[0] = exec_cmd;
	new_argv[1] = stty_cmd;
	for (i=1;i<argc;i++) {
		new_argv[i+1] = argv[i];
	}
	if (devtty) new_argv[++i] =
#ifdef STTY_READS_STDOUT
		">/dev/tty";
#else
		"</dev/tty";
#endif

	new_argv[i+1] = (char *)0;

	Tcl_ResetResult(interp);


	/* normally, I wouldn't set one of Tcl's own variables, but in this */
	/* case, I only only want to see if Tcl resets it to non-NONE, */
	/* and I don't know any other way of doing it */


	Tcl_SetVar(interp,"errorCode","NONE",0);
	rc = Tcl_ExecCmd((ClientData)0,interp,argc+1+devtty,new_argv);

	ckfree((char *)new_argv);


	/* if stty-reads-stdout, stty will fail since Exec */
	/* will detect the stderr.  Only by examining errorCode */
	/* can we tell if a real error occurred. */	

#ifdef STTY_READS_STDOUT
	if (rc == TCL_ERROR) {







|
|
|
|
<

|

|

|

|

<
|



>
|
|
|
>
>

|

<
>







324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364
char **argv;
int devtty;		/* if true, redirect to /dev/tty */
{
	char **new_argv;
	int i;
	int rc;

	Tcl_Obj *cmdObj = Tcl_NewStringObj("",0);
	Tcl_IncrRefCount(cmdObj);

	Tcl_AppendStringsToObj(cmdObj,"exec /bin/stty",(char *)0);

	for (i=1;i<argc;i++) {
	    Tcl_AppendStringsToObj(cmdObj," ",argv[i],(char *)0);
	}
	if (devtty) Tcl_AppendStringsToObj(cmdObj,
#ifdef STTY_READS_STDOUT
		" >/dev/tty",
#else
		" </dev/tty",
#endif

		(char *)0);

	Tcl_ResetResult(interp);

	/*
	 * normally, I wouldn't set one of Tcl's own variables, but in this
	 * case, I only want to see if Tcl resets it to non-NONE, and I don't
	 * know any other way of doing it
	 */

	Tcl_SetVar(interp,"errorCode","NONE",0);
	rc = Tcl_EvalObjEx(interp,cmdObj,TCL_EVAL_DIRECT);


	Tcl_DecrRefCount(cmdObj);

	/* if stty-reads-stdout, stty will fail since Exec */
	/* will detect the stderr.  Only by examining errorCode */
	/* can we tell if a real error occurred. */	

#ifdef STTY_READS_STDOUT
	if (rc == TCL_ERROR) {
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
	char **argv0 = argv;

	for (argv=argv0+1;*argv;argv++) {
		if (argv[0][0] == '<') {
			redirect = argv;
			infile = *(argv+1);
			if (!infile) {
				errorlog("usage: < ttyname");
				return TCL_ERROR;
			}
			if (streq(infile,"/dev/tty")) {
				infile = 0;
				*argv = 0;
				*(argv+1) = 0;
				argc -= 2;
			} else {
				master = exp_trap_off(infile);
				if (-1 == (fd = open(infile,2))) {
					errorlog("couldn't open %s: %s",
					 infile,Tcl_PosixError(interp));
					return TCL_ERROR;
				}
			}
			break;
		}
	}







|










|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
	char **argv0 = argv;

	for (argv=argv0+1;*argv;argv++) {
		if (argv[0][0] == '<') {
			redirect = argv;
			infile = *(argv+1);
			if (!infile) {
				expErrorLog("usage: < ttyname");
				return TCL_ERROR;
			}
			if (streq(infile,"/dev/tty")) {
				infile = 0;
				*argv = 0;
				*(argv+1) = 0;
				argc -= 2;
			} else {
				master = exp_trap_off(infile);
				if (-1 == (fd = open(infile,2))) {
					expErrorLog("couldn't open %s: %s",
					 infile,Tcl_PosixError(interp));
					return TCL_ERROR;
				}
			}
			break;
		}
	}
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
			if (cooked) {
				/* find out user's new defn of 'cooked' */
				tty_cooked = tty_current;
			}
		} else if (saw_known_stty_arg) {
			if (exp_tty_set_simple(&tty_current) == -1) {
			    if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
				errorlog("stty: impossible in this context\n");
				errorlog("are you disconnected or in a batch, at, or cron script?");
				/* user could've conceivably closed /dev/tty as well */
			    }
			    exp_error(interp,"stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
			    rc = TCL_ERROR;
			}
		}








|
|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
			if (cooked) {
				/* find out user's new defn of 'cooked' */
				tty_cooked = tty_current;
			}
		} else if (saw_known_stty_arg) {
			if (exp_tty_set_simple(&tty_current) == -1) {
			    if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
				expErrorLog("stty: impossible in this context\n");
				expErrorLog("are you disconnected or in a batch, at, or cron script?");
				/* user could've conceivably closed /dev/tty as well */
			    }
			    exp_error(interp,"stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
			    rc = TCL_ERROR;
			}
		}

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
	int cmd_is_stty = FALSE;
	int cooked = FALSE;
	int was_raw, was_echo;

	if (argc == 1) return TCL_OK;

	if (streq(argv[1],"stty")) {
		debuglog("system stty is deprecated, use stty\r\n");

		cmd_is_stty = TRUE;
		was_raw = exp_israw();
		was_echo = exp_isecho();
	}

	if (argc > 2 && cmd_is_stty) {







|







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
	int cmd_is_stty = FALSE;
	int cooked = FALSE;
	int was_raw, was_echo;

	if (argc == 1) return TCL_OK;

	if (streq(argv[1],"stty")) {
		expDiagLogU("system stty is deprecated, use stty\r\n");

		cmd_is_stty = TRUE;
		was_raw = exp_israw();
		was_echo = exp_isecho();
	}

	if (argc > 2 && cmd_is_stty) {
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
		if (stty_args_recognized) {
#ifdef HAVE_TCSETATTR
 			if (tcsetattr(exp_dev_tty,TCSADRAIN, &tty_current) == -1) {
#else
		        if (ioctl(exp_dev_tty, TCSETSW, &tty_current) == -1) {
#endif
			    if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
				errorlog("system stty: impossible in this context\n");
				errorlog("are you disconnected or in a batch, at, or cron script?");
				/* user could've conceivably closed /dev/tty as well */
			    }
			    exp_error(interp,"system stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
			    return(TCL_ERROR);
			}
			if (cmd_is_stty) {
				sprintf(interp->result,"%sraw %secho",







|
|







617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
		if (stty_args_recognized) {
#ifdef HAVE_TCSETATTR
 			if (tcsetattr(exp_dev_tty,TCSADRAIN, &tty_current) == -1) {
#else
		        if (ioctl(exp_dev_tty, TCSETSW, &tty_current) == -1) {
#endif
			    if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
				expErrorLog("system stty: impossible in this context\n");
				expErrorLog("are you disconnected or in a batch, at, or cron script?");
				/* user could've conceivably closed /dev/tty as well */
			    }
			    exp_error(interp,"system stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
			    return(TCL_ERROR);
			}
			if (cmd_is_stty) {
				sprintf(interp->result,"%sraw %secho",
629
630
631
632
633
634
635

636
637
638


639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654





655

656
657
658
659
660
661
662
		bufp += arg_len;
		/* no need to check bounds, we accted for it earlier */
		memcpy(bufp," ",1);
		bufp += 1;
	}

	*(bufp-1) = '\0';

	old = signal(SIGCHLD, SIG_DFL);
	systemStatus = system(buf);
	signal(SIGCHLD, old);	/* restore signal handler */


	debuglog("system(%s) = %d\r\n",buf,i);

	if (systemStatus == -1) {
		exp_error(interp,Tcl_PosixError(interp));
		return TCL_ERROR;
	}
	*(int *)&waitStatus = systemStatus;

	if (!stty_args_recognized) {
		/* find out what weird options user asked for */
#ifdef HAVE_TCSETATTR
		if (tcgetattr(exp_dev_tty, &tty_current) == -1) {
#else
	        if (ioctl(exp_dev_tty, TCGETS, &tty_current) == -1) {
#endif
			errorlog("ioctl(get): %s\r\n",Tcl_PosixError(interp));





			exp_exit(interp,1);

		}
		if (cooked) {
			/* find out user's new defn of 'cooked' */
			tty_cooked = tty_current;
		}
	}








>



>
>
|














|
>
>
>
>
>
|
>







648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
		bufp += arg_len;
		/* no need to check bounds, we accted for it earlier */
		memcpy(bufp," ",1);
		bufp += 1;
	}

	*(bufp-1) = '\0';

	old = signal(SIGCHLD, SIG_DFL);
	systemStatus = system(buf);
	signal(SIGCHLD, old);	/* restore signal handler */
	expDiagLogU("system(");
	expDiagLogU(buf);
	expDiagLog(") = %d\r\n",i);

	if (systemStatus == -1) {
		exp_error(interp,Tcl_PosixError(interp));
		return TCL_ERROR;
	}
	*(int *)&waitStatus = systemStatus;

	if (!stty_args_recognized) {
		/* find out what weird options user asked for */
#ifdef HAVE_TCSETATTR
		if (tcgetattr(exp_dev_tty, &tty_current) == -1) {
#else
	        if (ioctl(exp_dev_tty, TCGETS, &tty_current) == -1) {
#endif
			expErrorLog("ioctl(get): %s\r\n",Tcl_PosixError(interp));

			/* SF #439042 -- Allow overide of "exit" by user / script
			 */
			{
			  char buffer [] = "exit 1";
			  Tcl_Eval(interp, buffer); 
			}
		}
		if (cooked) {
			/* find out user's new defn of 'cooked' */
			tty_cooked = tty_current;
		}
	}

Changes to exp_tty_comm.c.

1
2
3
4
5
6

7
8
9
10

11
12
13
14
15
16
17
/* exp_tty_comm.c - tty support routines common to both Expect program
   and library */

#include "expect_cf.h"
#include <stdio.h>


#include "exp_tty_in.h"
#include "exp_rename.h"
#define EXP_AVOID_INCLUDING_TCL_H
#include "expect_comm.h"

#include "exp_log.h"

#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif







>


<

>







1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
/* exp_tty_comm.c - tty support routines common to both Expect program
   and library */

#include "expect_cf.h"
#include <stdio.h>

#include "tcl.h"
#include "exp_tty_in.h"
#include "exp_rename.h"

#include "expect_comm.h"
#include "exp_command.h"
#include "exp_log.h"

#ifndef TRUE
#define FALSE 0
#define TRUE 1
#endif

Changes to expect.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>	/* for isspace */
#include <time.h>	/* for time(3) */
#if 0
#include <setjmp.h>
#endif

#include "expect_cf.h"

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include "tcl.h"

#include "string.h"

#include "tclRegexp.h"
#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"
#include "exp_event.h"
#include "exp_tty.h"
#include "exp_tstamp.h"	/* this should disappear when interact */







<
<
<















<







10
11
12
13
14
15
16



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38

#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <ctype.h>	/* for isspace */
#include <time.h>	/* for time(3) */




#include "expect_cf.h"

#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include "tcl.h"

#include "string.h"


#include "exp_rename.h"
#include "exp_prog.h"
#include "exp_command.h"
#include "exp_log.h"
#include "exp_event.h"
#include "exp_tty.h"
#include "exp_tstamp.h"	/* this should disappear when interact */
51
52
53
54
55
56
57














58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#define INIT_EXPECT_TIMEOUT	10	/* seconds */
int exp_default_parity =	TRUE;
int exp_default_rm_nulls =	TRUE;

/* user variable names */
#define EXPECT_TIMEOUT		"timeout"
#define EXPECT_OUT		"expect_out"















/* 1 ecase struct is reserved for each case in the expect command.  Note that
eof/timeout don't use any of theirs, but the algorithm is simpler this way. */

struct ecase {	/* case for expect command */
	struct exp_i	*i_list;
	char *pat;	/* original pattern spec */
	char *body;	/* ptr to body to be executed upon match */
#define PAT_EOF		1
#define PAT_TIMEOUT	2
#define PAT_DEFAULT	3
#define PAT_FULLBUFFER	4
#define PAT_GLOB	5 /* glob-style pattern list */
#define PAT_RE		6 /* regular expression */
#define PAT_EXACT	7 /* exact string */
#define PAT_NULL	8 /* ASCII 0 */
#define PAT_TYPES	9 /* used to size array of pattern type descriptions */
	int use;	/* PAT_XXX */
	int simple_start;/* offset from start of buffer denoting where a */
			/* glob or exact match begins */
	int transfer;	/* if false, leave matched chars in input stream */
	int indices;	/* if true, write indices */
/*	int iwrite;*/	/* if true write spawn_id */
	int iread;	/* if true, reread indirects */
	int timestamp;	/* if true, write timestamps */
#define CASE_UNKNOWN	0
#define CASE_NORM	1
#define CASE_LOWER	2
	int Case;	/* convert case before doing match? */
	regexp *re;	/* if this is 0, then pattern match via glob */
};

/* descriptions of the pattern types, used for debugging */
char *pattern_style[PAT_TYPES];

struct exp_cases_descriptor {
	int count;







>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
|














<






<







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92
93
94
95

96
97
98
99
100
101
102
#define INIT_EXPECT_TIMEOUT	10	/* seconds */
int exp_default_parity =	TRUE;
int exp_default_rm_nulls =	TRUE;

/* user variable names */
#define EXPECT_TIMEOUT		"timeout"
#define EXPECT_OUT		"expect_out"

typedef struct ThreadSpecificData {
    int timeout;
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

/*
 * addr of these placeholders appear as clientData in ExpectCmd * when called
 * as expect_user and expect_tty.  It would be nicer * to invoked
 * expDevttyGet() but C doesn't allow this in an array initialization, sigh.
 */
static ExpState StdinoutPlaceholder;
static ExpState DevttyPlaceholder;

/* 1 ecase struct is reserved for each case in the expect command.  Note that
eof/timeout don't use any of theirs, but the algorithm is simpler this way. */

struct ecase {	/* case for expect command */
	struct exp_i	*i_list;
	Tcl_Obj *pat;	/* original pattern spec */
	Tcl_Obj *body;	/* ptr to body to be executed upon match */
#define PAT_EOF		1
#define PAT_TIMEOUT	2
#define PAT_DEFAULT	3
#define PAT_FULLBUFFER	4
#define PAT_GLOB	5 /* glob-style pattern list */
#define PAT_RE		6 /* regular expression */
#define PAT_EXACT	7 /* exact string */
#define PAT_NULL	8 /* ASCII 0 */
#define PAT_TYPES	9 /* used to size array of pattern type descriptions */
	int use;	/* PAT_XXX */
	int simple_start;/* offset from start of buffer denoting where a */
			/* glob or exact match begins */
	int transfer;	/* if false, leave matched chars in input stream */
	int indices;	/* if true, write indices */

	int iread;	/* if true, reread indirects */
	int timestamp;	/* if true, write timestamps */
#define CASE_UNKNOWN	0
#define CASE_NORM	1
#define CASE_LOWER	2
	int Case;	/* convert case before doing match? */

};

/* descriptions of the pattern types, used for debugging */
char *pattern_style[PAT_TYPES];

struct exp_cases_descriptor {
	int count;
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	cmd->ecd.cases = 0;
	cmd->ecd.count = 0;
	cmd->i_list = 0;
}

static int i_read_errno;/* place to save errno, if i_read() == -1, so it
			   doesn't get overwritten before we get to read it */
#if 0
static jmp_buf env;	/* for interruptable read() */
			/* longjmp(env,1) times out the read */
			/* longjmp(env,2) restarts the read */
static int env_valid = FALSE;	/* whether we can longjmp or not */
#endif

#ifdef SIMPLE_EVENT
static int alarm_fired;	/* if alarm occurs */
#endif

void exp_background_filehandlers_run_all();

/* exp_indirect_updateX is called by Tcl when an indirect variable is set */
static char *exp_indirect_update1();	/* 1-part Tcl variable names */
static char *exp_indirect_update2();	/* 2-part Tcl variable names */

static int	exp_i_read _ANSI_ARGS_((Tcl_Interp *,int,int,int));

#ifdef SIMPLE_EVENT
/*ARGSUSED*/
static RETSIGTYPE
sigalarm_handler(n)
int n;		       	/* unused, for compatibility with STDC */
{
	alarm_fired = TRUE;
#if 0
	/* check env_valid first to protect us from the alarm occurring */
	/* in the window between i_read and alarm(0) */
	if (env_valid) longjmp(env,1);
#endif /*0*/
}
#endif /*SIMPLE_EVENT*/

#if 0
/*ARGSUSED*/
static RETSIGTYPE
sigalarm_handler(n)
int n;		       	/* unused, for compatibility with STDC */
{
#ifdef REARM_SIG
	signal(SIGALRM,sigalarm_handler);
#endif

	/* check env_valid first to protect us from the alarm occurring */
	/* in the window between i_read and alarm(0) */
	if (env_valid) longjmp(env,1);
}
#endif /*0*/

#if 0

/* upon interrupt, act like timeout */
/*ARGSUSED*/
static RETSIGTYPE
sigint_handler(n)
int n;			/* unused, for compatibility with STDC */
{
#ifdef REARM_SIG
	signal(SIGINT,sigint_handler);/* not nec. for BSD, but doesn't hurt */
#endif

#ifdef TCL_DEBUGGER
	if (exp_tcl_debugger_available) {
		/* if the debugger is active and we're reading something, */
		/* force the debugger to go interactive now and when done, */
		/* restart the read.  */

		Dbg_On(exp_interp,env_valid);

		/* restart the read */
		if (env_valid) longjmp(env,2);

		/* if no read is in progess, just let debugger start at */
		/* the next command. */
		return;
	}
#endif

#if 0
/* the ability to timeout a read via ^C is hereby removed 8-Mar-1993 - DEL */

	/* longjmp if we are executing a read inside of expect command */
	if (env_valid) longjmp(env,1);
#endif

	/* if anywhere else in code, prepare to exit */
	exp_exit(exp_interp,0);
}
#endif /*0*/

/* remove nulls from s.  Initially, the number of chars in s is c, */
/* not strlen(s).  This count does not include the trailing null. */
/* returns number of nulls removed. */
static int
rm_nulls(s,c)
char *s;
int c;
{
	char *s2 = s;	/* points to place in original string to put */
			/* next non-null character */
	int count = 0;
	int i;

	for (i=0;i<c;i++,s++) {
		if (0 == *s) {
			count++;
			continue;
		}
		if (count) *s2 = *s;
		s2++;
	}
	return(count);
}

/* free up everything in ecase */
static void
free_ecase(interp,ec,free_ilist)
Tcl_Interp *interp;
struct ecase *ec;
int free_ilist;		/* if we should free ilist */
{
	if (ec->re) ckfree((char *)ec->re);

	if (ec->i_list->duration == EXP_PERMANENT) {
		if (ec->pat) ckfree(ec->pat);
		if (ec->body) ckfree(ec->body);
	}

	if (free_ilist) {
		ec->i_list->ecount--;
		if (ec->i_list->ecount == 0)
			exp_free_i(interp,ec->i_list,exp_indirect_update2);
	}

	ckfree((char *)ec);	/* NEW */
}

/* free up any argv structures in the ecases */
static void
free_ecases(interp,eg,free_ilist)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;







<
<
<
<
<
<





|





<
<







<
<
<
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







<
<
|
|
|
|

|
|
|
|
|

|







129
130
131
132
133
134
135






136
137
138
139
140
141
142
143
144
145
146


147
148
149
150
151
152
153





154
155
156

















































































157
158
159
160
161
162
163


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	cmd->ecd.cases = 0;
	cmd->ecd.count = 0;
	cmd->i_list = 0;
}

static int i_read_errno;/* place to save errno, if i_read() == -1, so it
			   doesn't get overwritten before we get to read it */







#ifdef SIMPLE_EVENT
static int alarm_fired;	/* if alarm occurs */
#endif

void exp_background_channelhandlers_run_all();

/* exp_indirect_updateX is called by Tcl when an indirect variable is set */
static char *exp_indirect_update1();	/* 1-part Tcl variable names */
static char *exp_indirect_update2();	/* 2-part Tcl variable names */



#ifdef SIMPLE_EVENT
/*ARGSUSED*/
static RETSIGTYPE
sigalarm_handler(n)
int n;		       	/* unused, for compatibility with STDC */
{
	alarm_fired = TRUE;





}
#endif /*SIMPLE_EVENT*/


















































































/* free up everything in ecase */
static void
free_ecase(interp,ec,free_ilist)
Tcl_Interp *interp;
struct ecase *ec;
int free_ilist;		/* if we should free ilist */
{


    if (ec->i_list->duration == EXP_PERMANENT) {
	if (ec->pat) Tcl_DecrRefCount(ec->pat);
	if (ec->body) Tcl_DecrRefCount(ec->body);
    }

    if (free_ilist) {
	ec->i_list->ecount--;
	if (ec->i_list->ecount == 0)
	    exp_free_i(interp,ec->i_list,exp_indirect_update2);
    }

    ckfree((char *)ec);	/* NEW */
}

/* free up any argv structures in the ecases */
static void
free_ecases(interp,eg,free_ilist)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;
325
326
327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359




360
361


362
363









364

365






366











367







368



369



370














371
372
373
374
375
376
377
378
379


380
381
382
383
384
385
386
387


388
389
390

391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
   foo\n	FALSE
   \nfoo\n	TRUE  (set of args)
   \nfoo\nbar	TRUE

   Current test is very cheap and almost always right :-)
*/
int 
exp_one_arg_braced(p)
char *p;
{
	int seen_nl = FALSE;


	for (;*p;p++) {
		if (*p == '\n') {
			seen_nl = TRUE;
			continue;
		}

		if (!isspace(*p)) {
			return(seen_nl);
		}
	}
	return FALSE;
}

/* called to execute a command of only one argument - a hack to commands */
/* to be called with all args surrounded by an outer set of braces */
/* returns TCL_whatever */
/*ARGSUSED*/
int
exp_eval_with_one_arg(clientData,interp,argv)
ClientData clientData;
Tcl_Interp *interp;
char **argv;
{




	char *buf;
	int rc;


	char *a;










	/* + 11 is for " -nobrace " and null at end */

	buf = ckalloc(strlen(argv[0]) + strlen(argv[1]) + 11);






	/* recreate statement (with -nobrace to prevent recursion) */











	sprintf(buf,"%s -nobrace %s",argv[0],argv[1]);











	/*



	 * replace top-level newlines with blanks














	 */

	/* Should only be necessary to run over argv[1] and then sprintf */
	/* that into the buffer, but the ICEM guys insist that writing */
	/* back over the original arguments makes their Tcl compiler very */
	/* unhappy. */
	for (a=buf;*a;) {
		extern char *TclWordEnd();



		for (;isspace(*a);a++) {
			if (*a == '\n') *a = ' ';
		}
#if TCL_MAJOR_VERSION < 8
		a = TclWordEnd(a,0,(int *)0)+1;
#else
		a = TclWordEnd(a,&a[strlen(a)],0,(int *)0)+1;
#endif


	}

	rc = Tcl_Eval(interp,buf);


	ckfree(buf);
	return(rc);

}

static void
ecase_clear(ec)
struct ecase *ec;
{
	ec->i_list = 0;
	ec->pat = 0;
	ec->body = 0;
	ec->transfer = TRUE;
	ec->indices = FALSE;
/*	ec->iwrite = FALSE;*/
	ec->iread = FALSE;
	ec->timestamp = FALSE;
	ec->re = 0;
	ec->Case = CASE_NORM;
	ec->use = PAT_GLOB;
}

static struct ecase *
ecase_new()
{







|
|


>







|











|


|

>
>
>
>
|
|
>
>
|

>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
|
<
|
<

>
>
|
<
|
<
|
|
<
<
>
>
|
|
<
>
|
<
|
>











<


<







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

349

350
351
352
353

354

355
356


357
358
359
360

361
362

363
364
365
366
367
368
369
370
371
372
373
374
375

376
377

378
379
380
381
382
383
384
   foo\n	FALSE
   \nfoo\n	TRUE  (set of args)
   \nfoo\nbar	TRUE

   Current test is very cheap and almost always right :-)
*/
int 
exp_one_arg_braced(objPtr)	/* INTL */
Tcl_Obj *objPtr;
{
	int seen_nl = FALSE;
	char *p = Tcl_GetString(objPtr);

	for (;*p;p++) {
		if (*p == '\n') {
			seen_nl = TRUE;
			continue;
		}

		if (!isspace(*p)) { /* INTL: ISO space */
			return(seen_nl);
		}
	}
	return FALSE;
}

/* called to execute a command of only one argument - a hack to commands */
/* to be called with all args surrounded by an outer set of braces */
/* returns TCL_whatever */
/*ARGSUSED*/
int
exp_eval_with_one_arg(clientData,interp,objv) /* INTL */
ClientData clientData;
Tcl_Interp *interp;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
#define NUM_STATIC_OBJS 20
    Tcl_Obj *staticObjArray[NUM_STATIC_OBJS];
    int maxobjs = NUM_STATIC_OBJS;
    Tcl_Token *tokenPtr;
    char *p, *next;
    int rc;
    Tcl_Obj **objs = staticObjArray;
    int objc, bytesLeft, numWords, i;
    Tcl_Parse parse;

    /*
     * Prepend the command name and the -nobrace switch so we can
     * reinvoke without recursing.
     */
    objc = 2;
    objs[0] = objv[0];
    objs[1] = Tcl_NewStringObj("-nobrace", -1);
    Tcl_IncrRefCount(objs[0]);
    Tcl_IncrRefCount(objs[1]);

    p = Tcl_GetStringFromObj(objv[1], &bytesLeft);

    /*
     * Treat the pattern/action block like a series of Tcl commands.
     * For each command, parse the command words, perform substititions
     * on each word, and add the words to an array of values.  We don't
     * actually evaluate the individual commands, just the substitutions.
     */

    do {
	if (Tcl_ParseCommand(interp, p, bytesLeft, 0, &parse)
	        != TCL_OK) {
	    rc = TCL_ERROR;
	    goto done;
	}
	numWords = parse.numWords;
 	if (numWords > 0) {
	    /*
	     * Generate an array of objects for the words of the command.
	     */
    
	    if (objc + numWords > maxobjs) {
		Tcl_Obj ** newobjs;
		maxobjs = (objc + numWords) * 2;
		newobjs = (Tcl_Obj **)ckalloc(maxobjs * sizeof (Tcl_Obj *));
		memcpy(newobjs, objs, objc*sizeof(Tcl_Obj *));
		if (objs != staticObjArray) {
		    ckfree((char*)objs);
		}
		objs = newobjs;   
	    }

	    /*
	     * For each word, perform substitutions then store the
	     * result in the objs array.
	     */
	    
	    for (tokenPtr = parse.tokenPtr; numWords > 0;
		 numWords--, tokenPtr += (tokenPtr->numComponents + 1)) {
		objs[objc] = Tcl_EvalTokens(interp, tokenPtr+1,
			tokenPtr->numComponents);
		if (objs[objc] == NULL) {
		    rc = TCL_ERROR;
		    goto done;
		}
		objc++;
	    }
	}

	/*
	 * Advance to the next command in the script.
	 */
	next = parse.commandStart + parse.commandSize;
	bytesLeft -= next - p;
	p = next;
	Tcl_FreeParse(&parse);

    } while (bytesLeft > 0);


    /*
     * Now evaluate the entire command with no further substitutions.
     */



    rc = Tcl_EvalObjv(interp, objc, objs, 0);
 done:


    for (i = 0; i < objc; i++) {
	Tcl_DecrRefCount(objs[i]);
    }
    if (objs != staticObjArray) {

	ckfree((char *) objs);
    }

    return(rc);
#undef NUM_STATIC_OBJS
}

static void
ecase_clear(ec)
struct ecase *ec;
{
	ec->i_list = 0;
	ec->pat = 0;
	ec->body = 0;
	ec->transfer = TRUE;
	ec->indices = FALSE;

	ec->iread = FALSE;
	ec->timestamp = FALSE;

	ec->Case = CASE_NORM;
	ec->use = PAT_GLOB;
}

static struct ecase *
ecase_new()
{
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

477












478




479

480
481
482

483
484
485
486
487
488
489
490
491
492
493
494
495
496
497





498




499
500





501
502
503

504
505

506
507




508
509


510
511
512
513
514
515
516
517
518
519
520
521
522

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

542
543
544

545
546
547
548
549



550
551
552
553
554
555
556
557
558
559






560
561



562








563



564




565
















566

567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586

587
588
589





590

591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
















































649
650
651
652
653
654
655
656

657
658
659
660
661
662

663

664


665
666
667
668
669
670
671
672
673
674
675
676
677
















678
679
680
681
682
683
684







685
686
687
688
689
690
691
692

693
694
695
696
697
698
699


700



701
702


703
704
705
706
707


708
709


710
711









712
713
714
715
716
717
718
719
720
721
722
723

724
725
726
727
728
729
730
731
732
733
734
735
736
737
738




739
740
741
742
743
744


745

746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
default exp_i is forced so that the command "expect" works right.

The exp_i chain can be broken by the caller if desired.

*/

static int
parse_expect_args(interp,eg,default_spawn_id,argc,argv)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;
int default_spawn_id;	/* suggested master if called as expect_user or _tty */
int argc;
char **argv;
{
	int i;
	char *arg;
	struct ecase ec;	/* temporary to collect args */

	argv++;
	argc--;

	eg->timeout_specified_by_flag = FALSE;

	ecase_clear(&ec);

	/* Allocate an array to store the ecases.  Force array even if 0 */
	/* cases.  This will often be too large (i.e., if there are flags) */
	/* but won't affect anything. */

	eg->ecd.cases = (struct ecase **)ckalloc(
		sizeof(struct ecase *) * (1+(argc/2)));

	eg->ecd.count = 0;

	for (i = 0;i<argc;i++) {

		arg = argv[i];












	




		if (exp_flageq("timeout",arg,7)) {

			ec.use = PAT_TIMEOUT;
		} else if (exp_flageq("eof",arg,3)) {
			ec.use = PAT_EOF;

		} else if (exp_flageq("full_buffer",arg,11)) {
			ec.use = PAT_FULLBUFFER;
		} else if (exp_flageq("default",arg,7)) {
			ec.use = PAT_DEFAULT;
		} else if (exp_flageq("null",arg,4)) {
			ec.use = PAT_NULL;
		} else if (arg[0] == '-') {
			arg++;
			if (exp_flageq1('-',arg)		/* "--" is deprecated */
			  || exp_flageq("glob",arg,2)) {
				i++;
				/* assignment here is not actually necessary */
				/* since cases are initialized this way above */
				/* ec.use = PAT_GLOB; */
			} else if (exp_flageq("regexp",arg,2)) {





				i++;




				ec.use = PAT_RE;
				TclRegError((char *)0);





				if (!(ec.re = TclRegComp(argv[i]))) {
					exp_error(interp,"bad regular expression: %s",
								TclGetRegError());

					goto error;
				}

			} else if (exp_flageq("exact",arg,2)) {
				i++;




				ec.use = PAT_EXACT;
			} else if (exp_flageq("notransfer",arg,1)) {


				ec.transfer = 0;
				continue;
			} else if (exp_flageq("nocase",arg,3)) {
				ec.Case = CASE_LOWER;
				continue;
			} else if (exp_flageq1('i',arg)) {
				i++;
				if (i>=argc) {
					exp_error(interp,"-i requires following spawn_id");
					goto error;
				}

				ec.i_list = exp_new_i_complex(interp,argv[i],

					eg->duration,exp_indirect_update2);

				ec.i_list->cmdtype = eg->cmdtype;

				/* link new i_list to head of list */
				ec.i_list->next = eg->i_list;
				eg->i_list = ec.i_list;

				continue;
			} else if (exp_flageq("indices",arg,2)) {
				ec.indices = TRUE;
				continue;
			} else if (exp_flageq("iwrite",arg,2)) {
/*				ec.iwrite = TRUE;*/
				continue;
			} else if (exp_flageq("iread",arg,2)) {
				ec.iread = TRUE;
				continue;
			} else if (exp_flageq("timestamp",arg,2)) {

				ec.timestamp = TRUE;
				continue;
			} else if (exp_flageq("timeout",arg,2)) {

				i++;
				if (i>=argc) {
					exp_error(interp,"-timeout requires following # of seconds");
					goto error;
				}




				eg->timeout = atoi(argv[i]);
				eg->timeout_specified_by_flag = TRUE;
				continue;
			} else if (exp_flageq("nobrace",arg,7)) {
				/* nobrace does nothing but take up space */
				/* on the command line which prevents */
				/* us from re-expanding any command lines */
				/* of one argument that looks like it should */
				/* be expanded to multiple arguments. */






				continue;
			} else {



				exp_error(interp,"usage: unrecognized flag <%s>",arg);








				goto error;



			}




		}


















		/* if no -i, use previous one */
		if (!ec.i_list) {
			/* if no -i flag has occurred yet, use default */
			if (!eg->i_list) {
				if (default_spawn_id != EXP_SPAWN_ID_BAD) {
					eg->i_list = exp_new_i_simple(default_spawn_id,eg->duration);
				} else {
					/* it'll be checked later, if used */

					(void) exp_update_master(interp,&default_spawn_id,0,0);
					eg->i_list = exp_new_i_simple(default_spawn_id,eg->duration);
				}
			}
			ec.i_list = eg->i_list;
		}
		ec.i_list->ecount++;

		/* save original pattern spec */
		/* keywords such as "-timeout" are saved as patterns here */
		/* useful for debugging but not otherwise used */
		save_str(&ec.pat,argv[i],eg->duration == EXP_TEMPORARY);

		save_str(&ec.body,argv[i+1],eg->duration == EXP_TEMPORARY);
			
		i++;







		*(eg->ecd.cases[eg->ecd.count] = ecase_new()) = ec;

		/* clear out for next set */
		ecase_clear(&ec);

		eg->ecd.count++;
	}


	/* if no patterns at all have appeared force the current */
	/* spawn id to be added to list anyway */

	if (eg->i_list == 0) {
		if (default_spawn_id != EXP_SPAWN_ID_BAD) {
			eg->i_list = exp_new_i_simple(default_spawn_id,eg->duration);
		} else {
			/* it'll be checked later, if used */

			(void) exp_update_master(interp,&default_spawn_id,0,0);
			eg->i_list = exp_new_i_simple(default_spawn_id,eg->duration);
		}
	}

	return(TCL_OK);

 error:
	/* very hard to free case_master_list here if it hasn't already */
	/* been attached to a case, ugh */

	/* note that i_list must be avail to free ecases! */
	free_ecases(interp,eg,0);

	/* undo temporary ecase */
	/* free_ecase doesn't quite handle this right, so do it by hand */
	if (ec.re) ckfree((char *)ec.re);
	if (eg->duration == EXP_PERMANENT) {
		if (ec.pat) ckfree(ec.pat);
		if (ec.body) ckfree(ec.body);
	}

	if (eg->i_list)
		exp_free_i(interp,eg->i_list,exp_indirect_update2);
	return(TCL_ERROR);
}

#define EXP_IS_DEFAULT(x)	((x) == EXP_TIMEOUT || (x) == EXP_EOF)

static char yes[] = "yes\r\n";
static char no[] = "no\r\n";

/* this describes status of a successful match */
struct eval_out {
	struct ecase *e;		/* ecase that matched */
	struct exp_f *f;			/* struct exp_f that matched */
	char *buffer;			/* buffer that matched */
	int match;			/* # of chars in buffer that matched */
					/* or # of chars in buffer at EOF */
};


















































/* like eval_cases, but handles only a single cases that needs a real */
/* string match */
/* returns EXP_X where X is MATCH, NOMATCH, FULLBUFFER, TCLERRROR */
static int
eval_case_string(interp,e,m,o,last_f,last_case,suffix)
Tcl_Interp *interp;
struct ecase *e;
int m;

struct eval_out *o;		/* 'output' - i.e., final case of interest */
/* next two args are for debugging, when they change, reprint buffer */
struct exp_f **last_f;
int *last_case;
char *suffix;
{

	struct exp_f *f = exp_fs + m;

	char *buffer;



	/* if -nocase, use the lowerized buffer */
	buffer = ((e->Case == CASE_NORM)?f->buffer:f->lower);

	/* if master or case changed, redisplay debug-buffer */
	if ((f != *last_f) || e->Case != *last_case) {
		debuglog("\r\nexpect%s: does \"%s\" (spawn_id %d) match %s ",
			 	suffix,
				dprintify(buffer),f-exp_fs,
				pattern_style[e->use]);
		*last_f = f;
		*last_case = e->Case;
	}

















	if (e->use == PAT_RE) {
		debuglog("\"%s\"? ",dprintify(e->pat));
		TclRegError((char *)0);
		if (buffer && TclRegExec(e->re,buffer,buffer)) {
			o->e = e;
			o->match = e->re->endp[0]-buffer;







			o->buffer = buffer;
			o->f = f;
			debuglog(yes);
			return(EXP_MATCH);
		} else {
			debuglog(no);
			if (TclGetRegError()) {
			    exp_error(interp,"-re failed: %s",TclGetRegError());

			    return(EXP_TCLERROR);
		        }
		    }
	} else if (e->use == PAT_GLOB) {
		int match; /* # of chars that matched */

	        debuglog("\"%s\"? ",dprintify(e->pat));


		if (buffer && (-1 != (match = Exp_StringMatch(



				buffer,e->pat,&e->simple_start)))) {
			o->e = e;


			o->match = match;
			o->buffer = buffer;
			o->f = f;
			debuglog(yes);
			return(EXP_MATCH);


		} else debuglog(no);
	} else if (e->use == PAT_EXACT) {


		char *p = strstr(buffer,e->pat);
	        debuglog("\"%s\"? ",dprintify(e->pat));









		if (p) {
			e->simple_start = p - buffer;
			o->e = e;
			o->match = strlen(e->pat);
			o->buffer = buffer;
			o->f = f;
			debuglog(yes);
			return(EXP_MATCH);
		} else debuglog(no);
	} else if (e->use == PAT_NULL) {
		int i = 0;
		debuglog("null? ");

		for (;i<f->size;i++) {
			if (buffer[i] == 0) {
				o->e = e;
				o->match = i+1;	/* in this case, match is */
						/* just the # of chars + 1 */
						/* before the null */
				o->buffer = buffer;
				o->f = f;
				debuglog(yes);
				return EXP_MATCH;
			}
		}
		debuglog(no);
	} else if ((f->size == f->msize) && (f->size > 0)) {
		debuglog("%s? ",e->pat);




		o->e = e;
		o->match = f->umsize;
		o->buffer = f->buffer;
		o->f = f;
		debuglog(yes);
		return(EXP_FULLBUFFER);


	}

	return(EXP_NOMATCH);
}

/* sets o.e if successfully finds a matching pattern, eof, timeout or deflt */
/* returns original status arg or EXP_TCLERROR */
static int
eval_cases(interp,eg,m,o,last_f,last_case,status,masters,mcount,suffix)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;
int m;
struct eval_out *o;		/* 'output' - i.e., final case of interest */
/* next two args are for debugging, when they change, reprint buffer */
struct exp_f **last_f;
int *last_case;
int status;
int *masters;
int mcount;
char *suffix;
{
	int i;
	int em;	/* master of ecase */
	struct ecase *e;

	if (o->e || status == EXP_TCLERROR || eg->ecd.count == 0) return(status);

	if (status == EXP_TIMEOUT) {
		for (i=0;i<eg->ecd.count;i++) {
			e = eg->ecd.cases[i];
			if (e->use == PAT_TIMEOUT || e->use == PAT_DEFAULT) {
				o->e = e;
				break;
			}
		}
		return(status);
	} else if (status == EXP_EOF) {
		for (i=0;i<eg->ecd.count;i++) {
			e = eg->ecd.cases[i];
			if (e->use == PAT_EOF || e->use == PAT_DEFAULT) {
				struct exp_fd_list *fdl;

				for (fdl=e->i_list->fd_list; fdl ;fdl=fdl->next) {
					em = fdl->fd;
					if (em == EXP_SPAWN_ID_ANY || em == m) {
						o->e = e;
						return(status);
					}
				}
			}
		}
		return(status);
	}

	/* the top loops are split from the bottom loop only because I can't */
	/* split'em further. */

	/* The bufferful condition does not prevent a pattern match from */
	/* occurring and vice versa, so it is scanned with patterns */
	for (i=0;i<eg->ecd.count;i++) {
		struct exp_fd_list *fdl;
		int j;

		e = eg->ecd.cases[i];
		if (e->use == PAT_TIMEOUT ||
		    e->use == PAT_DEFAULT ||
		    e->use == PAT_EOF) continue;

		for (fdl = e->i_list->fd_list; fdl; fdl = fdl->next) {
			em = fdl->fd;
			/* if em == EXP_SPAWN_ID_ANY, then user is explicitly asking */
			/* every case to be checked against every master */
			if (em == EXP_SPAWN_ID_ANY) {
				/* test against each spawn_id */
				for (j=0;j<mcount;j++) {
					status = eval_case_string(interp,e,masters[j],o,last_f,last_case,suffix);

					if (status != EXP_NOMATCH) return(status);
				}
			} else {
				/* reject things immediately from wrong spawn_id */
				if (em != m) continue;

				status = eval_case_string(interp,e,m,o,last_f,last_case,suffix);
				if (status != EXP_NOMATCH) return(status);
			}
		}
	}
	return(EXP_NOMATCH);
}

static void
ecases_remove_by_expi(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
struct exp_i *exp_i;







|


|
|
|

|
|
|
<
<
<

|

|

|
|
|

|
<

|

|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
|
<
|
>
|
<
<
|
<
|
<
<
<
<
|
|
|
|
|
>
>
>
>
>
|
>
>
>
>
|
|
>
>
>
>
>
|
<
|
>
|
|
>
|
|
>
>
>
>
|
<
>
>
|
|
|
|
|
|
|
|
|
|
|
<
|
>
|
|
|

|
|
|
|
<
|
|
|
|
<
<
<
|
|
<
>
|
|
<
>
|
|
|
|
|
>
>
>
|
<
|
|
|
|
|
|
|
|
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|
|
|
|
|
<
>
|
|
|
|
|
|
|

|
|
|
|
>
|
|
|
>
>
>
>
>
|
>
|


|

|

|
>
|
|

|
|
|
|
<
>
|
|
|
|

|


|
|

|
|

<
<
<
<
<
<
<
<
|
|
|









|
|
|
|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|


<
>


|



>
|
>
|
>
>

|
|

|
|
|
<
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
|
|
>
>
>
>
>
>
>
|
|
|
|
|
|
<
<
>
|
|
<
|
|

|
>
>
|
>
>
>
|
<
>
>
|
|
|
|
|
>
>
|
|
>
>
|
|
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
<
<
|
|
|
|
|
<
|
|
|
>
>
>
>
|
|
|
|
|
|
>
>
|
>
|





|


|


|


|



|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
>
|
|
|
|
|

|
|
|
|
|
|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427



428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466


467

468




469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

492
493
494
495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511
512
513
514
515
516

517
518
519
520
521
522
523
524
525
526

527
528
529
530



531
532

533
534
535

536
537
538
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663








664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780




781
782
783
784
785
786
787
788
789
790
791
792
793
794
795


796
797
798

799
800
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850


851
852
853
854
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
default exp_i is forced so that the command "expect" works right.

The exp_i chain can be broken by the caller if desired.

*/

static int
parse_expect_args(interp,eg,default_esPtr,objc,objv)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;
ExpState *default_esPtr;	/* suggested ExpState if called as expect_user or _tty */
int objc;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int i;
    char *string;
    struct ecase ec;	/* temporary to collect args */




    eg->timeout_specified_by_flag = FALSE;

    ecase_clear(&ec);

    /* Allocate an array to store the ecases.  Force array even if 0 */
    /* cases.  This will often be too large (i.e., if there are flags) */
    /* but won't affect anything. */

    eg->ecd.cases = (struct ecase **)ckalloc(sizeof(struct ecase *) * (1+(objc/2)));


    eg->ecd.count = 0;

    for (i = 1;i<objc;i++) {
	int index;
	string = Tcl_GetString(objv[i]);
	if (string[0] == '-') {
	    static char *flags[] = {
		"-glob", "-regexp", "-exact", "-notransfer", "-nocase",
		"-i", "-indices", "-iread", "-timestamp", "-timeout",
		"-nobrace", "--", (char *)0
	    };
	    enum flags {
		EXP_ARG_GLOB, EXP_ARG_REGEXP, EXP_ARG_EXACT,
		EXP_ARG_NOTRANSFER, EXP_ARG_NOCASE, EXP_ARG_SPAWN_ID,
		EXP_ARG_INDICES, EXP_ARG_IREAD, EXP_ARG_TIMESTAMP,
		EXP_ARG_DASH_TIMEOUT, EXP_ARG_NOBRACE, EXP_ARG_DASH
	    };

	    /*
	     * Allow abbreviations of switches and report an error if we
	     * get an invalid switch.
	     */

	    if (Tcl_GetIndexFromObj(interp, objv[i], flags, "flag", 0,
		    &index) != TCL_OK) {

		return TCL_ERROR;
	    }
	    switch ((enum flags) index) {


	    case EXP_ARG_GLOB:

	    case EXP_ARG_DASH:




		i++;
		/* assignment here is not actually necessary */
		/* since cases are initialized this way above */
		/* ec.use = PAT_GLOB; */
		if (i >= objc) {
		    Tcl_WrongNumArgs(interp, 1, objv,"-glob pattern");
		    return TCL_ERROR;
		}
		goto pattern;
	    case EXP_ARG_REGEXP:
		i++;
		if (i >= objc) {
		    Tcl_WrongNumArgs(interp, 1, objv,"-regexp regexp");
		    return TCL_ERROR;
		}
		ec.use = PAT_RE;

		/*
		 * Try compiling the expression so we can report
		 * any errors now rather then when we first try to
		 * use it.
		 */


		if (!(Tcl_GetRegExpFromObj(interp, objv[i],
					   TCL_REG_ADVANCED))) {
		    goto error;
		}
		goto pattern;
	    case EXP_ARG_EXACT:
		i++;
		if (i >= objc) {
		    Tcl_WrongNumArgs(interp, 1, objv, "-exact string");
		    return TCL_ERROR;
		}
		ec.use = PAT_EXACT;

		goto pattern;
	    case EXP_ARG_NOTRANSFER:
		ec.transfer = 0;
		break;
	    case EXP_ARG_NOCASE:
		ec.Case = CASE_LOWER;
		break;
	    case EXP_ARG_SPAWN_ID:
		i++;
		if (i>=objc) {
		    Tcl_WrongNumArgs(interp, 1, objv, "-i spawn_id");
		    goto error;
		}

		ec.i_list = exp_new_i_complex(interp,
				      Tcl_GetString(objv[i]),
				      eg->duration, exp_indirect_update2);
		if (!ec.i_list) goto error;
		ec.i_list->cmdtype = eg->cmdtype;

		/* link new i_list to head of list */
		ec.i_list->next = eg->i_list;
		eg->i_list = ec.i_list;
		break;

	    case EXP_ARG_INDICES:
		ec.indices = TRUE;
		break;
	    case EXP_ARG_IREAD:



		ec.iread = TRUE;
		break;

	    case EXP_ARG_TIMESTAMP:
		ec.timestamp = TRUE;
		break;

	    case EXP_ARG_DASH_TIMEOUT:
		i++;
		if (i>=objc) {
		    Tcl_WrongNumArgs(interp, 1, objv, "-timeout seconds");
		    goto error;
		}
		if (Tcl_GetIntFromObj(interp, objv[i],
				      &eg->timeout) != TCL_OK) {
		    goto error;
		}

		eg->timeout_specified_by_flag = TRUE;
		break;
	    case EXP_ARG_NOBRACE:
		/* nobrace does nothing but take up space */
		/* on the command line which prevents */
		/* us from re-expanding any command lines */
		/* of one argument that looks like it should */
		/* be expanded to multiple arguments. */
		break;
	    }
	    /*
	     * Keep processing arguments, we aren't ready for the
	     * pattern yet.
	     */
	    continue;
	} else {
	    /*
	     * We have a pattern or keyword.
	     */

	    static char *keywords[] = {
		"timeout", "eof", "full_buffer", "default", "null",
		(char *)NULL
	    };
	    enum keywords {
		EXP_ARG_TIMEOUT, EXP_ARG_EOF, EXP_ARG_FULL_BUFFER,
		EXP_ARG_DEFAULT, EXP_ARG_NULL
	    };

	    /*
	     * Match keywords exactly, otherwise they are patterns.
	     */

	    if (Tcl_GetIndexFromObj(interp, objv[i], keywords, "keyword",
		    1 /* exact */, &index) != TCL_OK) {
		Tcl_ResetResult(interp);
		goto pattern;
	    }
	    switch ((enum keywords) index) {
	    case EXP_ARG_TIMEOUT:
		ec.use = PAT_TIMEOUT;
		break;
	    case EXP_ARG_EOF:
		ec.use = PAT_EOF;
		break;
	    case EXP_ARG_FULL_BUFFER:
		ec.use = PAT_FULLBUFFER;
		break;
	    case EXP_ARG_DEFAULT:
		ec.use = PAT_DEFAULT;
		break;
	    case EXP_ARG_NULL:
		ec.use = PAT_NULL;
		break;
	    }
pattern:
	    /* if no -i, use previous one */
	    if (!ec.i_list) {
		/* if no -i flag has occurred yet, use default */
		if (!eg->i_list) {
		    if (default_esPtr != EXP_SPAWN_ID_BAD) {
			eg->i_list = exp_new_i_simple(default_esPtr,eg->duration);
		    } else {

		        default_esPtr = expStateCurrent(interp,0,0,1);
		        if (!default_esPtr) goto error;
		        eg->i_list = exp_new_i_simple(default_esPtr,eg->duration);
		    }
		}
		ec.i_list = eg->i_list;
	    }
	    ec.i_list->ecount++;

	    /* save original pattern spec */
	    /* keywords such as "-timeout" are saved as patterns here */
	    /* useful for debugging but not otherwise used */

	    ec.pat = objv[i];
	    if (eg->duration == EXP_PERMANENT) Tcl_IncrRefCount(ec.pat);

	    i++;
	    if (i < objc) {
		ec.body = objv[i];
		if (eg->duration == EXP_PERMANENT) Tcl_IncrRefCount(ec.body);
	    } else {
		ec.body = NULL;
	    }

	    *(eg->ecd.cases[eg->ecd.count] = ecase_new()) = ec;

		/* clear out for next set */
	    ecase_clear(&ec);

	    eg->ecd.count++;
	}
    }

    /* if no patterns at all have appeared force the current */
    /* spawn id to be added to list anyway */

    if (eg->i_list == 0) {
	if (default_esPtr != EXP_SPAWN_ID_BAD) {
	    eg->i_list = exp_new_i_simple(default_esPtr,eg->duration);
	} else {

	    default_esPtr = expStateCurrent(interp,0,0,1);
	    if (!default_esPtr) goto error;
	    eg->i_list = exp_new_i_simple(default_esPtr,eg->duration);
	}
    }

    return(TCL_OK);

 error:
    /* very hard to free case_master_list here if it hasn't already */
    /* been attached to a case, ugh */

    /* note that i_list must be avail to free ecases! */
    free_ecases(interp,eg,0);









    if (eg->i_list)
	exp_free_i(interp,eg->i_list,exp_indirect_update2);
    return(TCL_ERROR);
}

#define EXP_IS_DEFAULT(x)	((x) == EXP_TIMEOUT || (x) == EXP_EOF)

static char yes[] = "yes\r\n";
static char no[] = "no\r\n";

/* this describes status of a successful match */
struct eval_out {
    struct ecase *e;		/* ecase that matched */
    ExpState *esPtr;		/* ExpState that matched */
    Tcl_Obj *buffer;		/* buffer that matched */
    int match;			/* # of bytes in buffer that matched */
			        /* or # of bytes in buffer at EOF */
};




/*
 *----------------------------------------------------------------------
 *
 * string_case_first --
 *
 *	Find the first instance of a pattern in a string.
 *
 * Results:
 *	Returns the pointer to the first instance of the pattern
 *	in the given string, or NULL if no match was found.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
string_case_first(string,pattern)	/* INTL */
    register char *string;	/* String. */
    register char *pattern;	/* Pattern, which may contain
				 * special characters. */
{
    char *s, *p;
    int offset;
    Tcl_UniChar ch1, ch2;
    
    while (*string != 0) {
	s = string;
	p = pattern;
	while (*s) {
	    s += Tcl_UtfToUniChar(s, &ch1);
	    offset = Tcl_UtfToUniChar(p, &ch2);
	    if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
		break;
	    }
	    p += offset;
	}
	if (*p == '\0') {
	    return string;
	}
	string++;
    }
    return NULL;
}

/* like eval_cases, but handles only a single cases that needs a real */
/* string match */
/* returns EXP_X where X is MATCH, NOMATCH, FULLBUFFER, TCLERRROR */
static int
eval_case_string(interp,e,esPtr,o,last_esPtr,last_case,suffix)
Tcl_Interp *interp;
struct ecase *e;

ExpState *esPtr;
struct eval_out *o;		/* 'output' - i.e., final case of interest */
/* next two args are for debugging, when they change, reprint buffer */
ExpState **last_esPtr;
int *last_case;
char *suffix;
{
    Tcl_Obj *buffer;
    Tcl_RegExp re;
    Tcl_RegExpInfo info;
    char *str;
    int length, flags;
    int result;

    buffer = esPtr->buffer;
    str = Tcl_GetStringFromObj(buffer, &length);

    /* if ExpState or case changed, redisplay debug-buffer */
    if ((esPtr != *last_esPtr) || e->Case != *last_case) {
	expDiagLog("\r\nexpect%s: does \"",suffix);

	expDiagLogU(expPrintify(str));
	expDiagLog("\" (spawn_id %s) match %s ",esPtr->name,pattern_style[e->use]);
	*last_esPtr = esPtr;
	*last_case = e->Case;
    }

    if (e->use == PAT_RE) {
	expDiagLog("\"");
	expDiagLogU(expPrintify(Tcl_GetString(e->pat)));
	expDiagLog("\"? ");
	if (e->Case == CASE_NORM) {
	    flags = TCL_REG_ADVANCED;
	} else {
	    flags = TCL_REG_ADVANCED | TCL_REG_NOCASE;
	}
		    
	re = Tcl_GetRegExpFromObj(interp, e->pat, flags);

	result = Tcl_RegExpExecObj(interp, re, buffer, 0 /* offset */,
		-1 /* nmatches */, 0 /* eflags */);
	if (result > 0) {





	    o->e = e;

	    /*
	     * Retrieve the byte offset of the end of the
	     * matched string.  
	     */

	    Tcl_RegExpGetInfo(re, &info);
	    o->match = Tcl_UtfAtIndex(str, info.matches[0].end) - str;
	    o->buffer = buffer;
	    o->esPtr = esPtr;
	    expDiagLogU(yes);
	    return(EXP_MATCH);
	} else if (result == 0) {
	    expDiagLogU(no);


	} else { /* result < 0 */
	    return(EXP_TCLERROR);
	}

    } else if (e->use == PAT_GLOB) {
	int match; /* # of bytes that matched */

	expDiagLog("\"");
	expDiagLogU(expPrintify(Tcl_GetString(e->pat)));
	expDiagLog("\"? ");
	if (buffer) {
	    match = Exp_StringCaseMatch(Tcl_GetString(buffer),
		    Tcl_GetString(e->pat),
		    (e->Case == CASE_NORM) ? 0 : 1,
		    &e->simple_start);

	    if (match != -1) {
		o->e = e;
		o->match = match;
		o->buffer = buffer;
		o->esPtr = esPtr;
		expDiagLogU(yes);
		return(EXP_MATCH);
	    }
	}
	expDiagLogU(no);
    } else if (e->use == PAT_EXACT) {
	int patLength;
	char *pat = Tcl_GetStringFromObj(e->pat, &patLength);
	char *p;

	if (e->Case == CASE_NORM) {
	    p = strstr(str, pat);
	} else {
	    p = string_case_first(str, pat);
	}	    

	expDiagLog("\"");
	expDiagLogU(expPrintify(Tcl_GetString(e->pat)));
	expDiagLog("\"? ");
	if (p) {
	    e->simple_start = p - str;
	    o->e = e;
	    o->match = patLength;
	    o->buffer = buffer;
	    o->esPtr = esPtr;
	    expDiagLogU(yes);
	    return(EXP_MATCH);
	} else expDiagLogU(no);
    } else if (e->use == PAT_NULL) {
	char *p;
	expDiagLogU("null? ");
	p = Tcl_UtfFindFirst(str, 0);

	if (p) {
	    o->e = e;
	    o->match = p-str;


	    o->buffer = buffer;
	    o->esPtr = esPtr;
	    expDiagLogU(yes);
	    return EXP_MATCH;
	}

	expDiagLogU(no);
    } else if (e->use == PAT_FULLBUFFER) {
      expDiagLogU(Tcl_GetString(e->pat));
      expDiagLogU("? ");
      /* this must be the same test as in expIRead */
      if ((expSizeGet(esPtr) + TCL_UTF_MAX >= esPtr->msize)
	    && (length > 0)) {
	o->e = e;
	o->match = length;
	o->buffer = esPtr->buffer;
	o->esPtr = esPtr;
	expDiagLogU(yes);
	return(EXP_FULLBUFFER);
      } else {
	expDiagLogU(no);
      }
    }
    return(EXP_NOMATCH);
}

/* sets o.e if successfully finds a matching pattern, eof, timeout or deflt */
/* returns original status arg or EXP_TCLERROR */
static int
eval_cases(interp,eg,esPtr,o,last_esPtr,last_case,status,esPtrs,mcount,suffix)
Tcl_Interp *interp;
struct exp_cmd_descriptor *eg;
ExpState *esPtr;
struct eval_out *o;		/* 'output' - i.e., final case of interest */
/* next two args are for debugging, when they change, reprint buffer */
ExpState **last_esPtr;
int *last_case;
int status;
ExpState *(esPtrs[]);
int mcount;
char *suffix;
{
    int i;
    ExpState *em;   /* ExpState of ecase */
    struct ecase *e;

    if (o->e || status == EXP_TCLERROR || eg->ecd.count == 0) return(status);

    if (status == EXP_TIMEOUT) {
	for (i=0;i<eg->ecd.count;i++) {
	    e = eg->ecd.cases[i];
	    if (e->use == PAT_TIMEOUT || e->use == PAT_DEFAULT) {
		o->e = e;
		break;
	    }
	}
	return(status);
    } else if (status == EXP_EOF) {
	for (i=0;i<eg->ecd.count;i++) {
	    e = eg->ecd.cases[i];
	    if (e->use == PAT_EOF || e->use == PAT_DEFAULT) {
		struct exp_state_list *slPtr;

		for (slPtr=e->i_list->state_list; slPtr ;slPtr=slPtr->next) {
		    em = slPtr->esPtr;
		    if (expStateAnyIs(em) || em == esPtr) {
			o->e = e;
			return(status);
		    }
		}
	    }
	}
	return(status);
    }

    /* the top loops are split from the bottom loop only because I can't */
    /* split'em further. */

    /* The bufferful condition does not prevent a pattern match from */
    /* occurring and vice versa, so it is scanned with patterns */
    for (i=0;i<eg->ecd.count;i++) {
	struct exp_state_list *slPtr;
	int j;

	e = eg->ecd.cases[i];
	if (e->use == PAT_TIMEOUT ||
		e->use == PAT_DEFAULT ||
		e->use == PAT_EOF) continue;

	for (slPtr = e->i_list->state_list; slPtr; slPtr = slPtr->next) {
	    em = slPtr->esPtr;
	    /* if em == EXP_SPAWN_ID_ANY, then user is explicitly asking */
	    /* every case to be checked against every ExpState */
	    if (expStateAnyIs(em)) {
		/* test against each spawn_id */
		for (j=0;j<mcount;j++) {
		    status = eval_case_string(interp,e,esPtrs[j],o,
			    last_esPtr,last_case,suffix);
		    if (status != EXP_NOMATCH) return(status);
		}
	    } else {
		/* reject things immediately from wrong spawn_id */
		if (em != esPtr) continue;

		status = eval_case_string(interp,e,esPtr,o,last_esPtr,last_case,suffix);
		if (status != EXP_NOMATCH) return(status);
	    }
	}
    }
    return(EXP_NOMATCH);
}

static void
ecases_remove_by_expi(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
struct exp_i *exp_i;
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
{
	ecases_remove_by_expi(interp,ecmd,exp_i);
	exp_i_remove(interp,&ecmd->i_list,exp_i);
}

/* remove ecases tied to a single direct spawn id */
static void
ecmd_remove_fd(interp,ecmd,m,direct)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
int m;
int direct;
{
	struct exp_i *exp_i, *next;
	struct exp_fd_list **fdl;

	for (exp_i=ecmd->i_list;exp_i;exp_i=next) {
		next = exp_i->next;

		if (!(direct & exp_i->direct)) continue;

		for (fdl = &exp_i->fd_list;*fdl;) {
			if (m == ((*fdl)->fd)) {
				struct exp_fd_list *tmp = *fdl;
				*fdl = (*fdl)->next;
				exp_free_fd_single(tmp);

				/* if last bg ecase, disarm spawn id */
				if ((ecmd->cmdtype == EXP_CMD_BG) && (m != EXP_SPAWN_ID_ANY)) {
					exp_fs[m].bg_ecount--;
					if (exp_fs[m].bg_ecount == 0) {
						exp_disarm_background_filehandler(m);
						exp_fs[m].bg_interp = 0;
					}
				}

				continue;
			}
			fdl = &(*fdl)->next;
		}

		/* if left with no fds (and is direct), get rid of it */
		/* and any dependent ecases */
		if (exp_i->direct == EXP_DIRECT && !exp_i->fd_list) {
			exp_i_remove_with_ecases(interp,ecmd,exp_i);
		}
	}
}

/* this is called from exp_close to clean up the fd */
void
exp_ecmd_remove_fd_direct_and_indirect(interp,m)
Tcl_Interp *interp;
int m;
{
	ecmd_remove_fd(interp,&exp_cmds[EXP_CMD_BEFORE],m,EXP_DIRECT|EXP_INDIRECT);
	ecmd_remove_fd(interp,&exp_cmds[EXP_CMD_AFTER],m,EXP_DIRECT|EXP_INDIRECT);
	ecmd_remove_fd(interp,&exp_cmds[EXP_CMD_BG],m,EXP_DIRECT|EXP_INDIRECT);

	/* force it - explanation in exp_tk.c where this func is defined */
	exp_disarm_background_filehandler_force(m);
}

/* arm a list of background fd's */
static void
fd_list_arm(interp,fdl)
Tcl_Interp *interp;
struct exp_fd_list *fdl;
{
	/* for each spawn id in list, arm if necessary */
	for (;fdl;fdl=fdl->next) {
		int m = fdl->fd;
		if (m == EXP_SPAWN_ID_ANY) continue;

		if (exp_fs[m].bg_ecount == 0) {
			exp_arm_background_filehandler(m);
			exp_fs[m].bg_interp = interp;
		}
		exp_fs[m].bg_ecount++;
	}
}

/* return TRUE if this ecase is used by this fd */
static int
exp_i_uses_fd(exp_i,fd)
struct exp_i *exp_i;
int fd;
{
	struct exp_fd_list *fdp;

	for (fdp = exp_i->fd_list;fdp;fdp=fdp->next) {
		if (fdp->fd == fd) return 1;
	}
	return 0;
}

static void
ecase_append(interp,ec)
Tcl_Interp *interp;
struct ecase *ec;
{
	if (!ec->transfer) Tcl_AppendElement(interp,"-notransfer");
	if (ec->indices) Tcl_AppendElement(interp,"-indices");
/*	if (ec->iwrite) Tcl_AppendElement(interp,"-iwrite");*/
	if (!ec->Case) Tcl_AppendElement(interp,"-nocase");

	if (ec->re) Tcl_AppendElement(interp,"-re");
	else if (ec->use == PAT_GLOB) Tcl_AppendElement(interp,"-gl");
	else if (ec->use == PAT_EXACT) Tcl_AppendElement(interp,"-ex");
	Tcl_AppendElement(interp,ec->pat);
	Tcl_AppendElement(interp,ec->body?ec->body:"");
}

/* append all ecases that match this exp_i */
static void
ecase_by_exp_i_append(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;







|


|


|
|

|
|

|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|


|

|

|

|
|
|


|


|

|

|

|
|
|
|

|
|
|
|
|
|




|

|

|

|
|











<


|


|
|







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
{
	ecases_remove_by_expi(interp,ecmd,exp_i);
	exp_i_remove(interp,&ecmd->i_list,exp_i);
}

/* remove ecases tied to a single direct spawn id */
static void
ecmd_remove_state(interp,ecmd,esPtr,direct)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
ExpState *esPtr;
int direct;
{
    struct exp_i *exp_i, *next;
    struct exp_state_list **slPtr;

    for (exp_i=ecmd->i_list;exp_i;exp_i=next) {
	next = exp_i->next;

	if (!(direct & exp_i->direct)) continue;

	for (slPtr = &exp_i->state_list;*slPtr;) {
	    if (esPtr == ((*slPtr)->esPtr)) {
		struct exp_state_list *tmp = *slPtr;
		*slPtr = (*slPtr)->next;
		exp_free_state_single(tmp);

		/* if last bg ecase, disarm spawn id */
		if ((ecmd->cmdtype == EXP_CMD_BG) && (expStateAnyIs(esPtr))) {
		    esPtr->bg_ecount--;
		    if (esPtr->bg_ecount == 0) {
			exp_disarm_background_channelhandler(esPtr);
			esPtr->bg_interp = 0;
		    }
		}
		
		continue;
	    }
	    slPtr = &(*slPtr)->next;
	}

	/* if left with no ExpStates (and is direct), get rid of it */
	/* and any dependent ecases */
	if (exp_i->direct == EXP_DIRECT && !exp_i->state_list) {
	    exp_i_remove_with_ecases(interp,ecmd,exp_i);
	}
    }
}

/* this is called from exp_close to clean up the ExpState */
void
exp_ecmd_remove_state_direct_and_indirect(interp,esPtr)
Tcl_Interp *interp;
ExpState *esPtr;
{
	ecmd_remove_state(interp,&exp_cmds[EXP_CMD_BEFORE],esPtr,EXP_DIRECT|EXP_INDIRECT);
	ecmd_remove_state(interp,&exp_cmds[EXP_CMD_AFTER],esPtr,EXP_DIRECT|EXP_INDIRECT);
	ecmd_remove_state(interp,&exp_cmds[EXP_CMD_BG],esPtr,EXP_DIRECT|EXP_INDIRECT);

	/* force it - explanation in exp_tk.c where this func is defined */
	exp_disarm_background_channelhandler_force(esPtr);
}

/* arm a list of background ExpState's */
static void
state_list_arm(interp,slPtr)
Tcl_Interp *interp;
struct exp_state_list *slPtr;
{
    /* for each spawn id in list, arm if necessary */
    for (;slPtr;slPtr=slPtr->next) {
	ExpState *esPtr = slPtr->esPtr;    
	if (expStateAnyIs(esPtr)) continue;

	if (esPtr->bg_ecount == 0) {
	    exp_arm_background_channelhandler(esPtr);
	    esPtr->bg_interp = interp;
	}
	esPtr->bg_ecount++;
    }
}

/* return TRUE if this ecase is used by this fd */
static int
exp_i_uses_state(exp_i,esPtr)
struct exp_i *exp_i;
ExpState *esPtr;
{
	struct exp_state_list *fdp;

	for (fdp = exp_i->state_list;fdp;fdp=fdp->next) {
		if (fdp->esPtr == esPtr) return 1;
	}
	return 0;
}

static void
ecase_append(interp,ec)
Tcl_Interp *interp;
struct ecase *ec;
{
	if (!ec->transfer) Tcl_AppendElement(interp,"-notransfer");
	if (ec->indices) Tcl_AppendElement(interp,"-indices");

	if (!ec->Case) Tcl_AppendElement(interp,"-nocase");

	if (ec->use == PAT_RE) Tcl_AppendElement(interp,"-re");
	else if (ec->use == PAT_GLOB) Tcl_AppendElement(interp,"-gl");
	else if (ec->use == PAT_EXACT) Tcl_AppendElement(interp,"-ex");
	Tcl_AppendElement(interp,Tcl_GetString(ec->pat));
	Tcl_AppendElement(interp,ec->body?Tcl_GetString(ec->body):"");
}

/* append all ecases that match this exp_i */
static void
ecase_by_exp_i_append(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

1128
1129
1130
1131
1132
1133

1134


1135





1136
1137





1138

1139
1140





1141
1142
1143

1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390























































1391
1392
1393
1394
1395
1396


1397








1398

1399

1400



1401
1402







1403











1404

1405
1406
1407




1408






1409
1410



1411










1412








1413










1414

1415




1416

1417


1418












1419


1420



1421


1422

1423








1424



1425


1426









1427

1428





1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459

1460

1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473

1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536

1537

1538

1539
1540
1541
1542
1543
1544
1545

1546
1547
1548
1549
1550

1551
1552
1553

1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598







1599



1600

1601













1602







1603
1604


1605

1606

1607

1608
1609



1610


1611

1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
Tcl_Interp *interp;
struct exp_i *exp_i;
{
	Tcl_AppendElement(interp,"-i");
	if (exp_i->direct == EXP_INDIRECT) {
		Tcl_AppendElement(interp,exp_i->variable);
	} else {
		struct exp_fd_list *fdp;

		/* if more than one element, add braces */
		if (exp_i->fd_list->next)
			Tcl_AppendResult(interp," {",(char *)0);

		for (fdp = exp_i->fd_list;fdp;fdp=fdp->next) {
			char buf[10];	/* big enough for a small int */
			sprintf(buf,"%d",fdp->fd);
			Tcl_AppendElement(interp,buf);
		}

		if (exp_i->fd_list->next)
			Tcl_AppendResult(interp,"} ",(char *)0);
	}
}

#if 0
/* delete ecases based on named -i descriptors */
int
expect_delete(interp,ecmd,argc,argv)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
int argc;
char **argv;
{
	while (*argv) {
		if (streq(argv[0],"-i") && argv[1]) {
			iflag = argv[1];
			argc-=2; argv+=2;
		} else if (streq(argv[0],"-all")) {
			all = TRUE;
			argc--; argv++;
		} else if (streq(argv[0],"-noindirect")) {
			direct &= ~EXP_INDIRECT;
			argc--; argv++;
		} else {
			exp_error(interp,"usage: -delete [-all | -i spawn_id]\n");
			return TCL_ERROR;
		}
	}

	if (all) {
		/* same logic as at end of regular expect cmd */
		free_ecases(interp,ecmd,0);
		exp_free_i(interp,ecmd->i_list,exp_indirect_update2);
		return TCL_OK;
	}

	if (!iflag) {
		if (0 == exp_update_master(interp,&m,0,0)) {
			return TCL_ERROR;
		}
	} else if (Tcl_GetInt(interp,iflag,&m) != TCL_OK) {
		/* handle as in indirect */

		struct exp_i **old_i;

		for (old_i=&ecmd->i_list;*old_i;) {
			struct exp_i *tmp;

			if ((*old_i)->direct == EXP_DIRECT) continue;
			if (!streq((*old_i)->variable,iflag)) continue;

			ecases_remove_by_expi(interp,ecmd,*old_i);

			/* unlink from middle of list */
			tmp = *old_i;
			*old_i = tmp->next;
			tmp->next = 0;
			exp_free_i(interp,tmp_i,exp_indirect_update2);
		} else {
			old_i = &(*old_i)->next;
		}
		return TCL_OK;
	}

	/* delete ecases of this direct_fd */
	/* unfinish after this ... */
	for (exp_i=ecmd->i_list;exp_i;exp_i=exp_i->next) {
		if (!(direct & exp_i->direct)) continue;
		if (!exp_i_uses_fd(exp_i,m)) continue;

		/* delete each ecase that uses this exp_i */


		ecase_by_exp_i_append(interp,ecmd,exp_i);
	}

	return TCL_OK;
}
#endif

/* return current setting of the permanent expect_before/after/bg */
int
expect_info(interp,ecmd,argc,argv)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
int argc;
char **argv;

{
	struct exp_i *exp_i;
	int i;
	int direct = EXP_DIRECT|EXP_INDIRECT;
	char *iflag = 0;
	int all = FALSE;	/* report on all fds */

	int m;








	while (*argv) {
		if (streq(argv[0],"-i") && argv[1]) {





			iflag = argv[1];

			argc-=2; argv+=2;
		} else if (streq(argv[0],"-all")) {





			all = TRUE;
			argc--; argv++;
		} else if (streq(argv[0],"-noindirect")) {

			direct &= ~EXP_INDIRECT;
			argc--; argv++;
		} else {
			exp_error(interp,"usage: -info [-all | -i spawn_id]\n");
			return TCL_ERROR;
		}
	}

	if (all) {
		/* avoid printing out -i when redundant */
		struct exp_i *previous = 0;

		for (i=0;i<ecmd->ecd.count;i++) {
			if (previous != ecmd->ecd.cases[i]->i_list) {
				exp_i_append(interp,ecmd->ecd.cases[i]->i_list);
				previous = ecmd->ecd.cases[i]->i_list;
			}
			ecase_append(interp,ecmd->ecd.cases[i]);
		}
		return TCL_OK;
	}

	if (!iflag) {
		if (0 == exp_update_master(interp,&m,0,0)) {
			return TCL_ERROR;
		}
	} else if (Tcl_GetInt(interp,iflag,&m) != TCL_OK) {
		/* handle as in indirect */
		Tcl_ResetResult(interp);
		for (i=0;i<ecmd->ecd.count;i++) {
			if (ecmd->ecd.cases[i]->i_list->direct == EXP_INDIRECT &&
			    streq(ecmd->ecd.cases[i]->i_list->variable,iflag)) {
				ecase_append(interp,ecmd->ecd.cases[i]);
			}
		}
		return TCL_OK;
	}

	/* print ecases of this direct_fd */
	for (exp_i=ecmd->i_list;exp_i;exp_i=exp_i->next) {
		if (!(direct & exp_i->direct)) continue;
		if (!exp_i_uses_fd(exp_i,m)) continue;
		ecase_by_exp_i_append(interp,ecmd,exp_i);
	}

	return TCL_OK;
}

/* Exp_ExpectGlobalCmd is invoked to process expect_before/after */
/*ARGSUSED*/
int
Exp_ExpectGlobalCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int result = TCL_OK;
	struct exp_i *exp_i, **eip;
	struct exp_fd_list *fdl;	/* temp for interating over fd_list */
	struct exp_cmd_descriptor eg;
	int count;

	struct exp_cmd_descriptor *ecmd = (struct exp_cmd_descriptor *) clientData;

	if ((argc == 2) && exp_one_arg_braced(argv[1])) {
		return(exp_eval_with_one_arg(clientData,interp,argv));
	} else if ((argc == 3) && streq(argv[1],"-brace")) {
		char *new_argv[2];
		new_argv[0] = argv[0];
		new_argv[1] = argv[2];
		return(exp_eval_with_one_arg(clientData,interp,new_argv));
	}

	if (argc > 1 && (argv[1][0] == '-')) {
		if (exp_flageq("info",&argv[1][1],4)) {
			return(expect_info(interp,ecmd,argc-2,argv+2));
		} 
	}

	exp_cmd_init(&eg,ecmd->cmdtype,EXP_PERMANENT);

	if (TCL_ERROR == parse_expect_args(interp,&eg,EXP_SPAWN_ID_BAD,
					argc,argv)) {
		return TCL_ERROR;
	}

	/*
	 * visit each NEW direct exp_i looking for spawn ids.
	 * When found, remove them from any OLD exp_i's.
	 */

	/* visit each exp_i */
	for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
		if (exp_i->direct == EXP_INDIRECT) continue;

		/* for each spawn id, remove it from ecases */
		for (fdl=exp_i->fd_list;fdl;fdl=fdl->next) {
			int m = fdl->fd;

			/* validate all input descriptors */
			if (m != EXP_SPAWN_ID_ANY) {
				if (!exp_fd2f(interp,m,1,1,"expect")) {
					result = TCL_ERROR;
					goto cleanup;
				}
			}

			/* remove spawn id from exp_i */
			ecmd_remove_fd(interp,ecmd,m,EXP_DIRECT);
		}
	}
	
	/*
	 * For each indirect variable, release its old ecases and 
	 * clean up the matching spawn ids.
	 * Same logic as in "expect_X delete" command.
	 */

	for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
		struct exp_i **old_i;

		if (exp_i->direct == EXP_DIRECT) continue;

		for (old_i = &ecmd->i_list;*old_i;) {
			struct exp_i *tmp;

			if (((*old_i)->direct == EXP_DIRECT) ||
			    (!streq((*old_i)->variable,exp_i->variable))) {
				old_i = &(*old_i)->next;
				continue;
			}

			ecases_remove_by_expi(interp,ecmd,*old_i);

			/* unlink from middle of list */
			tmp = *old_i;
			*old_i = tmp->next;
			tmp->next = 0;
			exp_free_i(interp,tmp,exp_indirect_update2);
		}

		/* if new one has ecases, update it */
		if (exp_i->ecount) {
			char *msg = exp_indirect_update1(interp,ecmd,exp_i);
			if (msg) {
				/* unusual way of handling error return */
				/* because of Tcl's variable tracing */
				strcpy(interp->result,msg);
				result = TCL_ERROR;
				goto indirect_update_abort;
			}
		}
	}
	/* empty i_lists have to be removed from global eg.i_list */
	/* before returning, even if during error */
 indirect_update_abort:

	/*
	 * New exp_i's that have 0 ecases indicate fd/vars to be deleted.
	 * Now that the deletions have been done, discard the new exp_i's.
	 */

	for (exp_i=eg.i_list;exp_i;) {
		struct exp_i *next = exp_i->next;

		if (exp_i->ecount == 0) {
			exp_i_remove(interp,&eg.i_list,exp_i);
		}
		exp_i = next;
	}
	if (result == TCL_ERROR) goto cleanup;

	/*
	 * arm all new bg direct fds
	 */

	if (ecmd->cmdtype == EXP_CMD_BG) {
		for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
			if (exp_i->direct == EXP_DIRECT) {
				fd_list_arm(interp,exp_i->fd_list);
			}
		}
	}

	/*
	 * now that old ecases are gone, add new ecases and exp_i's (both
	 * direct and indirect).
	 */

	/* append ecases */

	count = ecmd->ecd.count + eg.ecd.count;
	if (eg.ecd.count) {
		int start_index; /* where to add new ecases in old list */

		if (ecmd->ecd.count) {
			/* append to end */
			ecmd->ecd.cases = (struct ecase **)ckrealloc((char *)ecmd->ecd.cases, count * sizeof(struct ecase *));
			start_index = ecmd->ecd.count;
		} else {
			/* append to beginning */
			ecmd->ecd.cases = (struct ecase **)ckalloc(eg.ecd.count * sizeof(struct ecase *));
			start_index = 0;
		}
		memcpy(&ecmd->ecd.cases[start_index],eg.ecd.cases,
					eg.ecd.count*sizeof(struct ecase *));
		ecmd->ecd.count = count;
	}

	/* append exp_i's */
	for (eip = &ecmd->i_list;*eip;eip = &(*eip)->next) {
		/* empty loop to get to end of list */
	}
	/* *exp_i now points to end of list */

	*eip = eg.i_list;	/* connect new list to end of current list */

 cleanup:
	if (result == TCL_ERROR) {
		/* in event of error, free any unreferenced ecases */
		/* but first, split up i_list so that exp_i's aren't */
		/* freed twice */

		for (exp_i=eg.i_list;exp_i;) {
			struct exp_i *next = exp_i->next;
			exp_i->next = 0;
			exp_i = next;
		}
		free_ecases(interp,&eg,1);
	} else {
		if (eg.ecd.cases) ckfree((char *)eg.ecd.cases);
	}

	if (ecmd->cmdtype == EXP_CMD_BG) {
		exp_background_filehandlers_run_all();
	}

	return(result);
}

/* adjusts file according to user's size request */
void
exp_adjust(f)
struct exp_f *f;
{
	int new_msize;
























































	/* get the latest buffer size.  Double the user input for */
	/* two reasons.  1) Need twice the space in case the match */
	/* straddles two bufferfuls, 2) easier to hack the division */
	/* by two when shifting the buffers later on.  The extra  */
	/* byte in the malloc's is just space for a null we can slam on the */


	/* end.  It makes the logic easier later.  The -1 here is so that */








	/* requests actually come out to even/word boundaries (if user */

	/* gives "reasonable" requests) */

	new_msize = f->umsize*2 - 1;



	if (new_msize != f->msize) {
		if (!f->buffer) {







			/* allocate buffer space for 1st time */











			f->buffer = ckalloc((unsigned)new_msize+1);

			f->lower = ckalloc((unsigned)new_msize+1);
			f->size = 0;
		} else {




			/* buffer already exists - resize */







			/* if truncated, forget about some data */



			if (f->size > new_msize) {










				/* copy end of buffer down */








				memmove(f->buffer,f->buffer+(f->size - new_msize),new_msize);










				memmove(f->lower, f->lower +(f->size - new_msize),new_msize);

				f->size = new_msize;






				f->key = expect_key++;


			}















			f->buffer = ckrealloc(f->buffer,new_msize+1);



			f->lower = ckrealloc(f->lower,new_msize+1);


		}

		f->msize = new_msize;








		f->buffer[f->size] = '\0';



		f->lower[f->size] = '\0';


	}









}








/*

 expect_read() does the logical equivalent of a read() for the
expect command.  This includes figuring out which descriptor should
be read from.

The result of the read() is left in a spawn_id's buffer rather than
explicitly passing it back.  Note that if someone else has modified a
buffer either before or while this expect is running (i.e., if we or
some event has called Tcl_Eval which did another expect/interact),
expect_read will also call this a successful read (for the purposes if
needing to pattern match against it).

*/

/* if it returns a negative number, it corresponds to a EXP_XXX result */
/* if it returns a non-negative number, it means there is data */
/* (0 means nothing new was actually read, but it should be looked at again) */
int
expect_read(interp,masters,masters_max,m,timeout,key)
Tcl_Interp *interp;
int *masters;			/* If 0, then m is already known and set. */
int masters_max;		/* If *masters is not-zero, then masters_max */
				/* is the number of masters. */
				/* If *masters is zero, then masters_max */
				/* is used as the mask (ready vs except). */
				/* Crude but simplifies the interface. */
int *m;				/* Out variable to leave new master. */
int timeout;
int key;
{

	struct exp_f *f;

	int cc;
	int write_count;
	int tcl_set_flags;	/* if we have to discard chars, this tells */
				/* whether to show user locally or globally */

	if (masters == 0) {
		/* we already know the master, just find out what happened */
		cc = exp_get_next_event_info(interp,*m,masters_max);
		tcl_set_flags = TCL_GLOBAL_ONLY;
	} else {
		cc = exp_get_next_event(interp,masters,masters_max,m,timeout,key);
		tcl_set_flags = 0;
	}


	if (cc == EXP_DATA_NEW) {
		/* try to read it */

		cc = exp_i_read(interp,*m,timeout,tcl_set_flags);

		/* the meaning of 0 from i_read means eof.  Muck with it a */
		/* little, so that from now on it means "no new data arrived */
		/* but it should be looked at again anyway". */
		if (cc == 0) {
			cc = EXP_EOF;
		} else if (cc > 0) {
			f = exp_fs + *m;
			f->buffer[f->size += cc] = '\0';

			/* strip parity if requested */
			if (f->parity == 0) {
				/* do it from end backwards */
				char *p = f->buffer + f->size - 1;
				int count = cc;
				while (count--) {
					*p-- &= 0x7f;
				}
			}
		} /* else {
			assert(cc < 0) in which case some sort of error was
			encountered such as an interrupt with that forced an
			error return
		} */

	} else if (cc == EXP_DATA_OLD) {
		f = exp_fs + *m;
		cc = 0;
	} else if (cc == EXP_RECONFIGURE) {
		return EXP_RECONFIGURE;
	}

	if (cc == EXP_ABEOF) {	/* abnormal EOF */
		/* On many systems, ptys produce EIO upon EOF - sigh */
		if (i_read_errno == EIO) {
			/* Sun, Cray, BSD, and others */
			cc = EXP_EOF;
		} else if (i_read_errno == EINVAL) {
			/* Solaris 2.4 occasionally returns this */
			cc = EXP_EOF;
		} else {
			if (i_read_errno == EBADF) {
				exp_error(interp,"bad spawn_id (process died earlier?)");
			} else {
				exp_error(interp,"i_read(spawn_id=%d): %s",*m,
					Tcl_PosixError(interp));
				exp_close(interp,*m);
			}
			return(EXP_TCLERROR);
			/* was goto error; */
		}
	}

	/* EOF, TIMEOUT, and ERROR return here */
	/* In such cases, there is no need to update screen since, if there */
	/* was prior data read, it would have been sent to the screen when */
	/* it was read. */
	if (cc < 0) return (cc);


	/* update display */



	if (f->size) write_count = f->size - f->printed;
	else write_count = 0;

	if (write_count) {
		if (logfile_all || (loguser && logfile)) {
			fwrite(f->buffer + f->printed,1,write_count,logfile);
		}

		/* don't write to user if they're seeing it already, */
		/* that is, typing it! */
		if (loguser && !exp_is_stdinfd(*m) && !exp_is_devttyfd(*m))
			fwrite(f->buffer + f->printed,
					1,write_count,stdout);

		if (debugfile) fwrite(f->buffer + f->printed,
					1,write_count,debugfile);


		/* remove nulls from input, since there is no way */
		/* for Tcl to deal with such strings.  Doing it here */
		/* lets them be sent to the screen, just in case */
		/* they are involved in formatting operations */
		if (f->rm_nulls) {
			f->size -= rm_nulls(f->buffer + f->printed,write_count);
		}
		f->buffer[f->size] = '\0';

		/* copy to lowercase buffer */
		exp_lowmemcpy(f->lower+f->printed,
			      f->buffer+f->printed,
					1 + f->size - f->printed);

		f->printed = f->size; /* count'm even if not logging */
	}
	return(cc);
}

/* when buffer fills, copy second half over first and */
/* continue, so we can do matches over multiple buffers */
void
exp_buffer_shuffle(interp,f,save_flags,array_name,caller_name)
Tcl_Interp *interp;
struct exp_f *f;
int save_flags;
char *array_name;
char *caller_name;
{
	char spawn_id[10];	/* enough for a %d */
	char match_char;	/* place to hold char temporarily */
				/* uprooted by a NULL */

	int first_half = f->size/2;
	int second_half = f->size - first_half;

	/*
	 * allow user to see data we are discarding
	 */

	sprintf(spawn_id,"%d",f-exp_fs);
	debuglog("%s: set %s(spawn_id) \"%s\"\r\n",
		 caller_name,array_name,dprintify(spawn_id));
	Tcl_SetVar2(interp,array_name,"spawn_id",spawn_id,save_flags);








	/* temporarily null-terminate buffer in middle */



	match_char = f->buffer[first_half];

	f->buffer[first_half] = 0;





















	debuglog("%s: set %s(buffer) \"%s\"\r\n",
		 caller_name,array_name,dprintify(f->buffer));


	Tcl_SetVar2(interp,array_name,"buffer",f->buffer,save_flags);



	/* remove middle-null-terminator */

	f->buffer[first_half] = match_char;




	memcpy(f->buffer,f->buffer+first_half,second_half);


	memcpy(f->lower, f->lower +first_half,second_half);

	f->size = second_half;
	f->printed -= first_half;
	if (f->printed < 0) f->printed = 0;
}

/* map EXP_ style return value to TCL_ style return value */
/* not defined to work on TCL_OK */
int
exp_tcl2_returnvalue(x)
int x;







|


|


|

|



|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|


|
<
>

|
|
|
|
|
>
|
>
>

>
>
>
>
>
|
|
>
>
>
>
>
|
>
|
|
>
>
>
>
>
|
|
<
>
|
<
<
<
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|


|


|


|
|

|
|
|
|
|

|

|
|
|
|
|
|
|
|

|
|
|
|
|

|

|
|
|
|

|
|
|
|

|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|

|

|
|

|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|

|
|

|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|

|
|
|
|

|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|

|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|

|




|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
|
|
>
>
|
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
|
<
|
>
>
>
>
|
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>


<
|
|
<
|
|
|
|
|
|
<
|
|
>




|

|
<
|
<
<
<
|



>
|
>
|
|
|
|

|
|
|
|
|
|
|
|
>

|
|
<
|
|
|
|
|
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
|
|
|
<
|
>
|
<
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

>
|
>

>
|
|
|
|
<
<
<
>
|
|
<
|
<
>
|
<
|
>
|
<
|
|
<
<
<
<
|
<
<
<
<
|
|
|
|





|

|




|
|
|
|
|
|

|
|
|

<
|
|
|

>
>
>
>
>
>
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
|
>
>
|
>

>
|
>
|

>
>
>
|
>
>
|
>
|
|
|







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171












































































1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212

1213
1214



1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513



1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558

1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679

1680
1681

1682
1683
1684
1685
1686
1687

1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

1698



1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1730


1731









1732
1733
1734

1735
1736
1737

1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778



1779
1780
1781

1782

1783
1784

1785
1786
1787

1788
1789




1790




1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817

1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
Tcl_Interp *interp;
struct exp_i *exp_i;
{
	Tcl_AppendElement(interp,"-i");
	if (exp_i->direct == EXP_INDIRECT) {
		Tcl_AppendElement(interp,exp_i->variable);
	} else {
		struct exp_state_list *fdp;

		/* if more than one element, add braces */
		if (exp_i->state_list->next)
			Tcl_AppendResult(interp," {",(char *)0);

		for (fdp = exp_i->state_list;fdp;fdp=fdp->next) {
			char buf[10];	/* big enough for a small int */
			sprintf(buf,"%d",fdp->esPtr);
			Tcl_AppendElement(interp,buf);
		}

		if (exp_i->state_list->next)
			Tcl_AppendResult(interp,"} ",(char *)0);
	}
}













































































/* return current setting of the permanent expect_before/after/bg */
int
expect_info(interp,ecmd,objc,objv)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
int objc;

Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    struct exp_i *exp_i;
    int i;
    int direct = EXP_DIRECT|EXP_INDIRECT;
    char *iflag = 0;
    int all = FALSE;	/* report on all fds */
    ExpState *esPtr = 0;

    static char *flags[] = {"-i", "-all", "-noindirect", (char *)0};
    enum flags {EXP_ARG_I, EXP_ARG_ALL, EXP_ARG_NOINDIRECT};

    /* start with 2 to skip over "cmdname -info" */
    for (i = 2;i<objc;i++) {
	/*
	 * Allow abbreviations of switches and report an error if we
	 * get an invalid switch.
	 */

	int index;
	if (Tcl_GetIndexFromObj(interp, objv[i], flags, "flag", 0,
				&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch ((enum flags) index) {
	case EXP_ARG_I:
	    i++;
	    if (i >= objc) {
		Tcl_WrongNumArgs(interp, 1, objv,"-i spawn_id");
		return TCL_ERROR;
	    }
	    break;
	case EXP_ARG_ALL:
	    all = TRUE;
	    break;

	case EXP_ARG_NOINDIRECT:
	    direct &= ~EXP_INDIRECT;



	    break;
	}
    }

    if (all) {
	/* avoid printing out -i when redundant */
	struct exp_i *previous = 0;

	for (i=0;i<ecmd->ecd.count;i++) {
	    if (previous != ecmd->ecd.cases[i]->i_list) {
		exp_i_append(interp,ecmd->ecd.cases[i]->i_list);
		previous = ecmd->ecd.cases[i]->i_list;
	    }
	    ecase_append(interp,ecmd->ecd.cases[i]);
	}
	return TCL_OK;
    }

    if (!iflag) {
	if (!(esPtr = expStateCurrent(interp,0,0,0))) {
	    return TCL_ERROR;
	}
    } else if (!(esPtr = expStateFromChannelName(interp,iflag,0,0,0,"dummy"))) {
	/* not a valid ExpState so assume it is an indirect variable */
	Tcl_ResetResult(interp);
	for (i=0;i<ecmd->ecd.count;i++) {
	    if (ecmd->ecd.cases[i]->i_list->direct == EXP_INDIRECT &&
		    streq(ecmd->ecd.cases[i]->i_list->variable,iflag)) {
		ecase_append(interp,ecmd->ecd.cases[i]);
	    }
	}
	return TCL_OK;
    }
    
    /* print ecases of this direct_fd */
    for (exp_i=ecmd->i_list;exp_i;exp_i=exp_i->next) {
	if (!(direct & exp_i->direct)) continue;
	if (!exp_i_uses_state(exp_i,esPtr)) continue;
	ecase_by_exp_i_append(interp,ecmd,exp_i);
    }

    return TCL_OK;
}

/* Exp_ExpectGlobalObjCmd is invoked to process expect_before/after/background */
/*ARGSUSED*/
int
Exp_ExpectGlobalObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int result = TCL_OK;
    struct exp_i *exp_i, **eip;
    struct exp_state_list *slPtr;   /* temp for interating over state_list */
    struct exp_cmd_descriptor eg;
    int count;

    struct exp_cmd_descriptor *ecmd = (struct exp_cmd_descriptor *) clientData;

    if ((objc == 2) && exp_one_arg_braced(objv[1])) {
	return(exp_eval_with_one_arg(clientData,interp,objv));
    } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) {
	Tcl_Obj *new_objv[2];
	new_objv[0] = objv[0];
	new_objv[1] = objv[2];
	return(exp_eval_with_one_arg(clientData,interp,new_objv));
    }

    if (objc > 1 && (Tcl_GetString(objv[1])[0] == '-')) {
	if (exp_flageq("info",Tcl_GetString(objv[1])+1,4)) {
	    return(expect_info(interp,ecmd,objc,objv));
	} 
    }

    exp_cmd_init(&eg,ecmd->cmdtype,EXP_PERMANENT);

    if (TCL_ERROR == parse_expect_args(interp,&eg,EXP_SPAWN_ID_BAD,
	    objc,objv)) {
	return TCL_ERROR;
    }

    /*
     * visit each NEW direct exp_i looking for spawn ids.
     * When found, remove them from any OLD exp_i's.
     */

    /* visit each exp_i */
    for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
	if (exp_i->direct == EXP_INDIRECT) continue;

	/* for each spawn id, remove it from ecases */
	for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) {
	    ExpState *esPtr = slPtr->esPtr;

	    /* validate all input descriptors */
	    if (!expStateAnyIs(esPtr)) {
		if (!expStateCheck(interp,esPtr,1,1,"expect")) {
		    result = TCL_ERROR;
		    goto cleanup;
		}
	    }
	    
	    /* remove spawn id from exp_i */
	    ecmd_remove_state(interp,ecmd,esPtr,EXP_DIRECT);
	}
    }
	
    /*
     * For each indirect variable, release its old ecases and 
     * clean up the matching spawn ids.
     * Same logic as in "expect_X delete" command.
     */

    for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
	struct exp_i **old_i;

	if (exp_i->direct == EXP_DIRECT) continue;

	for (old_i = &ecmd->i_list;*old_i;) {
	    struct exp_i *tmp;

	    if (((*old_i)->direct == EXP_DIRECT) ||
		    (!streq((*old_i)->variable,exp_i->variable))) {
		old_i = &(*old_i)->next;
		continue;
	    }

	    ecases_remove_by_expi(interp,ecmd,*old_i);
	    
	    /* unlink from middle of list */
	    tmp = *old_i;
	    *old_i = tmp->next;
	    tmp->next = 0;
	    exp_free_i(interp,tmp,exp_indirect_update2);
	}

	/* if new one has ecases, update it */
	if (exp_i->ecount) {
	    char *msg = exp_indirect_update1(interp,ecmd,exp_i);
	    if (msg) {
		/* unusual way of handling error return */
		/* because of Tcl's variable tracing */
		strcpy(interp->result,msg);
		result = TCL_ERROR;
		goto indirect_update_abort;
	    }
	}
    }
    /* empty i_lists have to be removed from global eg.i_list */
    /* before returning, even if during error */
 indirect_update_abort:

    /*
     * New exp_i's that have 0 ecases indicate fd/vars to be deleted.
     * Now that the deletions have been done, discard the new exp_i's.
     */

    for (exp_i=eg.i_list;exp_i;) {
	struct exp_i *next = exp_i->next;

	if (exp_i->ecount == 0) {
	    exp_i_remove(interp,&eg.i_list,exp_i);
	}
	exp_i = next;
    }
    if (result == TCL_ERROR) goto cleanup;

    /*
     * arm all new bg direct fds
     */

    if (ecmd->cmdtype == EXP_CMD_BG) {
	for (exp_i=eg.i_list;exp_i;exp_i=exp_i->next) {
	    if (exp_i->direct == EXP_DIRECT) {
		state_list_arm(interp,exp_i->state_list);
	    }
	}
    }

    /*
     * now that old ecases are gone, add new ecases and exp_i's (both
     * direct and indirect).
     */

    /* append ecases */

    count = ecmd->ecd.count + eg.ecd.count;
    if (eg.ecd.count) {
	int start_index; /* where to add new ecases in old list */

	if (ecmd->ecd.count) {
	    /* append to end */
	    ecmd->ecd.cases = (struct ecase **)ckrealloc((char *)ecmd->ecd.cases, count * sizeof(struct ecase *));
	    start_index = ecmd->ecd.count;
	} else {
	    /* append to beginning */
	    ecmd->ecd.cases = (struct ecase **)ckalloc(eg.ecd.count * sizeof(struct ecase *));
	    start_index = 0;
	}
	memcpy(&ecmd->ecd.cases[start_index],eg.ecd.cases,
		eg.ecd.count*sizeof(struct ecase *));
	ecmd->ecd.count = count;
    }

    /* append exp_i's */
    for (eip = &ecmd->i_list;*eip;eip = &(*eip)->next) {
	/* empty loop to get to end of list */
    }
    /* *exp_i now points to end of list */

    *eip = eg.i_list;	/* connect new list to end of current list */

  cleanup:
    if (result == TCL_ERROR) {
	/* in event of error, free any unreferenced ecases */
	/* but first, split up i_list so that exp_i's aren't */
	/* freed twice */

	for (exp_i=eg.i_list;exp_i;) {
	    struct exp_i *next = exp_i->next;
	    exp_i->next = 0;
	    exp_i = next;
	}
	free_ecases(interp,&eg,1);
    } else {
	if (eg.ecd.cases) ckfree((char *)eg.ecd.cases);
    }

    if (ecmd->cmdtype == EXP_CMD_BG) {
	exp_background_channelhandlers_run_all();
    }

    return(result);
}

/* adjusts file according to user's size request */
void
expAdjust(esPtr)
ExpState *esPtr;
{
    int new_msize;
    int length;
    Tcl_Obj *newObj;
    char *string;
    int excessBytes;
    char *excessGuess;
    char *p;

    /*
     * Resize buffer to user's request * 2 + 1.
     * x2: in case the match straddles two bufferfuls.
     * +1: for trailing null.
     */

    new_msize = esPtr->umsize*2 + 1;

    if (new_msize != esPtr->msize) {
	string = Tcl_GetStringFromObj(esPtr->buffer, &length);
	if (length > new_msize) {
	    /*
	     * too much data, forget about data at beginning of buffer
	     */

	    excessBytes = length - new_msize;	/* initial guess */

	    /*
	     * Alas, string + excessBytes may be in the middle of a UTF char.
	     * Find out for sure.
	     */
	    excessGuess = string + excessBytes;
	    for (p=string;;p=Tcl_UtfNext(p)) {
		if (p >= excessGuess) break;
	    }

	    /* now we can calculate a valid # of excess bytes */
	    excessBytes = p - string;
	    newObj = Tcl_NewStringObj(string + excessBytes,length - excessBytes);
	} else {
	    /*
	     * too little data
	     */

	    /* first copy what's there */
	    newObj = Tcl_NewStringObj(string,length);

	    /*
	     * Force object to allocate a buffer at least new_msize bytes long,
	     * then reset correct string length.
	     */

	    Tcl_SetObjLength(newObj,new_msize);
	    Tcl_SetObjLength(newObj,length);
	}
	Tcl_IncrRefCount(newObj);
	Tcl_DecrRefCount(esPtr->buffer);
	esPtr->buffer = newObj;




	esPtr->key = expect_key++;
	esPtr->msize = new_msize;
    }
}

#if OBSOLETE
/* Strip parity */
static void
expParityStrip(obj,offsetBytes)
    Tcl_Obj *obj;
    int offsetBytes;
{
    char *p, ch;
    
    int changed = FALSE;
    
    for (p = Tcl_GetString(obj) + offsetBytes;*p;p++) {
	ch = *p & 0x7f;
	if (ch != *p) changed = TRUE;
	else *p &= 0x7f;
    }

    if (changed) {
	/* invalidate the unicode rep */
	if (obj->typePtr->freeIntRepProc) {
	    obj->typePtr->freeIntRepProc(obj);
	}
    }
}
#endif /*OBSOLETE*/

/* This function is only used when debugging.  It checks when a string's
   internal UTF is sane and whether an offset into the string appears to
   be at a UTF boundary.
*/
static void
expValid(obj,offset)
     Tcl_Obj *obj;
     int offset;
{
  char *s, *end;
  int len;

  s = Tcl_GetStringFromObj(obj,&len);


  if (offset > len) {
    printf("offset (%d) > length (%d)\n",offset,len);
    fflush(stdout);
    abort();
  }

  /* first test for null terminator */
  end = s + len;
  if (*end != '\0') {
    printf("obj lacks null terminator\n");
    fflush(stdout);
    abort();
  }

  /* check for valid UTF sequence */
  while (*s) {
    Tcl_UniChar uc;

    s += Tcl_UtfToUniChar(s,&uc);
    if (s > end) {
      printf("UTF out of sync with terminator\n");
      fflush(stdout);
      abort();
    }
  }
  s += offset;
  while (*s) {
    Tcl_UniChar uc;

    s += Tcl_UtfToUniChar(s,&uc);
    if (s > end) {
      printf("UTF from offset out of sync with terminator\n");
      fflush(stdout);
      abort();
    }
  }
}

/* Strip UTF-encoded nulls from object, beginning at offset */
static int
expNullStrip(obj,offsetBytes)
    Tcl_Obj *obj;
    int offsetBytes;
{
    char *src, *src2;
    char *dest;
    Tcl_UniChar uc;
    int newsize;       /* size of obj after all nulls removed */

    src2 = src = dest = Tcl_GetString(obj) + offsetBytes;

    while (*src) {
	src += Tcl_UtfToUniChar(src,&uc);
	if (uc != 0) {
	    dest += Tcl_UniCharToUtf(uc,dest);
	}
    }
    newsize = offsetBytes + (dest - src2);
    Tcl_SetObjLength(obj,newsize);
    return newsize;
}

/* returns # of bytes read or (non-positive) error of form EXP_XXX */
/* returns 0 for end of file */
/* If timeout is non-zero, set an alarm before doing the read, else assume */
/* the read will complete immediately. */
/*ARGSUSED*/
static int
expIRead(interp,esPtr,timeout,save_flags) /* INTL */
Tcl_Interp *interp;
ExpState *esPtr;
int timeout;
int save_flags;
{
    int cc = EXP_TIMEOUT;
    int size = expSizeGet(esPtr);

    if (size + TCL_UTF_MAX >= esPtr->msize) 
	exp_buffer_shuffle(interp,esPtr,save_flags,EXPECT_OUT,"expect");
    size = expSizeGet(esPtr);

#ifdef SIMPLE_EVENT
 restart:

    alarm_fired = FALSE;

    if (timeout > -1) {
	signal(SIGALRM,sigalarm_handler);
	alarm((timeout > 0)?timeout:1);
    }
#endif

    
    cc = Tcl_ReadChars(esPtr->channel,
	    esPtr->buffer,
	    esPtr->msize - (size / TCL_UTF_MAX),
	    1 /* append */);
    i_read_errno = errno;

#ifdef SIMPLE_EVENT
    alarm(0);

    if (cc == -1) {
	/* check if alarm went off */
	if (i_read_errno == EINTR) {
	    if (alarm_fired) {
		return EXP_TIMEOUT;
	    } else {
		if (Tcl_AsyncReady()) {
		    int rc = Tcl_AsyncInvoke(interp,TCL_OK);
		    if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
		}
		goto restart;
	    }
	}
    }
#endif
    return cc;	
}

/*

 * expRead() does the logical equivalent of a read() for the expect command.
 * This includes figuring out which descriptor should be read from.

 *
 * The result of the read() is left in a spawn_id's buffer rather than
 * explicitly passing it back.  Note that if someone else has modified a buffer
 * either before or while this expect is running (i.e., if we or some event has
 * called Tcl_Eval which did another expect/interact), expRead will also call
 * this a successful read (for the purposes if needing to pattern match against

 * it).
 */

/* if it returns a negative number, it corresponds to a EXP_XXX result */
/* if it returns a non-negative number, it means there is data */
/* (0 means nothing new was actually read, but it should be looked at again) */
int
expRead(interp,esPtrs,esPtrsMax,esPtrOut,timeout,key)
Tcl_Interp *interp;
ExpState *(esPtrs[]);		/* If 0, then esPtrOut already known and set */

int esPtrsMax;			/* number of esPtrs */



ExpState **esPtrOut;		/* Out variable to leave new ExpState. */
int timeout;
int key;
{
    ExpState *esPtr;

    int size;
    int cc;
    int write_count;
    int tcl_set_flags;	/* if we have to discard chars, this tells */
			/* whether to show user locally or globally */

    if (esPtrs == 0) {
	/* we already know the ExpState, just find out what happened */
	cc = exp_get_next_event_info(interp,*esPtrOut);
	tcl_set_flags = TCL_GLOBAL_ONLY;
    } else {
	cc = exp_get_next_event(interp,esPtrs,esPtrsMax,esPtrOut,timeout,key);
	tcl_set_flags = 0;
    }
    esPtr = *esPtrOut;

    if (cc == EXP_DATA_NEW) {
	/* try to read it */

	cc = expIRead(interp,esPtr,timeout,tcl_set_flags);
	
	/* the meaning of 0 from i_read means eof.  Muck with it a */
	/* little, so that from now on it means "no new data arrived */
	/* but it should be looked at again anyway". */
	if (cc == 0) {
	    cc = EXP_EOF;
	} else if (cc > 0) {


	    /* successfully read data */









	} else {
	    /* failed to read data - some sort of error was encountered such as
	     * an interrupt with that forced an error return

	     */
	}
    } else if (cc == EXP_DATA_OLD) {

	cc = 0;
    } else if (cc == EXP_RECONFIGURE) {
	return EXP_RECONFIGURE;
    }

    if (cc == EXP_ABEOF) {	/* abnormal EOF */
	/* On many systems, ptys produce EIO upon EOF - sigh */
	if (i_read_errno == EIO) {
	    /* Sun, Cray, BSD, and others */
	    cc = EXP_EOF;
	} else if (i_read_errno == EINVAL) {
	    /* Solaris 2.4 occasionally returns this */
	    cc = EXP_EOF;
	} else {
	    if (i_read_errno == EBADF) {
		exp_error(interp,"bad spawn_id (process died earlier?)");
	    } else {
		exp_error(interp,"i_read(spawn_id fd=%d): %s",esPtr->fdin,
			Tcl_PosixError(interp));
		exp_close(interp,esPtr);
	    }
	    return(EXP_TCLERROR);
	    /* was goto error; */
	}
    }

    /* EOF, TIMEOUT, and ERROR return here */
    /* In such cases, there is no need to update screen since, if there */
    /* was prior data read, it would have been sent to the screen when */
    /* it was read. */
    if (cc < 0) return (cc);

    /*
     * update display
     */

    size = expSizeGet(esPtr);
    if (size) write_count = size - esPtr->printed;
    else write_count = 0;
    
    if (write_count) {



	/*
	 * Show chars to user if they've requested it, UNLESS they're seeing it
	 * already because they're typing it and tty driver is echoing it.

	 * Also send to Diag and Log if appropriate.

	 */
	expLogInteractionU(esPtr,Tcl_GetString(esPtr->buffer) + esPtr->printed);

	    
	/*
	 * strip nulls from input, since there is no way for Tcl to deal with

	 * such strings.  Doing it here lets them be sent to the screen, just
	 * in case they are involved in formatting operations




	 */




	if (esPtr->rm_nulls) size = expNullStrip(esPtr->buffer,esPtr->printed);
	esPtr->printed = size; /* count'm even if not logging */
    }
    return(cc);
}

/* when buffer fills, copy second half over first and */
/* continue, so we can do matches over multiple buffers */
void
exp_buffer_shuffle(interp,esPtr,save_flags,array_name,caller_name) /* INTL */
Tcl_Interp *interp;
ExpState *esPtr;
int save_flags;
char *array_name;
char *caller_name;
{
    char *str;
    char *middleGuess;
    char *p;
    int length, newlen;
    int skiplen;
    char lostByte;

    /*
     * allow user to see data we are discarding
     */


    expDiagLog("%s: set %s(spawn_id) \"%s\"\r\n",
	    caller_name,array_name,esPtr->name);
    Tcl_SetVar2(interp,array_name,"spawn_id",esPtr->name,save_flags);

    /*
     * The internal storage buffer object should only be referred
     * to by the channel that uses it.  We always copy the contents
     * out of the object before passing the data to anyone outside
     * of these routines.  This ensures that the object always has
     * a refcount of 1 so we can safely modify the contents in place.
     */

    if (Tcl_IsShared(esPtr->buffer)) {
	panic("exp_buffer_shuffle called with shared buffer object");
    }

    str = Tcl_GetStringFromObj(esPtr->buffer,&length);

    /* guess at the middle */
    middleGuess = str + length/2;

    /* crawl our way into the middle of the string
     * to make sure we are at a UTF char boundary
     */
    for (p=str;*p;p = Tcl_UtfNext(p)) {
	if (p > middleGuess) break;   /* ok, that's enough */
    }

    /*
     * p is now at the beginning of a UTF char in the middle of the string
     */

    /*
     * before doing move, show user data we are discarding
     */
    skiplen = p-str;
    lostByte = *p;
    /* temporarily stick null in middle of string */
    Tcl_SetObjLength(esPtr->buffer,skiplen);

    expDiagLog("%s: set %s(buffer) \"",caller_name,array_name);
    expDiagLogU(expPrintify(Tcl_GetString(esPtr->buffer)));
    expDiagLogU("\"\r\n");
    Tcl_SetVar2(interp,array_name,"buffer",Tcl_GetString(esPtr->buffer),
	    save_flags);

    /*
     * restore damage
     */
    *p = lostByte;

    /*
     * move 2nd half of string down to 1st half
     */

    newlen = length - skiplen;
    memmove(str,p, newlen);

    Tcl_SetObjLength(esPtr->buffer,newlen);

    esPtr->printed -= skiplen;
    if (esPtr->printed < 0) esPtr->printed = 0;
}

/* map EXP_ style return value to TCL_ style return value */
/* not defined to work on TCL_OK */
int
exp_tcl2_returnvalue(x)
int x;
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
	case EXP_TCLCNT:		return TCL_CONTINUE;
	case EXP_TCLCNTEXP:		return EXP_CONTINUE;
	case EXP_TCLCNTTIMER:		return EXP_CONTINUE_TIMER;
	case EXP_TCLRETTCL:		return EXP_TCL_RETURN;
	}
}

/* returns # of chars read or (non-positive) error of form EXP_XXX */
/* returns 0 for end of file */
/* If timeout is non-zero, set an alarm before doing the read, else assume */
/* the read will complete immediately. */
/*ARGSUSED*/
static int
exp_i_read(interp,m,timeout,save_flags)
Tcl_Interp *interp;
int m;
int timeout;
int save_flags;
{
	struct exp_f *f;
	int cc = EXP_TIMEOUT;

	f = exp_fs + m;
	if (f->size == f->msize) 
		exp_buffer_shuffle(interp,f,save_flags,EXPECT_OUT,"expect");

#ifdef SIMPLE_EVENT
 restart:

	alarm_fired = FALSE;

	if (timeout > -1) {
		signal(SIGALRM,sigalarm_handler);
		alarm((timeout > 0)?timeout:1);
	}
#endif

	cc = read(m,f->buffer+f->size, f->msize-f->size);
	i_read_errno = errno;

#ifdef SIMPLE_EVENT
	alarm(0);

	if (cc == -1) {
		/* check if alarm went off */
		if (i_read_errno == EINTR) {
			if (alarm_fired) {
				return EXP_TIMEOUT;
			} else {
				if (Tcl_AsyncReady()) {
					int rc = Tcl_AsyncInvoke(interp,TCL_OK);
					if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
				}
				if (!f->valid) {
					exp_error(interp,"spawn_id %d no longer valid",f-exp_fs);
					return EXP_TCLERROR;
				}
				goto restart;
			}
		}
	}
#endif
	return(cc);
}

/* variables predefined by expect are retrieved using this routine
which looks in the global space if they are not in the local space.
This allows the user to localize them if desired, and also to
avoid having to put "global" in procedure definitions.
*/
char *
exp_get_var(interp,var)
Tcl_Interp *interp;
char *var;
{
	char *val;

	if (NULL != (val = Tcl_GetVar(interp,var,0 /* local */)))
		return(val);
	return(Tcl_GetVar(interp,var,TCL_GLOBAL_ONLY));
}

static int
get_timeout(interp)
Tcl_Interp *interp;
{
	static int timeout = INIT_EXPECT_TIMEOUT;
 	char *t;

	if (NULL != (t = exp_get_var(interp,EXPECT_TIMEOUT))) {
		timeout = atoi(t);
	}
	return(timeout);
}

/* make a copy of a linked list (1st arg) and attach to end of another (2nd
arg) */
static int
update_expect_fds(i_list,fd_union)
struct exp_i *i_list;
struct exp_fd_list **fd_union;
{
	struct exp_i *p;

	/* for each i_list in an expect statement ... */
	for (p=i_list;p;p=p->next) {
		struct exp_fd_list *fdl;

		/* for each fd in the i_list */
		for (fdl=p->fd_list;fdl;fdl=fdl->next) {
			struct exp_fd_list *tmpfdl;
			struct exp_fd_list *u;

			if (fdl->fd == EXP_SPAWN_ID_ANY) continue;

			/* check this one against all so far */
			for (u = *fd_union;u;u=u->next) {
				if (fdl->fd == u->fd) goto found;
			}
			/* if not found, link in as head of list */
			tmpfdl = exp_new_fd(fdl->fd);
			tmpfdl->next = *fd_union;
			*fd_union = tmpfdl;
		found:;
		}
	}
	return TCL_OK;
}

char *
exp_cmdtype_printable(cmdtype)
int cmdtype;
{
	switch (cmdtype) {







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










|

|
|
|






|
|

|
|
|
|





|

|

|

|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|







1908
1909
1910
1911
1912
1913
1914


























































1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
	case EXP_TCLCNT:		return TCL_CONTINUE;
	case EXP_TCLCNTEXP:		return EXP_CONTINUE;
	case EXP_TCLCNTTIMER:		return EXP_CONTINUE_TIMER;
	case EXP_TCLRETTCL:		return EXP_TCL_RETURN;
	}
}



























































/* variables predefined by expect are retrieved using this routine
which looks in the global space if they are not in the local space.
This allows the user to localize them if desired, and also to
avoid having to put "global" in procedure definitions.
*/
char *
exp_get_var(interp,var)
Tcl_Interp *interp;
char *var;
{
    char *val;

    if (NULL != (val = Tcl_GetVar(interp,var,0 /* local */)))
	return(val);
    return(Tcl_GetVar(interp,var,TCL_GLOBAL_ONLY));
}

static int
get_timeout(interp)
Tcl_Interp *interp;
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    char *t;

    if (NULL != (t = exp_get_var(interp,EXPECT_TIMEOUT))) {
	tsdPtr->timeout = atoi(t);
    }
    return(tsdPtr->timeout);
}

/* make a copy of a linked list (1st arg) and attach to end of another (2nd
arg) */
static int
update_expect_states(i_list,i_union)
struct exp_i *i_list;
struct exp_state_list **i_union;
{
    struct exp_i *p;

    /* for each i_list in an expect statement ... */
    for (p=i_list;p;p=p->next) {
	struct exp_state_list *slPtr;

	/* for each esPtr in the i_list */
	for (slPtr=p->state_list;slPtr;slPtr=slPtr->next) {
	    struct exp_state_list *tmpslPtr;
	    struct exp_state_list *u;

	    if (expStateAnyIs(slPtr->esPtr)) continue;
	    
	    /* check this one against all so far */
	    for (u = *i_union;u;u=u->next) {
		if (slPtr->esPtr == u->esPtr) goto found;
	    }
	    /* if not found, link in as head of list */
	    tmpslPtr = exp_new_state(slPtr->esPtr);
	    tmpslPtr->next = *i_union;
	    *i_union = tmpslPtr;
	    found:;
	}
    }
    return TCL_OK;
}

char *
exp_cmdtype_printable(cmdtype)
int cmdtype;
{
	switch (cmdtype) {
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833




1834

1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854

1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
















1874





1875

















1876
1877




1878





1879


1880



1881


1882




















1883


1884




1885




1886







1887












1888















































1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919

1920
1921
1922
1923
1924
1925
1926


1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941

1942
1943
1944
1945
1946
1947

1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158





2159

2160
2161
2162
2163
2164
2165
2166
2167


2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189

2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227






2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284

2285

2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
{
	char *msg;

	struct exp_i *exp_i = (struct exp_i *)clientData;
	exp_configure_count++;
	msg = exp_indirect_update1(interp,&exp_cmds[exp_i->cmdtype],exp_i);

	exp_background_filehandlers_run_all();

	return msg;
}

static char *
exp_indirect_update1(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
struct exp_i *exp_i;
{
	struct exp_fd_list *fdl;	/* temp for interating over fd_list */

	/*
	 * disarm any fd's that lose all their ecases
	 */

	if (ecmd->cmdtype == EXP_CMD_BG) {
		/* clean up each spawn id used by this exp_i */
		for (fdl=exp_i->fd_list;fdl;fdl=fdl->next) {
			int m = fdl->fd;

			if (m == EXP_SPAWN_ID_ANY) continue;

			/* silently skip closed or preposterous fds */
			/* since we're just disabling them anyway */
			/* preposterous fds will have been reported */
			/* by code in next section already */
			if (!exp_fd2f(interp,fdl->fd,1,0,"")) continue;





			exp_fs[m].bg_ecount--;

			if (exp_fs[m].bg_ecount == 0) {
				exp_disarm_background_filehandler(m);
				exp_fs[m].bg_interp = 0;
			}
		}
	}

	/*
	 * reread indirect variable
	 */

	exp_i_update(interp,exp_i);

	/*
	 * check validity of all fd's in variable
	 */

	for (fdl=exp_i->fd_list;fdl;fdl=fdl->next) {
		/* validate all input descriptors */
		if (fdl->fd == EXP_SPAWN_ID_ANY) continue;


		if (!exp_fd2f(interp,fdl->fd,1,1,
				exp_cmdtype_printable(ecmd->cmdtype))) {
			static char msg[200];
			sprintf(msg,"%s from indirect variable (%s)",
				interp->result,exp_i->variable);
			return msg;
		}
	}

	/* for each spawn id in list, arm if necessary */
	if (ecmd->cmdtype == EXP_CMD_BG) {
		fd_list_arm(interp,exp_i->fd_list);
	}

	return (char *)0;
}

void
















exp_background_filehandlers_run_all()





{

















	int m;
	struct exp_f *f;










	/* kick off any that already have input waiting */


	for (m=0;m<=exp_fd_max;m++) {



		f = exp_fs + m;


		if (!f->valid) continue;























		/* is bg_interp the best way to check if armed? */




		if (f->bg_interp && (f->size > 0)) {




			exp_background_filehandler((ClientData)f->fd_ptr,0/*ignored*/);







		}












	}















































}

/* this function is called from the background when input arrives */
/*ARGSUSED*/
void
exp_background_filehandler(clientData,mask)
ClientData clientData;
int mask;
{
	int m;

	Tcl_Interp *interp;
	int cc;			/* number of chars returned in a single read */
				/* or negative EXP_whatever */
	struct exp_f *f;		/* file associated with master */

	int i;			/* trusty temporary */

	struct eval_out eo;	/* final case of interest */
	struct exp_f *last_f;	/* for differentiating when multiple f's */
				/* to print out better debugging messages */
	int last_case;		/* as above but for case */

	/* restore our environment */
	m = *(int *)clientData;
	f = exp_fs + m;
	interp = f->bg_interp;

	/* temporarily prevent this handler from being invoked again */
	exp_block_background_filehandler(m);


	/* if mask == 0, then we've been called because the patterns changed */
	/* not because the waiting data has changed, so don't actually do */
	/* any I/O */

	if (mask == 0) {
		cc = 0;
	} else {


		cc = expect_read(interp,(int *)0,mask,&m,EXP_TIME_INFINITY,0);
	}

do_more_data:
	eo.e = 0;		/* no final case yet */
	eo.f = 0;		/* no final file selected yet */
	eo.match = 0;		/* nothing matched yet */

	/* force redisplay of buffer when debugging */
	last_f = 0;

	if (cc == EXP_EOF) {
		/* do nothing */
	} else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/
		goto finish;

		/* if we were going to do this right, we should */
		/* differentiate between things like HP ioctl-open-traps */
		/* that fall out here and should rightfully be ignored */
		/* and real errors that should be reported.  Come to */
		/* think of it, the only errors will come from HP */
		/* ioctl handshake botches anyway. */

	} else {
		/* normal case, got data */
		/* new data if cc > 0, same old data if cc == 0 */

		/* below here, cc as general status */
		cc = EXP_NOMATCH;
	}

	cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE],
			m,&eo,&last_f,&last_case,cc,&m,1,"_background");
	cc = eval_cases(interp,&exp_cmds[EXP_CMD_BG],
			m,&eo,&last_f,&last_case,cc,&m,1,"_background");
	cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER],
			m,&eo,&last_f,&last_case,cc,&m,1,"_background");
	if (cc == EXP_TCLERROR) {
		/* only likely problem here is some internal regexp botch */
		Tcl_BackgroundError(interp);
		goto finish;
	}
	/* special eof code that cannot be done in eval_cases */
	/* or above, because it would then be executed several times */
	if (cc == EXP_EOF) {
		eo.f = exp_fs + m;
		eo.match = eo.f->size;
		eo.buffer = eo.f->buffer;
		debuglog("expect_background: read eof\r\n");
		goto matched;
	}
	if (!eo.e) {
		/* if we get here, there must not have been a match */
		goto finish;
	}

 matched:
#define out(i,val)  debuglog("expect_background: set %s(%s) \"%s\"\r\n",EXPECT_OUT,i, \
						dprintify(val)); \
		    Tcl_SetVar2(interp,EXPECT_OUT,i,val,TCL_GLOBAL_ONLY);
	{
/*		int iwrite = FALSE;*/	/* write spawn_id? */
		char *body = 0;
		char *buffer;	/* pointer to normal or lowercased data */
		struct ecase *e = 0;	/* points to current ecase */
		int match = -1;		/* characters matched */
		char match_char;	/* place to hold char temporarily */
					/* uprooted by a NULL */
		char *eof_body = 0;

		if (eo.e) {
			e = eo.e;
			body = e->body;
/*			iwrite = e->iwrite;*/
			if (cc != EXP_TIMEOUT) {
				f = eo.f;
				match = eo.match;
				buffer = eo.buffer;
			}
#if 0
			if (e->timestamp) {
				char value[20];

				time(&current_time);
				elapsed_time = current_time - start_time;
				elapsed_time_total = current_time - start_time_total;
				sprintf(value,"%d",elapsed_time);
				out("seconds",value);
				sprintf(value,"%d",elapsed_time_total);
				out("seconds_total",value);
				/* deprecated */
				exp_timestamp(interp,&current_time,EXPECT_OUT);
			}
#endif
		} else if (cc == EXP_EOF) {
			/* read an eof but no user-supplied case */
			f = eo.f;
			match = eo.match;
			buffer = eo.buffer;
		}			

		if (match >= 0) {
			char name[20], value[20];

			if (e && e->use == PAT_RE) {
				regexp *re = e->re;

				for (i=0;i<NSUBEXP;i++) {
					int offset;

					if (re->startp[i] == 0) continue;

					if (e->indices) {
					  /* start index */
					  sprintf(name,"%d,start",i);
					  offset = re->startp[i]-buffer;
					  sprintf(value,"%d",offset);
					  out(name,value);

					  /* end index */
					  sprintf(name,"%d,end",i);
					  sprintf(value,"%d",
						re->endp[i]-buffer-1);
					  out(name,value);
					}

					/* string itself */
					sprintf(name,"%d,string",i);

					/* temporarily null-terminate in */
					/* middle */
					match_char = *re->endp[i];
					*re->endp[i] = 0;
					out(name,re->startp[i]);
					*re->endp[i] = match_char;
				}
				/* redefine length of string that */
				/* matched for later extraction */
				match = re->endp[0]-buffer;
			} else if (e && (e->use == PAT_GLOB || e->use == PAT_EXACT)) {
				char *str;

				if (e->indices) {
				  /* start index */
				  sprintf(value,"%d",e->simple_start);
				  out("0,start",value);

				  /* end index */
				  sprintf(value,"%d",e->simple_start + match - 1);
				  out("0,end",value);
				}

				/* string itself */
				str = f->buffer + e->simple_start;
				/* temporarily null-terminate in middle */
				match_char = str[match];
				str[match] = 0;
				out("0,string",str);
				str[match] = match_char;

				/* redefine length of string that */
				/* matched for later extraction */
				match += e->simple_start;
			} else if (e && e->use == PAT_NULL && e->indices) {
				/* start index */
				sprintf(value,"%d",match-1);
				out("0,start",value);
				/* end index */
				sprintf(value,"%d",match-1);
				out("0,end",value);
			} else if (e && e->use == PAT_FULLBUFFER) {
				debuglog("expect_background: full buffer\r\n");
			}
		}

		/* this is broken out of (match > 0) (above) since it can */
		/* that an EOF occurred with match == 0 */
		if (eo.f) {
			char spawn_id[10];	/* enough for a %d */

/*			if (iwrite) {*/
				sprintf(spawn_id,"%d",f-exp_fs);
				out("spawn_id",spawn_id);
/*			}*/

			/* save buf[0..match] */
			/* temporarily null-terminate string in middle */
			match_char = f->buffer[match];
			f->buffer[match] = 0;
			out("buffer",f->buffer);
			/* remove middle-null-terminator */
			f->buffer[match] = match_char;

			/* "!e" means no case matched - transfer by default */
			if (!e || e->transfer) {
				/* delete matched chars from input buffer */
				f->size -= match;
				f->printed -= match;
				if (f->size != 0) {
				   memmove(f->buffer,f->buffer+match,f->size);
				   memmove(f->lower,f->lower+match,f->size);
				}
				f->buffer[f->size] = '\0';
				f->lower[f->size] = '\0';
			}

			if (cc == EXP_EOF) {
				/* exp_close() deletes all background bodies */
				/* so save eof body temporarily */
				if (body) {
					eof_body = ckalloc(strlen(body)+1);
					strcpy(eof_body,body);
					body = eof_body;
				}

				exp_close(interp,f - exp_fs);
			}

		}

		if (body) {
			int result = Tcl_GlobalEval(interp,body);
			if (result != TCL_OK) Tcl_BackgroundError(interp);

			if (eof_body) ckfree(eof_body);
		}


		/*
		 * Event handler will not call us back if there is more input
		 * pending but it has already arrived.  bg_status will be
		 * "blocked" only if armed.
		 */
		if (exp_fs[m].valid && (exp_fs[m].bg_status == blocked)





		 && (f->size > 0)) {

			cc = f->size;
			goto do_more_data;
		}
	}
 finish:
	/* fd could have gone away, so check before using */
	if (exp_fs[m].valid)
		exp_unblock_background_filehandler(m);


}
#undef out

/*ARGSUSED*/
int
Exp_ExpectCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int cc;			/* number of chars returned in a single read */
				/* or negative EXP_whatever */
	int m;			/* before doing an actual read, attempt */
				/* to match upon any spawn_id */
	struct exp_f *f;		/* file associated with master */

	int i;			/* trusty temporary */
	struct exp_cmd_descriptor eg;
	struct exp_fd_list *fd_list;	/* list of masters to watch */
	struct exp_fd_list *fdl;	/* temp for interating over fd_list */
	int *masters;		/* array of masters to watch */

	int mcount;		/* number of masters to watch */

	struct eval_out eo;	/* final case of interest */

	int result;		/* Tcl result */

	time_t start_time_total;/* time at beginning of this procedure */
	time_t start_time = 0;	/* time when restart label hit */
	time_t current_time = 0;/* current time (when we last looked)*/
	time_t end_time;	/* future time at which to give up */
	time_t elapsed_time_total;/* time from now to match/fail/timeout */
	time_t elapsed_time;	/* time from restart to (ditto) */

	struct exp_f *last_f;	/* for differentiating when multiple f's */
				/* to print out better debugging messages */
	int last_case;		/* as above but for case */
	int first_time = 1;	/* if not "restarted" */

	int key;		/* identify this expect command instance */
	int configure_count;	/* monitor exp_configure_count */

	int timeout;		/* seconds */
	int remtime;		/* remaining time in timeout */
	int reset_timer;	/* should timer be reset after continue? */

	if ((argc == 2) && exp_one_arg_braced(argv[1])) {
		return(exp_eval_with_one_arg(clientData,interp,argv));
	} else if ((argc == 3) && streq(argv[1],"-brace")) {
		char *new_argv[2];
		new_argv[0] = argv[0];
		new_argv[1] = argv[2];
		return(exp_eval_with_one_arg(clientData,interp,new_argv));
	}

	time(&start_time_total);
	start_time = start_time_total;
	reset_timer = TRUE;







	/* make arg list for processing cases */
	/* do it dynamically, since expect can be called recursively */

	exp_cmd_init(&eg,EXP_CMD_FG,EXP_TEMPORARY);
	fd_list = 0;
	masters = 0;
	if (TCL_ERROR == parse_expect_args(interp,&eg,
					*(int *)clientData,argc,argv))
		return TCL_ERROR;

 restart_with_update:
	/* validate all descriptors */
	/* and flatten fds into array */

	if ((TCL_ERROR == update_expect_fds(exp_cmds[EXP_CMD_BEFORE].i_list,&fd_list))
	 || (TCL_ERROR == update_expect_fds(exp_cmds[EXP_CMD_AFTER].i_list, &fd_list))
	 || (TCL_ERROR == update_expect_fds(eg.i_list,&fd_list))) {
		result = TCL_ERROR;
		goto cleanup;
	}

	/* declare ourselves "in sync" with external view of close/indirect */
	configure_count = exp_configure_count;

	/* count and validate fd_list */
	mcount = 0;
	for (fdl=fd_list;fdl;fdl=fdl->next) {
		mcount++;
		/* validate all input descriptors */
		if (!exp_fd2f(interp,fdl->fd,1,1,"expect")) {
			result = TCL_ERROR;
			goto cleanup;
		}
	}

	/* make into an array */
	masters = (int *)ckalloc(mcount * sizeof(int));
	for (fdl=fd_list,i=0;fdl;fdl=fdl->next,i++) {
		masters[i] = fdl->fd;
	}

     restart:
	if (first_time) first_time = 0;
	else time(&start_time);

	if (eg.timeout_specified_by_flag) {
		timeout = eg.timeout;
	} else {
		/* get the latest timeout */
		timeout = get_timeout(interp);
	}

	key = expect_key++;

	result = TCL_OK;
	last_f = 0;


	/* end of restart code */


	eo.e = 0;		/* no final case yet */
	eo.f = 0;		/* no final file selected yet */
	eo.match = 0;		/* nothing matched yet */

	/* timeout code is a little tricky, be very careful changing it */
	if (timeout != EXP_TIME_INFINITY) {
		/* if exp_continue -continue_timer, do not update end_time */
		if (reset_timer) {
			time(&current_time);
			end_time = current_time + timeout;
		} else {
			reset_timer = TRUE;
		}
	}

	/* remtime and current_time updated at bottom of loop */
	remtime = timeout;

	for (;;) {
		if ((timeout != EXP_TIME_INFINITY) && (remtime < 0)) {
			cc = EXP_TIMEOUT;
		} else {
			cc = expect_read(interp,masters,mcount,&m,remtime,key);
		}

		/*SUPPRESS 530*/
		if (cc == EXP_EOF) {
			/* do nothing */
		} else if (cc == EXP_TIMEOUT) {
			debuglog("expect: timed out\r\n");
		} else if (cc == EXP_RECONFIGURE) {
			reset_timer = FALSE;
			goto restart_with_update;
		} else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/
			goto error;
		} else {
			/* new data if cc > 0, same old data if cc == 0 */

			f = exp_fs + m;

			/* below here, cc as general status */
			cc = EXP_NOMATCH;

			/* force redisplay of buffer when debugging */
			last_f = 0;
		}

		cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE],
			m,&eo,&last_f,&last_case,cc,masters,mcount,"");
		cc = eval_cases(interp,&eg,
			m,&eo,&last_f,&last_case,cc,masters,mcount,"");
		cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER],
			m,&eo,&last_f,&last_case,cc,masters,mcount,"");
		if (cc == EXP_TCLERROR) goto error;
		/* special eof code that cannot be done in eval_cases */
		/* or above, because it would then be executed several times */
		if (cc == EXP_EOF) {
			eo.f = exp_fs + m;
			eo.match = eo.f->size;
			eo.buffer = eo.f->buffer;
			debuglog("expect: read eof\r\n");
			break;
		} else if (cc == EXP_TIMEOUT) break;
		/* break if timeout or eof and failed to find a case for it */

		if (eo.e) break;

		/* no match was made with current data, force a read */
		f->force_read = TRUE;

		if (timeout != EXP_TIME_INFINITY) {
			time(&current_time);
			remtime = end_time - current_time;
		}
	}

	goto done;

error:
	result = exp_2tcl_returnvalue(cc);
 done:
#define out(i,val)  debuglog("expect: set %s(%s) \"%s\"\r\n",EXPECT_OUT,i, \
						dprintify(val)); \
		    Tcl_SetVar2(interp,EXPECT_OUT,i,val,0);

	if (result != TCL_ERROR) {
/*		int iwrite = FALSE;*/	/* write spawn_id? */
		char *body = 0;
		char *buffer;	/* pointer to normal or lowercased data */
		struct ecase *e = 0;	/* points to current ecase */
		int match = -1;		/* characters matched */
		char match_char;	/* place to hold char temporarily */
					/* uprooted by a NULL */
		char *eof_body = 0;

		if (eo.e) {
			e = eo.e;
			body = e->body;
/*			iwrite = e->iwrite;*/
			if (cc != EXP_TIMEOUT) {
				f = eo.f;
				match = eo.match;
				buffer = eo.buffer;
			}
			if (e->timestamp) {
				char value[20];

				time(&current_time);
				elapsed_time = current_time - start_time;
				elapsed_time_total = current_time - start_time_total;
				sprintf(value,"%d",elapsed_time);
				out("seconds",value);
				sprintf(value,"%d",elapsed_time_total);
				out("seconds_total",value);

				/* deprecated */
				exp_timestamp(interp,&current_time,EXPECT_OUT);
			}
		} else if (cc == EXP_EOF) {
			/* read an eof but no user-supplied case */
			f = eo.f;
			match = eo.match;
			buffer = eo.buffer;
		}			

		if (match >= 0) {
			char name[20], value[20];

			if (e && e->use == PAT_RE) {
				regexp *re = e->re;

				for (i=0;i<NSUBEXP;i++) {
					int offset;

					if (re->startp[i] == 0) continue;

					if (e->indices) {
					  /* start index */
					  sprintf(name,"%d,start",i);
					  offset = re->startp[i]-buffer;
					  sprintf(value,"%d",offset);
					  out(name,value);

					  /* end index */
					  sprintf(name,"%d,end",i);
					  sprintf(value,"%d",
						re->endp[i]-buffer-1);
					  out(name,value);
					}

					/* string itself */
					sprintf(name,"%d,string",i);

					/* temporarily null-terminate in */
					/* middle */
					match_char = *re->endp[i];
					*re->endp[i] = 0;
					out(name,re->startp[i]);
					*re->endp[i] = match_char;
				}
				/* redefine length of string that */
				/* matched for later extraction */
				match = re->endp[0]-buffer;
			} else if (e && (e->use == PAT_GLOB || e->use == PAT_EXACT)) {
				char *str;

				if (e->indices) {
				  /* start index */
				  sprintf(value,"%d",e->simple_start);
				  out("0,start",value);

				  /* end index */
				  sprintf(value,"%d",e->simple_start + match - 1);
				  out("0,end",value);
				}

				/* string itself */
				str = f->buffer + e->simple_start;
				/* temporarily null-terminate in middle */
				match_char = str[match];
				str[match] = 0;
				out("0,string",str);
				str[match] = match_char;

				/* redefine length of string that */
				/* matched for later extraction */
				match += e->simple_start;
			} else if (e && e->use == PAT_NULL && e->indices) {
				/* start index */
				sprintf(value,"%d",match-1);
				out("0,start",value);
				/* end index */
				sprintf(value,"%d",match-1);
				out("0,end",value);
			} else if (e && e->use == PAT_FULLBUFFER) {
				debuglog("expect: full buffer\r\n");
			}
		}

		/* this is broken out of (match > 0) (above) since it can */
		/* that an EOF occurred with match == 0 */
		if (eo.f) {
			char spawn_id[10];	/* enough for a %d */

/*			if (iwrite) {*/
				sprintf(spawn_id,"%d",f-exp_fs);
				out("spawn_id",spawn_id);
/*			}*/

			/* save buf[0..match] */
			/* temporarily null-terminate string in middle */
			match_char = f->buffer[match];
			f->buffer[match] = 0;
			out("buffer",f->buffer);
			/* remove middle-null-terminator */
			f->buffer[match] = match_char;

			/* "!e" means no case matched - transfer by default */
			if (!e || e->transfer) {
				/* delete matched chars from input buffer */
				f->size -= match;
				f->printed -= match;
				if (f->size != 0) {
				   memmove(f->buffer,f->buffer+match,f->size);
				   memmove(f->lower,f->lower+match,f->size);
				}
				f->buffer[f->size] = '\0';
				f->lower[f->size] = '\0';
			}

			if (cc == EXP_EOF) {
				/* exp_close() deletes all background bodies */
				/* so save eof body temporarily */
				if (body) {
					eof_body = ckalloc(strlen(body)+1);
					strcpy(eof_body,body);
					body = eof_body;
				}

				exp_close(interp,f - exp_fs);
			}

		}

		if (body) {
			result = Tcl_Eval(interp,body);

			if (eof_body) ckfree(eof_body);
		}
	}

 cleanup:
	if (result == EXP_CONTINUE_TIMER) {
		reset_timer = FALSE;
		result = EXP_CONTINUE;
	}

	if ((result == EXP_CONTINUE)
	     && (configure_count == exp_configure_count)) {
		debuglog("expect: continuing expect\r\n");
		goto restart;
	}

	if (fd_list) {
		exp_free_fd(fd_list);
		fd_list = 0;
	}
	if (masters) {
		ckfree((char *)masters);
		masters = 0;
	}

	if (result == EXP_CONTINUE) {
		debuglog("expect: continuing expect after update\r\n");
		goto restart_with_update;
	}

	free_ecases(interp,&eg,0);	/* requires i_lists to be avail */
	exp_free_i(interp,eg.i_list,exp_indirect_update2);

	return(result);
}
#undef out

/* beginning of deprecated code */

#define out(elt)		Tcl_SetVar2(interp,array,elt,ascii,0);
void
exp_timestamp(interp,timeval,array)
Tcl_Interp *interp;
time_t *timeval;
char *array;
{
	struct tm *tm;
	char *ascii;

	tm = localtime(timeval);	/* split */
	ascii = asctime(tm);		/* print */
	ascii[24] = '\0';		/* zap trailing \n */

	out("timestamp");

	sprintf(ascii,"%ld",*timeval);
	out("epoch");

	sprintf(ascii,"%d",tm->tm_sec);
	out("sec");
	sprintf(ascii,"%d",tm->tm_min);
	out("min");
	sprintf(ascii,"%d",tm->tm_hour);
	out("hour");
	sprintf(ascii,"%d",tm->tm_mday);
	out("mday");
	sprintf(ascii,"%d",tm->tm_mon);
	out("mon");
	sprintf(ascii,"%d",tm->tm_year);
	out("year");
	sprintf(ascii,"%d",tm->tm_wday);
	out("wday");
	sprintf(ascii,"%d",tm->tm_yday);
	out("yday");
	sprintf(ascii,"%d",tm->tm_isdst);
	out("isdst");
}
/* end of deprecated code */

/*ARGSUSED*/
static int
Exp_TimestampCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;







|










|


|




|
|

|





|

>
>
>
>
|
>
|
|
|














|
|
|
>

|
|
|
|
|
|
|




|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>

>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|



<
|
|
|

<
<
<
<
|
|

|

|
|
<
|

|
|

>
|
|
<
|
|
|
|
>
>
|
|


|
|
|

|
|

|
|
|
|
>
|
|
<
|
|
|
>
|
|
|

|
|
|

|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|


<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|
|
|
|
|
>
>
>
>
>
|
>
|
|
|
|

<
<
|
>
>

<



|


|
|

|

|
<
<

|
|
|
|
<
>
|

|

|
|
|
|
|
|
<
<

|

|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
>
>
>
>
>
>
|
|

|
|
|
|
|
|


|
<

|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|
|
|

|
|
|
|
|
|

|

|
|

>
|
>

|
|
|

|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|

|
|

|
|
|
|
|

|


|

<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
|
|
|

|
<
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|

|
|

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260

2261
2262
2263
2264




2265
2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279

2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341












2342





























































































































































2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361


2362
2363
2364
2365

2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377


2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393


2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437

2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523


2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564




2565








2566








2567


















































































































































2568
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598











































2599
2600
2601
2602
2603
2604
2605
{
	char *msg;

	struct exp_i *exp_i = (struct exp_i *)clientData;
	exp_configure_count++;
	msg = exp_indirect_update1(interp,&exp_cmds[exp_i->cmdtype],exp_i);

	exp_background_channelhandlers_run_all();

	return msg;
}

static char *
exp_indirect_update1(interp,ecmd,exp_i)
Tcl_Interp *interp;
struct exp_cmd_descriptor *ecmd;
struct exp_i *exp_i;
{
	struct exp_state_list *slPtr;	/* temp for interating over state_list */

	/*
	 * disarm any ExpState's that lose all their ecases
	 */

	if (ecmd->cmdtype == EXP_CMD_BG) {
		/* clean up each spawn id used by this exp_i */
		for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) {
			ExpState *esPtr = slPtr->esPtr;

			if (expStateAnyIs(esPtr)) continue;

			/* silently skip closed or preposterous fds */
			/* since we're just disabling them anyway */
			/* preposterous fds will have been reported */
			/* by code in next section already */
			if (!expStateCheck(interp,slPtr->esPtr,1,0,"")) continue;

			/* check before decrementing, ecount may not be */
			/* positive if update is called before ecount is */
			/* properly synchronized */
			if (esPtr->bg_ecount > 0) {
				esPtr->bg_ecount--;
			}
			if (esPtr->bg_ecount == 0) {
				exp_disarm_background_channelhandler(esPtr);
				esPtr->bg_interp = 0;
			}
		}
	}

	/*
	 * reread indirect variable
	 */

	exp_i_update(interp,exp_i);

	/*
	 * check validity of all fd's in variable
	 */

	for (slPtr=exp_i->state_list;slPtr;slPtr=slPtr->next) {
	    /* validate all input descriptors */

	    if (expStateAnyIs(slPtr->esPtr)) continue;

	    if (!expStateCheck(interp,slPtr->esPtr,1,1,
		    exp_cmdtype_printable(ecmd->cmdtype))) {
		static char msg[200];
		sprintf(msg,"%s from indirect variable (%s)",
			interp->result,exp_i->variable);
		return msg;
	    }
	}

	/* for each spawn id in list, arm if necessary */
	if (ecmd->cmdtype == EXP_CMD_BG) {
		state_list_arm(interp,exp_i->state_list);
	}

	return (char *)0;
}

int
expMatchProcess(interp, eo, cc, bg, detail)
    Tcl_Interp *interp;
    struct eval_out *eo;	/* final case of interest */
    int cc;			/* EOF, TIMEOUT, etc... */
    int bg;			/* 1 if called from background handler, */
				/* else 0 */
    char *detail;
{
    ExpState *esPtr = 0;
    Tcl_Obj *body = 0;
    Tcl_Obj *buffer;
    struct ecase *e = 0;	/* points to current ecase */
    int match = -1;		/* characters matched */
    char match_char;	/* place to hold char temporarily */
    /* uprooted by a NULL */
    int result = TCL_OK;

#define out(indexName, value) \
 expDiagLog("%s: set %s(%s) \"",detail,EXPECT_OUT,indexName); \
 expDiagLogU(expPrintify(value)); \
 expDiagLogU("\"\r\n"); \
 Tcl_SetVar2(interp, EXPECT_OUT,indexName,value,(bg ? TCL_GLOBAL_ONLY : 0));

    if (eo->e) {
	e = eo->e;
	body = e->body;
	if (cc != EXP_TIMEOUT) {
	    esPtr = eo->esPtr;
	    match = eo->match;
	    buffer = eo->buffer;
	}
    } else if (cc == EXP_EOF) {
	/* read an eof but no user-supplied case */
	esPtr = eo->esPtr;
	match = eo->match;
	buffer = eo->buffer;
    }			

    if (match >= 0) {
	char name[20], value[20];
	int i;

	if (e && e->use == PAT_RE) {
	    Tcl_RegExp re;
	    int flags;
	    Tcl_RegExpInfo info;

	    if (e->Case == CASE_NORM) {
		flags = TCL_REG_ADVANCED;
	    } else {
		flags = TCL_REG_ADVANCED | TCL_REG_NOCASE;
	    }
		    
	    re = Tcl_GetRegExpFromObj(interp, e->pat, flags);
	    Tcl_RegExpGetInfo(re, &info);

	    for (i=0;i<=info.nsubs;i++) {
		int start, end;
		Tcl_Obj *val;

		start = info.matches[i].start;
		end = info.matches[i].end-1;
		if (start == -1) continue;

		if (e->indices) {
		    /* start index */
		    sprintf(name,"%d,start",i);
		    sprintf(value,"%d",start);
		    out(name,value);

		    /* end index */
		    sprintf(name,"%d,end",i);
		    sprintf(value,"%d",end);
		    out(name,value);
		}

				/* string itself */
		sprintf(name,"%d,string",i);
		val = Tcl_GetRange(buffer, start, end);
		expDiagLog("%s: set %s(%s) \"",detail,EXPECT_OUT,name);
		expDiagLogU(expPrintifyObj(val));
		expDiagLogU("\"\r\n");
		Tcl_SetVar2Ex(interp,EXPECT_OUT,name,val,(bg ? TCL_GLOBAL_ONLY : 0));
	    }
	} else if (e && (e->use == PAT_GLOB || e->use == PAT_EXACT)) {
	    char *str;

	    if (e->indices) {
		/* start index */
		sprintf(value,"%d",e->simple_start);
		out("0,start",value);

		/* end index */
		sprintf(value,"%d",e->simple_start + match - 1);
		out("0,end",value);
	    }

	    /* string itself */
	    str = Tcl_GetString(esPtr->buffer) + e->simple_start;
	    /* temporarily null-terminate in middle */
	    match_char = str[match];
	    str[match] = 0;
	    out("0,string",str);
	    str[match] = match_char;

				/* redefine length of string that */
				/* matched for later extraction */
	    match += e->simple_start;
	} else if (e && e->use == PAT_NULL && e->indices) {
				/* start index */
	    sprintf(value,"%d",match-1);
	    out("0,start",value);
				/* end index */
	    sprintf(value,"%d",match-1);
	    out("0,end",value);
	} else if (e && e->use == PAT_FULLBUFFER) {
	    expDiagLogU("expect_background: full buffer\r\n");
	}
    }

    /* this is broken out of (match > 0) (above) since it can */
    /* that an EOF occurred with match == 0 */
    if (eo->esPtr) {
	char *str;
	int length;

	out("spawn_id",esPtr->name);

	str = Tcl_GetStringFromObj(esPtr->buffer, &length);
	/* Save buf[0..match] */
	/* temporarily null-terminate string in middle */
	match_char = str[match];
	str[match] = 0;
	out("buffer",str);
	/* remove middle-null-terminator */
	str[match] = match_char;

	/* "!e" means no case matched - transfer by default */
	if (!e || e->transfer) {
	    /* delete matched chars from input buffer */
	    esPtr->printed -= match;
	    if (length != 0) {
		memmove(str,str+match,length-match);
	    }
	    Tcl_SetObjLength(esPtr->buffer, length-match);
	}

	if (cc == EXP_EOF) {
	    /* exp_close() deletes all background bodies */
	    /* so save eof body temporarily */
	    if (body) Tcl_IncrRefCount(body);
	    exp_close(interp,esPtr);
	}
    }

    if (body) {
	if (!bg) {
	    result = Tcl_EvalObjEx(interp,body,0);
	} else {
	    result = Tcl_EvalObjEx(interp,body,TCL_EVAL_GLOBAL);
	    if (result != TCL_OK) Tcl_BackgroundError(interp);
	}
	if (cc == EXP_EOF) Tcl_DecrRefCount(body);
    }
    return result;
}

/* this function is called from the background when input arrives */
/*ARGSUSED*/
void
exp_background_channelhandler(clientData,mask) /* INTL */
ClientData clientData;
int mask;
{

    ExpState *esPtr;
    Tcl_Interp *interp;
    int cc;			/* number of bytes returned in a single read */
				/* or negative EXP_whatever */




    struct eval_out eo;		/* final case of interest */
    ExpState *last_esPtr;	/* for differentiating when multiple esPtrs */
				/* to print out better debugging messages */
    int last_case;		/* as above but for case */

    /* restore our environment */
    esPtr = (ExpState *)clientData;

    interp = esPtr->bg_interp;

    /* temporarily prevent this handler from being invoked again */
    exp_block_background_channelhandler(esPtr);

    /*
     * if mask == 0, then we've been called because the patterns changed not
     * because the waiting data has changed, so don't actually do any I/O

     */
    if (mask == 0) {
	cc = 0;
    } else {
	esPtr->notifiedMask = mask;
	esPtr->notified = FALSE;
	cc = expRead(interp,(ExpState **)0,0,&esPtr,EXP_TIME_INFINITY,0);
    }

do_more_data:
    eo.e = 0;		/* no final case yet */
    eo.esPtr = 0;		/* no final file selected yet */
    eo.match = 0;		/* nothing matched yet */

    /* force redisplay of buffer when debugging */
    last_esPtr = 0;

    if (cc == EXP_EOF) {
	/* do nothing */
    } else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/
	goto finish;
	/* 
	 * if we were going to do this right, we should differentiate between
	 * things like HP ioctl-open-traps that fall out here and should

	 * rightfully be ignored and real errors that should be reported.  Come
	 * to think of it, the only errors will come from HP ioctl handshake
	 * botches anyway.
	 */
    } else {
	/* normal case, got data */
	/* new data if cc > 0, same old data if cc == 0 */

	/* below here, cc as general status */
	cc = EXP_NOMATCH;
    }

    cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE],
	    esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background");
    cc = eval_cases(interp,&exp_cmds[EXP_CMD_BG],
	    esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background");
    cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER],
	    esPtr,&eo,&last_esPtr,&last_case,cc,&esPtr,1,"_background");
    if (cc == EXP_TCLERROR) {
		/* only likely problem here is some internal regexp botch */
		Tcl_BackgroundError(interp);
		goto finish;
    }
    /* special eof code that cannot be done in eval_cases */
    /* or above, because it would then be executed several times */
    if (cc == EXP_EOF) {
	eo.esPtr = esPtr;
	eo.match = expSizeGet(eo.esPtr);
	eo.buffer = eo.esPtr->buffer;
	expDiagLogU("expect_background: read eof\r\n");
	goto matched;
    }
    if (!eo.e) {
	/* if we get here, there must not have been a match */
	goto finish;
    }

 matched:












    expMatchProcess(interp, &eo, cc, 1 /* bg */,"expect_background");






























































































































































    /*
     * Event handler will not call us back if there is more input
     * pending but it has already arrived.  bg_status will be
     * "blocked" only if armed.
     */

    /*
     * Connection could have been closed on us.  In this case,
     * exitWhenBgStatusUnblocked will be 1 and we should disable the channel
     * handler and release the esPtr.
     */

    if ((!esPtr->freeWhenBgHandlerUnblocked) && (esPtr->bg_status == blocked)) {
	if (0 != (cc = expSizeGet(esPtr))) {
	    goto do_more_data;
	}
    }
 finish:


    exp_unblock_background_channelhandler(esPtr);
    if (esPtr->freeWhenBgHandlerUnblocked)
	expStateFree(esPtr);
}


/*ARGSUSED*/
int
Exp_ExpectObjCmd(clientData, interp, objc, objv)
ClientData clientData;
Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];		/* Argument objects. */
{
    int cc;			/* number of chars returned in a single read */
				/* or negative EXP_whatever */
    ExpState *esPtr = 0;



    int i;			/* misc temporary */
    struct exp_cmd_descriptor eg;
    struct exp_state_list *state_list;	/* list of ExpStates to watch */
    struct exp_state_list *slPtr;	/* temp for interating over state_list */

    ExpState **esPtrs;
    int mcount;			/* number of esPtrs to watch */

    struct eval_out eo;		/* final case of interest */

    int result;			/* Tcl result */
    
    time_t start_time_total;	/* time at beginning of this procedure */
    time_t start_time = 0;	/* time when restart label hit */
    time_t current_time = 0;	/* current time (when we last looked)*/
    time_t end_time;		/* future time at which to give up */



    ExpState *last_esPtr;	/* for differentiating when multiple f's */
				/* to print out better debugging messages */
    int last_case;		/* as above but for case */
    int first_time = 1;		/* if not "restarted" */
    
    int key;			/* identify this expect command instance */
    int configure_count;	/* monitor exp_configure_count */

    int timeout;		/* seconds */
    int remtime;		/* remaining time in timeout */
    int reset_timer;		/* should timer be reset after continue? */

    if ((objc == 2) && exp_one_arg_braced(objv[1])) {
	return(exp_eval_with_one_arg(clientData,interp,objv));
    } else if ((objc == 3) && streq(Tcl_GetString(objv[1]),"-brace")) {
	Tcl_Obj *new_objv[2];
	new_objv[0] = objv[0];
	new_objv[1] = objv[2];
	return(exp_eval_with_one_arg(clientData,interp,new_objv));
    }

    time(&start_time_total);
    start_time = start_time_total;
    reset_timer = TRUE;
    
    if (&StdinoutPlaceholder == (ExpState *)clientData) {
	clientData = (ClientData) expStdinoutGet();
    } else if (&DevttyPlaceholder == (ExpState *)clientData) {
	clientData = (ClientData) expDevttyGet();
    }
	
    /* make arg list for processing cases */
    /* do it dynamically, since expect can be called recursively */

    exp_cmd_init(&eg,EXP_CMD_FG,EXP_TEMPORARY);
    state_list = 0;
    esPtrs = 0;
    if (TCL_ERROR == parse_expect_args(interp,&eg,
	    (ExpState *)clientData,objc,objv))
	return TCL_ERROR;

 restart_with_update:
    /* validate all descriptors and flatten ExpStates into array */


    if ((TCL_ERROR == update_expect_states(exp_cmds[EXP_CMD_BEFORE].i_list,&state_list))
	    || (TCL_ERROR == update_expect_states(exp_cmds[EXP_CMD_AFTER].i_list, &state_list))
	    || (TCL_ERROR == update_expect_states(eg.i_list,&state_list))) {
	result = TCL_ERROR;
	goto cleanup;
    }

    /* declare ourselves "in sync" with external view of close/indirect */
    configure_count = exp_configure_count;

    /* count and validate state_list */
    mcount = 0;
    for (slPtr=state_list;slPtr;slPtr=slPtr->next) {
	mcount++;
	/* validate all input descriptors */
	if (!expStateCheck(interp,slPtr->esPtr,1,1,"expect")) {
	    result = TCL_ERROR;
	    goto cleanup;
	}
    }

    /* make into an array */
    esPtrs = (ExpState **)ckalloc(mcount * sizeof(ExpState *));
    for (slPtr=state_list,i=0;slPtr;slPtr=slPtr->next,i++) {
	esPtrs[i] = slPtr->esPtr;
    }

  restart:
    if (first_time) first_time = 0;
    else time(&start_time);

    if (eg.timeout_specified_by_flag) {
	timeout = eg.timeout;
    } else {
	/* get the latest timeout */
	timeout = get_timeout(interp);
    }

    key = expect_key++;

    result = TCL_OK;
    last_esPtr = 0;

    /*
     * end of restart code
     */

    eo.e = 0;		/* no final case yet */
    eo.esPtr = 0;	/* no final ExpState selected yet */
    eo.match = 0;	/* nothing matched yet */

    /* timeout code is a little tricky, be very careful changing it */
    if (timeout != EXP_TIME_INFINITY) {
	/* if exp_continue -continue_timer, do not update end_time */
	if (reset_timer) {
	    time(&current_time);
	    end_time = current_time + timeout;
	} else {
	    reset_timer = TRUE;
	}
    }

    /* remtime and current_time updated at bottom of loop */
    remtime = timeout;

    for (;;) {
	if ((timeout != EXP_TIME_INFINITY) && (remtime < 0)) {
	    cc = EXP_TIMEOUT;
	} else {
	    cc = expRead(interp,esPtrs,mcount,&esPtr,remtime,key);
	}

	/*SUPPRESS 530*/
	if (cc == EXP_EOF) {
	    /* do nothing */
	} else if (cc == EXP_TIMEOUT) {
	    expDiagLogU("expect: timed out\r\n");
	} else if (cc == EXP_RECONFIGURE) {
	    reset_timer = FALSE;
	    goto restart_with_update;
	} else if (cc < 0) { /* EXP_TCLERROR or any other weird value*/
	    goto error;
	} else {
	    /* new data if cc > 0, same old data if cc == 0 */
	    


	    /* below here, cc as general status */
	    cc = EXP_NOMATCH;

	    /* force redisplay of buffer when debugging */
	    last_esPtr = 0;
	}

	cc = eval_cases(interp,&exp_cmds[EXP_CMD_BEFORE],
		esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,"");
	cc = eval_cases(interp,&eg,
		esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,"");
	cc = eval_cases(interp,&exp_cmds[EXP_CMD_AFTER],
		esPtr,&eo,&last_esPtr,&last_case,cc,esPtrs,mcount,"");
	if (cc == EXP_TCLERROR) goto error;
	/* special eof code that cannot be done in eval_cases */
	/* or above, because it would then be executed several times */
	if (cc == EXP_EOF) {
	    eo.esPtr = esPtr;
	    eo.match = expSizeGet(eo.esPtr);
	    eo.buffer = eo.esPtr->buffer;
	    expDiagLogU("expect: read eof\r\n");
	    break;
	} else if (cc == EXP_TIMEOUT) break;
	/* break if timeout or eof and failed to find a case for it */

	if (eo.e) break;

	/* no match was made with current data, force a read */
	esPtr->force_read = TRUE;

	if (timeout != EXP_TIME_INFINITY) {
	    time(&current_time);
	    remtime = end_time - current_time;
	}
    }

    goto done;

error:
    result = exp_2tcl_returnvalue(cc);
 done:




    if (result != TCL_ERROR) {








	result = expMatchProcess(interp, &eo, cc, 0 /* not bg */,"expect");








    }



















































































































































 cleanup:
    if (result == EXP_CONTINUE_TIMER) {
	reset_timer = FALSE;
	result = EXP_CONTINUE;
    }

    if ((result == EXP_CONTINUE) && (configure_count == exp_configure_count)) {

	expDiagLogU("expect: continuing expect\r\n");
	goto restart;
    }

    if (state_list) {
	exp_free_state(state_list);
	state_list = 0;
    }
    if (esPtrs) {
	ckfree((char *)esPtrs);
	esPtrs = 0;
    }

    if (result == EXP_CONTINUE) {
	expDiagLogU("expect: continuing expect after update\r\n");
	goto restart_with_update;
    }

    free_ecases(interp,&eg,0);	/* requires i_lists to be avail */
    exp_free_i(interp,eg.i_list,exp_indirect_update2);

    return(result);
}












































/*ARGSUSED*/
static int
Exp_TimestampCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718

2719
2720


2721
2722
2723
2724

2725
2726
2727

2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742

2743


2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783





2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856

2857
2858


2859
2860
2861
2862

2863
2864
2865


2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
	return TCL_OK;
 usage_error:
	exp_error(interp,"args: [-seconds #] [-format format]");
	return TCL_ERROR;

}

/* lowmemcpy - like memcpy but it lowercases result */
void
exp_lowmemcpy(dest,src,n)
char *dest;
char *src;
int n;
{
	for (;n>0;n--) {
		*dest = ((isascii(*src) && isupper(*src))?tolower(*src):*src);
		src++;	dest++;
	}
}

/*ARGSUSED*/
int
Exp_MatchMaxCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int size = -1;
	int m = -1;
	struct exp_f *f;
	int Default = FALSE;

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-d")) {
			Default = TRUE;
		} else if (streq(*argv,"-i")) {
			argc--;argv++;
			if (argc < 1) {
				exp_error(interp,"-i needs argument");
				return(TCL_ERROR);
			}
			m = atoi(*argv);
		} else break;
	}

	if (!Default) {
		if (m == -1) {
			if (!(f = exp_update_master(interp,&m,0,0)))
				return(TCL_ERROR);

		} else {
			if (!(f = exp_fd2f(interp,m,0,0,"match_max")))


				return(TCL_ERROR);
		}
	} else if (m != -1) {
		exp_error(interp,"cannot do -d and -i at the same time");

		return(TCL_ERROR);
	}


	if (argc == 0) {
		if (Default) {
			size = exp_default_match_max;
		} else {
			size = f->umsize;
		}
		sprintf(interp->result,"%d",size);
		return(TCL_OK);
	}

	if (argc > 1) {
		exp_error(interp,"too many arguments");
		return(TCL_OK);
	}


	/* all that's left is to set the size */


	size = atoi(argv[0]);
	if (size <= 0) {
		exp_error(interp,"must be positive");
		return(TCL_ERROR);
	}

	if (Default) exp_default_match_max = size;
	else f->umsize = size;

	return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_RemoveNullsCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int value = -1;
	int m = -1;
	struct exp_f *f;
	int Default = FALSE;

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-d")) {
			Default = TRUE;
		} else if (streq(*argv,"-i")) {
			argc--;argv++;
			if (argc < 1) {
				exp_error(interp,"-i needs argument");
				return(TCL_ERROR);
			}
			m = atoi(*argv);
		} else break;
	}






	if (!Default) {
		if (m == -1) {
			if (!(f = exp_update_master(interp,&m,0,0)))
				return(TCL_ERROR);
		} else {
			if (!(f = exp_fd2f(interp,m,0,0,"remove_nulls")))
				return(TCL_ERROR);
		}
	} else if (m != -1) {
		exp_error(interp,"cannot do -d and -i at the same time");
		return(TCL_ERROR);
	}

	if (argc == 0) {
		if (Default) {
			value = exp_default_match_max;
		} else {
			value = f->rm_nulls;
		}
		sprintf(interp->result,"%d",value);
		return(TCL_OK);
	}

	if (argc > 1) {
		exp_error(interp,"too many arguments");
		return(TCL_OK);
	}

	/* all that's left is to set the value */
	value = atoi(argv[0]);
	if (value != 0 && value != 1) {
		exp_error(interp,"must be 0 or 1");
		return(TCL_ERROR);
	}

	if (Default) exp_default_rm_nulls = value;
	else f->rm_nulls = value;

	return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_ParityCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
	int parity;
	int m = -1;
	struct exp_f *f;
	int Default = FALSE;

	argc--; argv++;

	for (;argc>0;argc--,argv++) {
		if (streq(*argv,"-d")) {
			Default = TRUE;
		} else if (streq(*argv,"-i")) {
			argc--;argv++;
			if (argc < 1) {
				exp_error(interp,"-i needs argument");
				return(TCL_ERROR);
			}
			m = atoi(*argv);
		} else break;
	}

	if (!Default) {
		if (m == -1) {
			if (!(f = exp_update_master(interp,&m,0,0)))
				return(TCL_ERROR);

		} else {
			if (!(f = exp_fd2f(interp,m,0,0,"parity")))


				return(TCL_ERROR);
		}
	} else if (m != -1) {
		exp_error(interp,"cannot do -d and -i at the same time");

		return(TCL_ERROR);
	}



	if (argc == 0) {
		if (Default) {
			parity = exp_default_parity;
		} else {
			parity = f->parity;
		}
		sprintf(interp->result,"%d",parity);
		return(TCL_OK);
	}

	if (argc > 1) {
		exp_error(interp,"too many arguments");
		return(TCL_OK);
	}

	/* all that's left is to set the parity */
	parity = atoi(argv[0]);

	if (Default) exp_default_parity = parity;
	else f->parity = parity;

	return(TCL_OK);
}

#if DEBUG_PERM_ECASES
/* This big chunk of code is just for debugging the permanent */
/* expect cases */
void
exp_fd_print(fdl)
struct exp_fd_list *fdl;
{
	if (!fdl) return;
	printf("%d ",fdl->fd);
	exp_fd_print(fdl->next);
}

void
exp_i_print(exp_i)
struct exp_i *exp_i;
{
	if (!exp_i) return;
	printf("exp_i %x",exp_i);
	printf((exp_i->direct == EXP_DIRECT)?" direct":" indirect");
	printf((exp_i->duration == EXP_PERMANENT)?" perm":" tmp");
	printf("  ecount = %d\n",exp_i->ecount);
	printf("variable %s, value %s\n",
		((exp_i->variable)?exp_i->variable:"--"),
		((exp_i->value)?exp_i->value:"--"));
	printf("fds: ");
	exp_fd_print(exp_i->fd_list); printf("\n");
	exp_i_print(exp_i->next);
}

void
exp_ecase_print(ecase)
struct ecase *ecase;
{







<
<
<
<
<
<
<
<
<
<
<
<
<








|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|

|
<
|
|
>
|
|
>
>
|
|
|
|
>


|
>
|
|
|
|
|
|
|
|
|

|
|
|
|
|
>
|
>
>
|
|
|
|
|

|
|

|










|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|

>
>
>
>
>
|
|
|
|
|
|
|
|
<
<
<
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|

|










|
|
|
|

|

|
|
|
|
|
|
|
|
|
|
|
|

|
<
|
|
>
|
|
>
>
|
|
|
<
>

|
|
>
>
|
|
|
|
|
|
|
|
|

|
|
|
|

|
|

|
|

|






|
|

|
|
|














|
|







2654
2655
2656
2657
2658
2659
2660













2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689

2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777



2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836

2837
2838
2839
2840
2841
2842
2843
2844
2845
2846

2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
	return TCL_OK;
 usage_error:
	exp_error(interp,"args: [-seconds #] [-format format]");
	return TCL_ERROR;

}














/*ARGSUSED*/
int
Exp_MatchMaxCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    int size = -1;
    ExpState *esPtr = 0;
    char *chanName = 0;
    int Default = FALSE;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-d")) {
	    Default = TRUE;
	} else if (streq(*argv,"-i")) {
	    argc--;argv++;
	    if (argc < 1) {
		exp_error(interp,"-i needs argument");
		return(TCL_ERROR);
	    }
	    chanName = *argv;
	} else break;
    }

    if (Default && chanName) {

	exp_error(interp,"cannot do -d and -i at the same time");
	return(TCL_ERROR);
    }

    if (!Default) {
	if (!chanName) {
	    if (!(esPtr = expStateCurrent(interp,0,0,0))) {
		return(TCL_ERROR);
	    }
	} else {
	    
	    if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,0,"match_max")))
		return(TCL_ERROR);
	}
    }

    if (argc == 0) {
	if (Default) {
	    size = exp_default_match_max;
	} else {
	    size = esPtr->umsize;
	}
	sprintf(interp->result,"%d",size);
	return(TCL_OK);
    }

    if (argc > 1) {
	exp_error(interp,"too many arguments");
	return(TCL_OK);
    }
    
    /*
     * All that's left is to set the size
     */

    size = atoi(argv[0]);
    if (size <= 0) {
	exp_error(interp,"must be positive");
	return(TCL_ERROR);
    }

    if (Default) exp_default_match_max = size;
    else esPtr->umsize = size;

    return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_RemoveNullsCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    int value = -1;
    ExpState *esPtr = 0;
    char *chanName = 0;
    int Default = FALSE;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-d")) {
	    Default = TRUE;
	} else if (streq(*argv,"-i")) {
	    argc--;argv++;
	    if (argc < 1) {
		exp_error(interp,"-i needs argument");
		return(TCL_ERROR);
	    }
	    chanName = *argv;
	} else break;
    }

    if (Default && chanName) {
	exp_error(interp,"cannot do -d and -i at the same time");
	return(TCL_ERROR);
    }

    if (!Default) {
	if (!chanName) {
	    if (!(esPtr = expStateCurrent(interp,0,0,0)))
		return(TCL_ERROR);
	} else {
	    if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,0,"remove_nulls")))
		return(TCL_ERROR);
	}



    }

    if (argc == 0) {
	if (Default) {
	  value = exp_default_rm_nulls;
	} else {
	  value = esPtr->rm_nulls;
	}
	sprintf(interp->result,"%d",value);
	return(TCL_OK);
    }

    if (argc > 1) {
	exp_error(interp,"too many arguments");
	return(TCL_OK);
    }

    /* all that's left is to set the value */
    value = atoi(argv[0]);
    if (value != 0 && value != 1) {
	exp_error(interp,"must be 0 or 1");
	return(TCL_ERROR);
    }

    if (Default) exp_default_rm_nulls = value;
    else esPtr->rm_nulls = value;

    return(TCL_OK);
}

/*ARGSUSED*/
int
Exp_ParityCmd(clientData,interp,argc,argv)
ClientData clientData;
Tcl_Interp *interp;
int argc;
char **argv;
{
    int parity;
    ExpState *esPtr = 0;
    char *chanName = 0;
    int Default = FALSE;

    argc--; argv++;

    for (;argc>0;argc--,argv++) {
	if (streq(*argv,"-d")) {
	    Default = TRUE;
	} else if (streq(*argv,"-i")) {
	    argc--;argv++;
	    if (argc < 1) {
		exp_error(interp,"-i needs argument");
		return(TCL_ERROR);
	    }
	    chanName = *argv;
	} else break;
    }

    if (Default && chanName) {

	exp_error(interp,"cannot do -d and -i at the same time");
	return(TCL_ERROR);
    }

    if (!Default) {
	if (!chanName) {
	    if (!(esPtr = expStateCurrent(interp,0,0,0))) {
		return(TCL_ERROR);
	    }
	} else {

	    if (!(esPtr = expStateFromChannelName(interp,chanName,0,0,0,"parity"))) {
		return(TCL_ERROR);
	    }
	}
    }

    if (argc == 0) {
	if (Default) {
	    parity = exp_default_parity;
	} else {
	    parity = esPtr->parity;
	}
	sprintf(interp->result,"%d",parity);
	return(TCL_OK);
    }

    if (argc > 1) {
	exp_error(interp,"too many arguments");
	return(TCL_OK);
    }

    /* all that's left is to set the parity */
    parity = atoi(argv[0]);

    if (Default) exp_default_parity = parity;
    else esPtr->parity = parity;

    return(TCL_OK);
}

#if DEBUG_PERM_ECASES
/* This big chunk of code is just for debugging the permanent */
/* expect cases */
void
exp_fd_print(slPtr)
struct exp_state_list *slPtr;
{
	if (!slPtr) return;
	printf("%d ",slPtr->esPtr);
	exp_fd_print(slPtr->next);
}

void
exp_i_print(exp_i)
struct exp_i *exp_i;
{
	if (!exp_i) return;
	printf("exp_i %x",exp_i);
	printf((exp_i->direct == EXP_DIRECT)?" direct":" indirect");
	printf((exp_i->duration == EXP_PERMANENT)?" perm":" tmp");
	printf("  ecount = %d\n",exp_i->ecount);
	printf("variable %s, value %s\n",
		((exp_i->variable)?exp_i->variable:"--"),
		((exp_i->value)?exp_i->value:"--"));
	printf("ExpStates: ");
	exp_fd_print(exp_i->state_list); printf("\n");
	exp_i_print(exp_i->next);
}

void
exp_ecase_print(ecase)
struct ecase *ecase;
{
2962
2963
2964
2965
2966
2967
2968

2969


2970
2971


2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992


2993
2994
2995
2996
2997
2998
2999
3000
3001
char **argv;
{
	exp_cmds_print();
	return TCL_OK;
}
#endif /*DEBUG_PERM_ECASES*/


/* need address for passing into cmdExpect */


static int spawn_id_bad = EXP_SPAWN_ID_BAD;
static int spawn_id_user = EXP_SPAWN_ID_USER;



static struct exp_cmd_data
cmd_data[]  = {
{"expect",	exp_proc(Exp_ExpectCmd),	(ClientData)&spawn_id_bad,	0},
{"expect_after",exp_proc(Exp_ExpectGlobalCmd),(ClientData)&exp_cmds[EXP_CMD_AFTER],0},
{"expect_before",exp_proc(Exp_ExpectGlobalCmd),(ClientData)&exp_cmds[EXP_CMD_BEFORE],0},
{"expect_user",	exp_proc(Exp_ExpectCmd),	(ClientData)&spawn_id_user,	0},
{"expect_tty",	exp_proc(Exp_ExpectCmd),	(ClientData)&exp_dev_tty,	0},
{"expect_background",exp_proc(Exp_ExpectGlobalCmd),(ClientData)&exp_cmds[EXP_CMD_BG],0},
{"match_max",	exp_proc(Exp_MatchMaxCmd),	0,	0},
{"remove_nulls",exp_proc(Exp_RemoveNullsCmd),	0,	0},
{"parity",	exp_proc(Exp_ParityCmd),		0,	0},
{"timestamp",	exp_proc(Exp_TimestampCmd),	0,	0},
{0}};

void
exp_init_expect_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);



	Tcl_SetVar(interp,EXPECT_TIMEOUT,INIT_EXPECT_TIMEOUT_LIT,0);
	Tcl_SetVar(interp,EXP_SPAWN_ID_ANY_VARNAME,EXP_SPAWN_ID_ANY_LIT,0);

	exp_cmd_init(&exp_cmds[EXP_CMD_BEFORE],EXP_CMD_BEFORE,EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_AFTER ],EXP_CMD_AFTER, EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_BG    ],EXP_CMD_BG,    EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_FG    ],EXP_CMD_FG,    EXP_TEMPORARY);

	/* preallocate to one element, so future realloc's work */







>
|
>
>
|
<
>
>



|
|
|
|
|
|


|









>
>

<







2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960

2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986

2987
2988
2989
2990
2991
2992
2993
char **argv;
{
	exp_cmds_print();
	return TCL_OK;
}
#endif /*DEBUG_PERM_ECASES*/

void
expExpectVarsInit()
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);


    tsdPtr->timeout = INIT_EXPECT_TIMEOUT;
}

static struct exp_cmd_data
cmd_data[]  = {
{"expect",	Exp_ExpectObjCmd,	0,	(ClientData)0,	0},
{"expect_after",Exp_ExpectGlobalObjCmd, 0,	(ClientData)&exp_cmds[EXP_CMD_AFTER],0},
{"expect_before",Exp_ExpectGlobalObjCmd,0,	(ClientData)&exp_cmds[EXP_CMD_BEFORE],0},
{"expect_user",	Exp_ExpectObjCmd,	0,	(ClientData)&StdinoutPlaceholder,0},
{"expect_tty",	Exp_ExpectObjCmd,	0,	(ClientData)&DevttyPlaceholder,0},
{"expect_background",Exp_ExpectGlobalObjCmd,0,	(ClientData)&exp_cmds[EXP_CMD_BG],0},
{"match_max",	exp_proc(Exp_MatchMaxCmd),	0,	0},
{"remove_nulls",exp_proc(Exp_RemoveNullsCmd),	0,	0},
{"parity",	exp_proc(Exp_ParityCmd),	0,	0},
{"timestamp",	exp_proc(Exp_TimestampCmd),	0,	0},
{0}};

void
exp_init_expect_cmds(interp)
Tcl_Interp *interp;
{
	exp_create_commands(interp,cmd_data);



	Tcl_SetVar(interp,EXPECT_TIMEOUT,INIT_EXPECT_TIMEOUT_LIT,0);


	exp_cmd_init(&exp_cmds[EXP_CMD_BEFORE],EXP_CMD_BEFORE,EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_AFTER ],EXP_CMD_AFTER, EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_BG    ],EXP_CMD_BG,    EXP_PERMANENT);
	exp_cmd_init(&exp_cmds[EXP_CMD_FG    ],EXP_CMD_FG,    EXP_TEMPORARY);

	/* preallocate to one element, so future realloc's work */

Changes to expect.h.

1
2
3
4
5
6
7
8
9
10
11
12
























































































































































































































































































































































































13
14
15
16
17
18
19
/* expect.h - include file for using the expect library, libexpect.a
from C or C++ (i.e., without Tcl)

Written by: Don Libes, [email protected], NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#ifndef _EXPECT_H
#define _EXPECT_H

























































































































































































































































































































































































#include "expect_comm.h"

enum exp_type {
	exp_end = 0,		/* placeholder - no more cases */
	exp_glob,		/* glob-style */
	exp_exact,		/* exact string */












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/* expect.h - include file for using the expect library, libexpect.a
from C or C++ (i.e., without Tcl)

Written by: Don Libes, [email protected], NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#ifndef _EXPECT_H
#define _EXPECT_H

#include <stdio.h>
#include <setjmp.h>

/*
 * tcl.h --
 *
 *	This header file describes the externally-visible facilities
 *	of the Tcl interpreter.
 *
 * Copyright (c) 1987-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1993-1996 Lucent Technologies.
 * Copyright (c) 1998-1999 Scriptics Corporation.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: expect.h,v 5.29 2000/01/06 23:22:05 wart Exp $
 */

#ifndef _TCL
#define _TCL

#ifndef __WIN32__
#   if defined(_WIN32) || defined(WIN32)
#	define __WIN32__
#   endif
#endif

#ifdef __WIN32__
#   ifndef STRICT
#	define STRICT
#   endif
#   ifndef USE_PROTOTYPE
#	define USE_PROTOTYPE 1
#   endif
#   ifndef HAS_STDARG
#	define HAS_STDARG 1
#   endif
#   ifndef USE_PROTOTYPE
#	define USE_PROTOTYPE 1
#   endif

/*
 * Under Windows we need to call Tcl_Alloc in all cases to avoid competing
 * C run-time library issues.
 */

#   ifndef USE_TCLALLOC
#	define USE_TCLALLOC 1
#   endif
#endif /* __WIN32__ */

/*
 * The following definitions set up the proper options for Macintosh
 * compilers.  We use this method because there is no autoconf equivalent.
 */

#ifdef MAC_TCL
#   ifndef HAS_STDARG
#	define HAS_STDARG 1
#   endif
#   ifndef USE_TCLALLOC
#	define USE_TCLALLOC 1
#   endif
#   ifndef NO_STRERROR
#	define NO_STRERROR 1
#   endif
#endif

/*
 * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
 * quotation marks), JOIN joins two arguments.
 */

#define VERBATIM(x) x
#ifdef _MSC_VER
# define STRINGIFY(x) STRINGIFY1(x)
# define STRINGIFY1(x) #x
# define JOIN(a,b) JOIN1(a,b)
# define JOIN1(a,b) a##b
#else
# ifdef RESOURCE_INCLUDED
#  define STRINGIFY(x) STRINGIFY1(x)
#  define STRINGIFY1(x) #x
#  define JOIN(a,b) JOIN1(a,b)
#  define JOIN1(a,b) a##b
# else
#  ifdef __STDC__
#   define STRINGIFY(x) #x
#   define JOIN(a,b) a##b
#  else
#   define STRINGIFY(x) "x"
#   define JOIN(a,b) VERBATIM(a)VERBATIM(b)
#  endif
# endif
#endif

/* 
 * A special definition used to allow this header file to be included 
 * in resource files so that they can get obtain version information from
 * this file.  Resource compilers don't like all the C stuff, like typedefs
 * and procedure declarations, that occur below.
 */

#ifndef RESOURCE_INCLUDED

#ifndef BUFSIZ
#include <stdio.h>
#endif

/*
 * Definitions that allow Tcl functions with variable numbers of
 * arguments to be used with either varargs.h or stdarg.h.  TCL_VARARGS
 * is used in procedure prototypes.  TCL_VARARGS_DEF is used to declare
 * the arguments in a function definiton: it takes the type and name of
 * the first argument and supplies the appropriate argument declaration
 * string for use in the function definition.  TCL_VARARGS_START
 * initializes the va_list data structure and returns the first argument.
 */

#if defined(__STDC__) || defined(HAS_STDARG)
#   include <stdarg.h>

#   define TCL_VARARGS(type, name) (type name, ...)
#   define TCL_VARARGS_DEF(type, name) (type name, ...)
#   define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
#else
#   include <varargs.h>

#   ifdef __cplusplus
#	define TCL_VARARGS(type, name) (type name, ...)
#	define TCL_VARARGS_DEF(type, name) (type va_alist, ...)
#   else
#	define TCL_VARARGS(type, name) ()
#	define TCL_VARARGS_DEF(type, name) (va_alist)
#   endif
#   define TCL_VARARGS_START(type, name, list) \
	(va_start(list), va_arg(list, type))
#endif

/*
 * Macros used to declare a function to be exported by a DLL.
 * Used by Windows, maps to no-op declarations on non-Windows systems.
 * The default build on windows is for a DLL, which causes the DLLIMPORT
 * and DLLEXPORT macros to be nonempty. To build a static library, the
 * macro STATIC_BUILD should be defined.
 */

#ifdef STATIC_BUILD
# define DLLIMPORT
# define DLLEXPORT
#else
# if defined(__WIN32__) && (defined(_MSC_VER) || (defined(__GNUC__) && defined(__declspec)))
#   define DLLIMPORT __declspec(dllimport)
#   define DLLEXPORT __declspec(dllexport)
# else
#  define DLLIMPORT
#  define DLLEXPORT
# endif
#endif

/*
 * These macros are used to control whether functions are being declared for
 * import or export.  If a function is being declared while it is being built
 * to be included in a shared library, then it should have the DLLEXPORT
 * storage class.  If is being declared for use by a module that is going to
 * link against the shared library, then it should have the DLLIMPORT storage
 * class.  If the symbol is beind declared for a static build or for use from a
 * stub library, then the storage class should be empty.
 *
 * The convention is that a macro called BUILD_xxxx, where xxxx is the
 * name of a library we are building, is set on the compile line for sources
 * that are to be placed in the library.  When this macro is set, the
 * storage class will be set to DLLEXPORT.  At the end of the header file, the
 * storage class will be reset to DLLIMPORt.
 */

#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
# define TCL_STORAGE_CLASS DLLEXPORT
#else
# ifdef USE_TCL_STUBS
#  define TCL_STORAGE_CLASS
# else
#  define TCL_STORAGE_CLASS DLLIMPORT
# endif
#endif

/*
 * Definitions that allow this header file to be used either with or
 * without ANSI C features like function prototypes.  */

#undef _ANSI_ARGS_
#undef CONST

#if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE)
#   define _USING_PROTOTYPES_ 1
#   define _ANSI_ARGS_(x)	x
#   define CONST const
#else
#   define _ANSI_ARGS_(x)	()
#   define CONST
#endif

#ifdef __cplusplus
#   define EXTERN extern "C" TCL_STORAGE_CLASS
#else
#   define EXTERN extern TCL_STORAGE_CLASS
#endif

/*
 * Macro to use instead of "void" for arguments that must have
 * type "void *" in ANSI C;  maps them to type "char *" in
 * non-ANSI systems.
 */
#ifndef __WIN32__
#ifndef VOID
#   ifdef __STDC__
#       define VOID void
#   else
#       define VOID char
#   endif
#endif
#else /* __WIN32__ */
/*
 * The following code is copied from winnt.h
 */
#ifndef VOID
#define VOID void
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
#endif
#endif /* __WIN32__ */

/*
 * Miscellaneous declarations.
 */

#ifndef NULL
#define NULL 0
#endif

typedef struct Tcl_RegExp_ *Tcl_RegExp;

/*
 * The following declarations either map ckalloc and ckfree to
 * malloc and free, or they map them to procedures with all sorts
 * of debugging hooks defined in tclCkalloc.c.
 */

#ifdef TCL_MEM_DEBUG

#  define Tcl_Alloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
#  define Tcl_Free(x)  Tcl_DbCkfree(x, __FILE__, __LINE__)
#  define Tcl_Realloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)
#  define ckalloc(x) Tcl_DbCkalloc(x, __FILE__, __LINE__)
#  define ckfree(x)  Tcl_DbCkfree(x, __FILE__, __LINE__)
#  define ckrealloc(x,y) Tcl_DbCkrealloc((x), (y),__FILE__, __LINE__)

#else

/*
 * If USE_TCLALLOC is true, then we need to call Tcl_Alloc instead of
 * the native malloc/free.  The only time USE_TCLALLOC should not be
 * true is when compiling the Tcl/Tk libraries on Unix systems.  In this
 * case we can safely call the native malloc/free directly as a performance
 * optimization.
 */

#  if USE_TCLALLOC
#     define ckalloc(x) Tcl_Alloc(x)
#     define ckfree(x) Tcl_Free(x)
#     define ckrealloc(x,y) Tcl_Realloc(x,y)
#  else
#     define ckalloc(x) malloc(x)
#     define ckfree(x)  free(x)
#     define ckrealloc(x,y) realloc(x,y)
#  endif
#  define Tcl_DumpActiveMemory(x)
#  define Tcl_ValidateAllMemory(x,y)

#endif /* !TCL_MEM_DEBUG */


/*
 * These function have been renamed. The old names are deprecated, but we
 * define these macros for backwards compatibilty.
 */

#define Tcl_Ckalloc Tcl_Alloc
#define Tcl_Ckfree Tcl_Free
#define Tcl_Ckrealloc Tcl_Realloc
#define Tcl_Return Tcl_SetResult
#define Tcl_TildeSubst Tcl_TranslateFileName

/*
 * In later releases, Tcl_Panic will be the correct name to use.  For now
 * we leave it as panic to avoid breaking existing binaries.
 */

#define Tcl_Panic panic
#define Tcl_PanicVA panicVA

#endif /* RESOURCE_INCLUDED */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCL */

/*
 * end of tcl.h definitions
 */


/*
 * regexp definitions - from tcl8.0/tclRegexp.h
 */

/*
 * Definitions etc. for regexp(3) routines.
 *
 * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
 * not the System V one.
 *
 * RCS: @(#) $Id: expect.h,v 5.29 2000/01/06 23:22:05 wart Exp $
 */

#ifndef _REGEXP
#define _REGEXP 1

#ifdef BUILD_tcl
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLEXPORT
#endif

/*
 * NSUBEXP must be at least 10, and no greater than 117 or the parser
 * will not work properly.
 */

#define NSUBEXP  20

typedef struct regexp {
	char *startp[NSUBEXP];
	char *endp[NSUBEXP];
	char regstart;		/* Internal use only. */
	char reganch;		/* Internal use only. */
	char *regmust;		/* Internal use only. */
	int regmlen;		/* Internal use only. */
	char program[1];	/* Unwarranted chumminess with compiler. */
} regexp;

EXTERN regexp *TclRegComp _ANSI_ARGS_((char *exp));
EXTERN int TclRegExec _ANSI_ARGS_((regexp *prog, char *string, char *start));
EXTERN void TclRegSub _ANSI_ARGS_((regexp *prog, char *source, char *dest));
EXTERN void exp_TclRegError _ANSI_ARGS_((char *msg));
EXTERN char *TclGetRegError _ANSI_ARGS_((void));

# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT

#endif /* REGEXP */


/*
 * end of regexp definitions
 */


/*
 * finally - expect-specific definitions
 */

#include "expect_comm.h"

enum exp_type {
	exp_end = 0,		/* placeholder - no more cases */
	exp_glob,		/* glob-style */
	exp_exact,		/* exact string */
46
47
48
49
50
51
52



53


54
55
56
57





58
59
60


61
62
63
64
65
66
67
EXTERN char *exp_pty_slave_name;	/* name of pty slave device if we */
					/* do allocation */
EXTERN char *exp_stty_init;		/* initial stty args */
EXTERN int exp_ttycopy;			/* copy tty parms from /dev/tty */
EXTERN int exp_ttyinit;			/* set tty parms to sane state */
EXTERN int exp_console;			/* redirect console */




EXTERN jmp_buf exp_readenv;		/* for interruptable read() */


EXTERN int exp_reading;			/* whether we can longjmp or not */
#define EXP_ABORT	1		/* abort read */
#define EXP_RESTART	2		/* restart read */






EXTERN int exp_logfile_all;
EXTERN FILE *exp_debugfile;
EXTERN FILE *exp_logfile;



EXTERN int exp_disconnect _ANSI_ARGS_((void));
EXTERN FILE *exp_popen	_ANSI_ARGS_((char *command));
EXTERN void (*exp_child_exec_prelude) _ANSI_ARGS_((void));

#ifndef EXP_DEFINE_FNS
EXTERN int exp_spawnl	_ANSI_ARGS_(TCL_VARARGS(char *,file));







>
>
>

>
>




>
>
>
>
>



>
>







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
EXTERN char *exp_pty_slave_name;	/* name of pty slave device if we */
					/* do allocation */
EXTERN char *exp_stty_init;		/* initial stty args */
EXTERN int exp_ttycopy;			/* copy tty parms from /dev/tty */
EXTERN int exp_ttyinit;			/* set tty parms to sane state */
EXTERN int exp_console;			/* redirect console */

#ifdef HAVE_SIGLONGJMP
EXTERN sigjmp_buf exp_readenv;		/* for interruptable read() */
#else
EXTERN jmp_buf exp_readenv;		/* for interruptable read() */
#endif /* HAVE_SIGLONGJMP */

EXTERN int exp_reading;			/* whether we can longjmp or not */
#define EXP_ABORT	1		/* abort read */
#define EXP_RESTART	2		/* restart read */

EXTERN int exp_is_debugging;
EXTERN int exp_loguser;

EXTERN void (*exp_close_in_child)();	/* procedure to close files in child */
EXTERN void exp_slave_control _ANSI_ARGS_((int,int));
EXTERN int exp_logfile_all;
EXTERN FILE *exp_debugfile;
EXTERN FILE *exp_logfile;
extern void exp_debuglog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));
extern void exp_errorlog _ANSI_ARGS_(TCL_VARARGS(char *,fmt));

EXTERN int exp_disconnect _ANSI_ARGS_((void));
EXTERN FILE *exp_popen	_ANSI_ARGS_((char *command));
EXTERN void (*exp_child_exec_prelude) _ANSI_ARGS_((void));

#ifndef EXP_DEFINE_FNS
EXTERN int exp_spawnl	_ANSI_ARGS_(TCL_VARARGS(char *,file));

Changes to expect.man.

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
Standard I/O is redirected to /dev/null.
.IP
The following fragment uses
.B disconnect
to continue running the script in the background.  
.nf

    if [fork]!=0 exit
    disconnect
    . . .

.fi
The following script reads a password, and then runs a program
every hour that demands a password each time it is run.  The script supplies
the password so that you only have to type it once.
(See the
.B stty
command which demonstrates how to turn off password echoing.)
.nf

    send_user "password?\\ "
    expect_user -re "(.*)\\n"
    for {} 1 {} {
        if [fork]!=0 {sleep 3600;continue}
        disconnect
        spawn priv_prog
        expect Password:
        send "$expect_out(1,string)\\r"
        . . .
        exit
    }







|















|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
Standard I/O is redirected to /dev/null.
.IP
The following fragment uses
.B disconnect
to continue running the script in the background.  
.nf

    if {[fork]!=0} exit
    disconnect
    . . .

.fi
The following script reads a password, and then runs a program
every hour that demands a password each time it is run.  The script supplies
the password so that you only have to type it once.
(See the
.B stty
command which demonstrates how to turn off password echoing.)
.nf

    send_user "password?\\ "
    expect_user -re "(.*)\\n"
    for {} 1 {} {
        if {[fork]!=0} {sleep 3600;continue}
        disconnect
        spawn priv_prog
        expect Password:
        send "$expect_out(1,string)\\r"
        . . .
        exit
    }
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461




462
463
464
465
466
467
468

.I status
(or 0 if not specified) is returned as the exit status of
.BR Expect .
.B exit
is implicitly executed if the end of the script is reached.
.TP
.B exp_continue
The command
.B exp_continue
allows
.B expect
itself to continue
executing rather than returning as it normally would.
(See




.B expect
for more information.)
.TP
.BI exp_internal " [\-f file] value"
causes further commands to send diagnostic information internal to
.B Expect
to stderr if







|





|
|
>
>
>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472

.I status
(or 0 if not specified) is returned as the exit status of
.BR Expect .
.B exit
is implicitly executed if the end of the script is reached.
.TP
\fBexp_continue\fR [-continue_timer]
The command
.B exp_continue
allows
.B expect
itself to continue
executing rather than returning as it normally would. By
default
.B exp_continue
resets the timeout timer. The
.I -continue_timer
flag prevents timer from being restarted. (See
.B expect
for more information.)
.TP
.BI exp_internal " [\-f file] value"
causes further commands to send diagnostic information internal to
.B Expect
to stderr if
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
flush the output buffer without reading any more output from the
process.
.IP
Normally, the matched output is discarded from Expect's internal buffers.
This may be prevented by prefixing a pattern with the
.B \-notransfer
flag.  This flag is especially useful in experimenting (and can be
abbreviated to "-n" for convenience while experimenting).

The spawn id associated with the matching output (or eof or
full_buffer) is stored in
.IR expect_out(spawn_id) .

The
.B \-timeout







|







783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
flush the output buffer without reading any more output from the
process.
.IP
Normally, the matched output is discarded from Expect's internal buffers.
This may be prevented by prefixing a pattern with the
.B \-notransfer
flag.  This flag is especially useful in experimenting (and can be
abbreviated to "-not" for convenience while experimenting).

The spawn id associated with the matching output (or eof or
full_buffer) is stored in
.IR expect_out(spawn_id) .

The
.B \-timeout
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
If the current process does not catch job control signals,
it will stop if sent a stop signal (by default ^Z).
To restart it, send a continue signal (such as by "kill \-CONT <pid>").
If you really want to send a SIGSTOP to such a process (by ^Z),
consider spawning csh first and then running your program.
On the other hand, if you want to send a SIGSTOP to
.B Expect
itself, first press the escape character, and then press ^Z.
.IP
String-body pairs can be used as a shorthand for avoiding having
to enter the interpreter and execute commands interactively.  The previous
terminal mode is used while the body of a string-body pair is being executed.
.IP
For speed, actions execute in raw mode by default.  The
.B \-reset







|







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
If the current process does not catch job control signals,
it will stop if sent a stop signal (by default ^Z).
To restart it, send a continue signal (such as by "kill \-CONT <pid>").
If you really want to send a SIGSTOP to such a process (by ^Z),
consider spawning csh first and then running your program.
On the other hand, if you want to send a SIGSTOP to
.B Expect
itself, first call interpreter (perhaps by using an escape character), and then press ^Z.
.IP
String-body pairs can be used as a shorthand for avoiding having
to enter the interpreter and execute commands interactively.  The previous
terminal mode is used while the body of a string-body pair is being executed.
.IP
For speed, actions execute in raw mode by default.  The
.B \-reset
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
flags are used.  A \-i flag implies a \-o flag.

It is possible to change the processes that are being interacted with
by using indirect spawn ids.  (Indirect spawn ids are described in the
section on the expect command.)  Indirect spawn ids may be specified
with the -i, -u, -input, or -output flags.
.TP
.B interpreter
causes the user to be interactively prompted for
.B Expect
and Tcl commands.
The result of each command is printed.
.IP
Actions such as
.B break







|







1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
flags are used.  A \-i flag implies a \-o flag.

It is possible to change the processes that are being interacted with
by using indirect spawn ids.  (Indirect spawn ids are described in the
section on the expect command.)  Indirect spawn ids may be specified
with the -i, -u, -input, or -output flags.
.TP
.B interpreter " [args]"
causes the user to be interactively prompted for
.B Expect
and Tcl commands.
The result of each command is printed.
.IP
Actions such as
.B break
1462
1463
1464
1465
1466
1467
1468






1469
1470
1471
1472
1473
1474
1475
prompt.  If a statement has open quotes, parens, braces, or brackets, a
secondary prompt (by default "+> ") is issued upon newline.  The secondary
prompt may be set by defining a procedure called "prompt2".
.IP
During
.BR interpreter ,
cooked mode is used, even if the its caller was using raw mode.






.TP
.BI log_file " [args] [[\-a] file]"
If a filename is provided,
.B log_file
will record a transcript of the session (beginning at that point) in the file.
.B log_file
will stop recording if no argument is given.  Any previous log file is closed.







>
>
>
>
>
>







1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
prompt.  If a statement has open quotes, parens, braces, or brackets, a
secondary prompt (by default "+> ") is issued upon newline.  The secondary
prompt may be set by defining a procedure called "prompt2".
.IP
During
.BR interpreter ,
cooked mode is used, even if the its caller was using raw mode.
.IP
If stdin is closed,
.B interpreter
will return unless the
.B \-eof
flag is used, in which case the subsequent argument is invoked.
.TP
.BI log_file " [args] [[\-a] file]"
If a filename is provided,
.B log_file
will record a transcript of the session (beginning at that point) in the file.
.B log_file
will stop recording if no argument is given.  Any previous log file is closed.
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
The
.B \-i
flag declares that the string be sent to the named spawn_id.
If the spawn_id is
.IR user_spawn_id ,
and the terminal is in raw mode, newlines in the string are translated
to return-newline
sequences so that they appear as it the terminal was in cooked mode.
The
.B \-raw
flag disables this translation.

The
.BR \-null
flag sends null characters (0 bytes).  By default, one null is sent.







|







1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
The
.B \-i
flag declares that the string be sent to the named spawn_id.
If the spawn_id is
.IR user_spawn_id ,
and the terminal is in raw mode, newlines in the string are translated
to return-newline
sequences so that they appear as if the terminal was in cooked mode.
The
.B \-raw
flag disables this translation.

The
.BR \-null
flag sends null characters (0 bytes).  By default, one null is sent.
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
.I tty_spawn_id
is a global variable containing a descriptor which refers to /dev/tty.
If /dev/tty does not exist (such as in a cron, at, or batch script), then
.I tty_spawn_id
is not defined.  This may be tested as:
.nf

    if [info vars tty_spawn_id] {
        # /dev/tty exists
    } else {
        # /dev/tty doesn't exist
        # probably in cron, batch, or at script
    }

.fi







|







1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
.I tty_spawn_id
is a global variable containing a descriptor which refers to /dev/tty.
If /dev/tty does not exist (such as in a cron, at, or batch script), then
.I tty_spawn_id
is not defined.  This may be tested as:
.nf

    if {[info vars tty_spawn_id]} {
        # /dev/tty exists
    } else {
        # /dev/tty doesn't exist
        # probably in cron, batch, or at script
    }

.fi
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
exit SIGINT", this will override the debugger trap.  This is useful
if you want to prevent users from getting to the debugger at all.

If you want to define your own trap on SIGINT but still trap to the
debugger when it is running, use:
.nf

    if ![exp_debug] {trap mystuff SIGINT}

.fi
Alternatively, you can trap to the debugger using some other signal.

.B trap
will not let you override the action for SIGALRM as this is used internally
to







|







2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
exit SIGINT", this will override the debugger trap.  This is useful
if you want to prevent users from getting to the debugger at all.

If you want to define your own trap on SIGINT but still trap to the
debugger when it is running, use:
.nf

    if {![exp_debug]} {trap mystuff SIGINT}

.fi
Alternatively, you can trap to the debugger using some other signal.

.B trap
will not let you override the action for SIGALRM as this is used internally
to
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
.B expect
variants and
.BR interact )
use a heuristic to decide if the list is actually one argument or many.
The heuristic can fail only in the case when the list actually does
represent a single argument which has multiple embedded \\n's with
non-whitespace characters between them.  This seems sufficiently improbable,
however the argument "-brace" can be used to force a single argument
to be handled as a single argument.  This could conceivably be used
with machine-generated Expect code.
.SH BUGS
It was really tempting to name the program "sex" (for either "Smart EXec"
or "Send-EXpect"), but good sense (or perhaps just Puritanism) prevailed.

On some systems, when a shell is spawned, it complains about not being







|







2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
.B expect
variants and
.BR interact )
use a heuristic to decide if the list is actually one argument or many.
The heuristic can fail only in the case when the list actually does
represent a single argument which has multiple embedded \\n's with
non-whitespace characters between them.  This seems sufficiently improbable,
however the argument "\-nobrace" can be used to force a single argument
to be handled as a single argument.  This could conceivably be used
with machine-generated Expect code.
.SH BUGS
It was really tempting to name the program "sex" (for either "Smart EXec"
or "Send-EXpect"), but good sense (or perhaps just Puritanism) prevailed.

On some systems, when a shell is spawned, it complains about not being

Changes to expect_cf.h.in.

1
2
3
4
5
6
7

8
9
10
11
12
13
14
/*
 * Check for headers
 */
#ifndef __EXPECT_CF_H__
#define __EXPECT_CF_H__

#undef NO_STDLIB_H		/* Tcl requires this name */

#undef HAVE_STDARG_H
#undef HAVE_VARARGS_H
#undef HAVE_STROPTS_H
#undef HAVE_SYSCONF_H
#undef HAVE_SYS_FCNTL_H
#undef HAVE_SYS_WAIT_H
#undef HAVE_SYS_BSDTYPES_H	/* nice ISC special */







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * Check for headers
 */
#ifndef __EXPECT_CF_H__
#define __EXPECT_CF_H__

#undef NO_STDLIB_H		/* Tcl requires this name */
#undef NO_UNION_WAIT
#undef HAVE_STDARG_H
#undef HAVE_VARARGS_H
#undef HAVE_STROPTS_H
#undef HAVE_SYSCONF_H
#undef HAVE_SYS_FCNTL_H
#undef HAVE_SYS_WAIT_H
#undef HAVE_SYS_BSDTYPES_H	/* nice ISC special */
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
#undef HAVE_INTTYPES_H
#undef HAVE_TIOCGWINSZ_IN_TERMIOS_H
#undef HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H

#undef pid_t
#undef RETSIGTYPE
#undef TIME_WITH_SYS_TIME	/* ok to include both time.h and sys/time.h */


/*
 * This section is for compile macros needed by
 * everything else.
 */

/*
 * Check for functions
 */
#undef HAVE_MEMCPY
#undef HAVE_SYSCONF
#undef SIMPLE_EVENT
#undef HAVE_STRFTIME
#undef HAVE_MEMMOVE
#undef HAVE_TIMEZONE		/* timezone() a la Pyramid */

#undef HAVE_STRCHR

#ifndef HAVE_STRCHR
#define strchr(s,c) index(s,c)
#endif /* HAVE_STRCHR */

/*







>















>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#undef HAVE_INTTYPES_H
#undef HAVE_TIOCGWINSZ_IN_TERMIOS_H
#undef HAVE_TCGETS_OR_TCGETA_IN_TERMIOS_H

#undef pid_t
#undef RETSIGTYPE
#undef TIME_WITH_SYS_TIME	/* ok to include both time.h and sys/time.h */
#undef SETPGRP_VOID		/* if setpgrp takes 0 args */

/*
 * This section is for compile macros needed by
 * everything else.
 */

/*
 * Check for functions
 */
#undef HAVE_MEMCPY
#undef HAVE_SYSCONF
#undef SIMPLE_EVENT
#undef HAVE_STRFTIME
#undef HAVE_MEMMOVE
#undef HAVE_TIMEZONE		/* timezone() a la Pyramid */
#undef HAVE_SIGLONGJMP
#undef HAVE_STRCHR

#ifndef HAVE_STRCHR
#define strchr(s,c) index(s,c)
#endif /* HAVE_STRCHR */

/*

Changes to expect_comm.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* expectcomm.h - public symbols common to both expect.h and expect_tcl.h

Written by: Don Libes, [email protected], NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#ifndef _EXPECT_COMM_H
#define _EXPECT_COMM_H

#if 0
#include "expect_cf.h"
#endif

#include <stdio.h>
#include <setjmp.h>

/* since it's possible that the caller may include tcl.h before including
   this file, we cannot include varargs/stdargs ourselves */

/* Much of the following stdarg/prototype support is taken from tcl.h
 * (7.5) with modifications.  What's going on here is that don't want
 * to simply include tcl.h everywhere, because one of the files is the
 * Tcl-less Expect library.)
 */


/* Definitions that allow Tcl functions with variable numbers of
 * arguments to be used with either varargs.h or stdarg.h.
 * TCL_VARARGS is used in procedure prototypes.  TCL_VARARGS_DEF is
 * used to declare the arguments in a function definiton: it takes the
 * type and name of the first argument and supplies the appropriate
 * argument declaration string for use in the function definition.
 * TCL_VARARGS_START initializes the va_list data structure and
 * returns the first argument.  */

/* in Tcl 7.5, Tcl now supplies these definitions */
#if !defined(TCL_VARARGS)
#  if defined(__STDC__) || defined(HAVE_STDARG_H)
#   include <stdarg.h>
#   define TCL_VARARGS(type, name) (type name, ...)
#   define TCL_VARARGS_DEF(type, name) (type name, ...)
#   define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
#  else
#   include <varargs.h>
#   ifdef __cplusplus
#	define TCL_VARARGS(type, name) (type name, ...)
#	define TCL_VARARGS_DEF(type, name) (type va_alist, ...)
#   else
#	define TCL_VARARGS(type, name) ()
#	define TCL_VARARGS_DEF(type, name) (va_alist)
#   endif
#   define TCL_VARARGS_START(type, name, list) \
	(va_start(list), va_arg(list, type))
#  endif /* use stdarg.h */

/*
 * Definitions that allow this header file to be used either with or
 * without ANSI C features like function prototypes.
 */

#  undef _ANSI_ARGS_
#  undef CONST

#  if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) || defined(__cplusplus) || defined(USE_PROTOTYPE)
#    define _USING_PROTOTYPES_ 1
#    define _ANSI_ARGS_(x)	x
#    define CONST const
#  else
#    define _ANSI_ARGS_(x)	()
#    define CONST
#  endif

#  ifdef __cplusplus
#    define EXTERN extern "C"
#  else
#    define EXTERN extern
#  endif

#endif /* defined(TCL_VARARGS) */

/* Arghhh!  Tcl pulls in all of tcl.h in order to get the regexp funcs */
/* Tcl offers us a way to avoid this: temporarily define _TCL.  Here goes: */

#ifdef EXP_AVOID_INCLUDING_TCL_H
# ifdef _TCL
#  define EXP__TCL_WAS_DEFINED
# else
#  define _TCL
# endif
#endif

#include "tclRegexp.h"

/* clean up the mess */
#ifdef EXP_AVOID_INCLUDING_TCL_H
# ifdef EXP__TCL_WAS_DEFINED
#  undef EXP__TCL_WAS_DEFINED
# else
#  undef _TCL
# endif
#endif

#if 0
/* moved to exp_int.h so expect_cf.h no longer needs to be installed */
#ifdef NO_STDLIB_H
#  include "../compat/stdlib.h"
#else
#  include <stdlib.h>		/* for malloc */
#endif /*NO_STDLIB_H*/
#endif

/* common return codes for Expect functions */
/* The library actually only uses TIMEOUT and EOF */
#define EXP_ABEOF	-1	/* abnormal eof in Expect */
				/* when in library, this define is not used. */
				/* Instead "-1" is used literally in the */
				/* usual sense to check errors in system */
				/* calls */












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12






































































































13
14
15
16
17
18
19
/* expectcomm.h - public symbols common to both expect.h and expect_tcl.h

Written by: Don Libes, [email protected], NIST, 12/3/90

Design and implementation of this program was paid for by U.S. tax
dollars.  Therefore it is public domain.  However, the author and NIST
would appreciate credit if this program or parts of it are used.
*/

#ifndef _EXPECT_COMM_H
#define _EXPECT_COMM_H







































































































/* common return codes for Expect functions */
/* The library actually only uses TIMEOUT and EOF */
#define EXP_ABEOF	-1	/* abnormal eof in Expect */
				/* when in library, this define is not used. */
				/* Instead "-1" is used literally in the */
				/* usual sense to check errors in system */
				/* calls */
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170

171

172
#define EXP_TCLCNTTIMER	-22
#define EXP_TCLBRK	-23
#define EXP_TCLCNTEXP	-24
#define EXP_TCLRETTCL	-25

/* yet more TCL return codes */
/* Tcl does not safely provide a way to define the values of these, so */
/* use ridiculously numbers for safety */
#define EXP_CONTINUE		-101	/* continue expect command */
					/* and restart timer */
#define EXP_CONTINUE_TIMER	-102	/* continue expect command */
					/* and continue timer */
#define EXP_TCL_RETURN		-103	/* converted by interact */
					/* and interpeter from */
					/* inter_return into */
					/* TCL_RETURN*/

#define EXP_TIME_INFINITY	-1
#define EXP_SPAWN_ID_BAD	-1

EXTERN int exp_is_debugging;
EXTERN int exp_loguser;
EXTERN int exp_disconnected;		/* proc. disc'd from controlling tty */

EXTERN void (*exp_close_in_child)();	/* procedure to close files in child */
EXTERN void exp_close_tcl_files();	/* deflt proc: close all Tcl's files */

EXTERN void exp_slave_control _ANSI_ARGS_((int,int));


EXTERN char *exp_pty_error;		/* place to pass a string generated */
					/* deep in the innards of the pty */
					/* code but needed by anyone */



#endif /* _EXPECT_COMM_H */







|









<
<
|
<
<
<
|
<
<
|
<
>




>

>

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53


54



55


56

57
58
59
60
61
62
63
64
65
#define EXP_TCLCNTTIMER	-22
#define EXP_TCLBRK	-23
#define EXP_TCLCNTEXP	-24
#define EXP_TCLRETTCL	-25

/* yet more TCL return codes */
/* Tcl does not safely provide a way to define the values of these, so */
/* use ridiculously different numbers for safety */
#define EXP_CONTINUE		-101	/* continue expect command */
					/* and restart timer */
#define EXP_CONTINUE_TIMER	-102	/* continue expect command */
					/* and continue timer */
#define EXP_TCL_RETURN		-103	/* converted by interact */
					/* and interpeter from */
					/* inter_return into */
					/* TCL_RETURN*/



/*



 * Everything below here should eventually be moved into expect.h


 * and Expect-thread-safe variables.

 */

EXTERN char *exp_pty_error;		/* place to pass a string generated */
					/* deep in the innards of the pty */
					/* code but needed by anyone */
EXTERN int exp_disconnected;		/* proc. disc'd from controlling tty */


#endif /* _EXPECT_COMM_H */

Changes to expect_tcl.h.

10
11
12
13
14
15
16








17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
*/

#ifndef _EXPECT_TCL_H
#define _EXPECT_TCL_H

#include "expect_comm.h"









EXTERN int exp_cmdlinecmds;
EXTERN int exp_interactive;
EXTERN FILE *exp_cmdfile;
EXTERN char *exp_cmdfilename;
EXTERN int exp_getpid;	/* pid of Expect itself */
EXTERN int exp_buffer_command_input;

EXTERN int exp_tcl_debugger_available;

EXTERN Tcl_Interp *exp_interp;

#define Exp_Init Expect_Init
EXTERN int	Expect_Init _ANSI_ARGS_((Tcl_Interp *));	/* for Tcl_AppInit apps */
EXTERN void	exp_parse_argv _ANSI_ARGS_((Tcl_Interp *,int argc,char **argv));
EXTERN int	exp_interpreter _ANSI_ARGS_((Tcl_Interp *));
EXTERN int	exp_interpret_cmdfile _ANSI_ARGS_((Tcl_Interp *,FILE *));
EXTERN int	exp_interpret_cmdfilename _ANSI_ARGS_((Tcl_Interp *,char *));
EXTERN void	exp_interpret_rcfiles _ANSI_ARGS_((Tcl_Interp *,int my_rc,int sys_rc));

EXTERN char *	exp_cook _ANSI_ARGS_((char *s,int *len));

EXTERN void	exp_close_on_exec _ANSI_ARGS_((int));

			/* app-specific exit handler */
EXTERN void	(*exp_app_exit)_ANSI_ARGS_((Tcl_Interp *));
EXTERN void	exp_exit _ANSI_ARGS_((Tcl_Interp *,int status));
EXTERN void	exp_exit_handlers _ANSI_ARGS_((ClientData));

EXTERN void	exp_error _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));

#endif /* _EXPECT_TCL_H */







>
>
>
>
>
>
>
>














|






|



<





10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
*/

#ifndef _EXPECT_TCL_H
#define _EXPECT_TCL_H

#include "expect_comm.h"

/*
 * This is a convenience macro used to initialize a thread local storage ptr.
 * Stolen from tclInt.h
 */
#ifndef TCL_TSD_INIT
#define TCL_TSD_INIT(keyPtr)	(ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData))
#endif

EXTERN int exp_cmdlinecmds;
EXTERN int exp_interactive;
EXTERN FILE *exp_cmdfile;
EXTERN char *exp_cmdfilename;
EXTERN int exp_getpid;	/* pid of Expect itself */
EXTERN int exp_buffer_command_input;

EXTERN int exp_tcl_debugger_available;

EXTERN Tcl_Interp *exp_interp;

#define Exp_Init Expect_Init
EXTERN int	Expect_Init _ANSI_ARGS_((Tcl_Interp *));	/* for Tcl_AppInit apps */
EXTERN void	exp_parse_argv _ANSI_ARGS_((Tcl_Interp *,int argc,char **argv));
EXTERN int	exp_interpreter _ANSI_ARGS_((Tcl_Interp *,Tcl_Obj *));
EXTERN int	exp_interpret_cmdfile _ANSI_ARGS_((Tcl_Interp *,FILE *));
EXTERN int	exp_interpret_cmdfilename _ANSI_ARGS_((Tcl_Interp *,char *));
EXTERN void	exp_interpret_rcfiles _ANSI_ARGS_((Tcl_Interp *,int my_rc,int sys_rc));

EXTERN char *	exp_cook _ANSI_ARGS_((char *s,int *len));

EXTERN void	expCloseOnExec _ANSI_ARGS_((int));

			/* app-specific exit handler */
EXTERN void	(*exp_app_exit)_ANSI_ARGS_((Tcl_Interp *));

EXTERN void	exp_exit_handlers _ANSI_ARGS_((ClientData));

EXTERN void	exp_error _ANSI_ARGS_(TCL_VARARGS(Tcl_Interp *,interp));

#endif /* _EXPECT_TCL_H */

Changes to fixline1.

1
2
3
4
5
6
7
8
9
10
11


12







13
#!expect --
# Synopsis: fixline1 newpath < input > output
# Author: Don Libes

# Description: change first line of script to reflect new binary
# try to match any of the following first lines
#!expect ...
#!../expect ...
#!expectk ...
#!foo/bar/expectk ...
#


regsub "^#!(.*/)*(.*)" [gets stdin] "#!$argv/\\2" line1







puts -nonewline "$line1\n[read stdin]"











>
>
|
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!expect --
# Synopsis: fixline1 newpath < input > output
# Author: Don Libes

# Description: change first line of script to reflect new binary
# try to match any of the following first lines
#!expect ...
#!../expect ...
#!expectk ...
#!foo/bar/expectk ...
#
if {0} {
    # Original scheme, but this can wire in a platform-specific path
    regsub "^#!(.*/)*(.*)" [gets stdin] "#!$argv/\\2" line1
} else {
    set header "#!/bin/sh\n"
    append header "# \\\n"
    append header {exec expect "$0" ${1+"$@"}}

    regsub "^#!(.*/)*(.*)" [gets stdin] $header line1
}
puts -nonewline "$line1\n[read stdin]"

Changes to pty_sgttyb.c.

22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
#include <signal.h>
#include <setjmp.h>
#include "expect_cf.h"
#include "exp_rename.h"
#include "exp_tty_in.h"
#include "exp_pty.h"

void debuglog();


#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

static char	master_name[] = "/dev/ptyXX";	/* master */







|
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <signal.h>
#include <setjmp.h>
#include "expect_cf.h"
#include "exp_rename.h"
#include "exp_tty_in.h"
#include "exp_pty.h"

void expDiagLog();
void expDiagLogU();

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

static char	master_name[] = "/dev/ptyXX";	/* master */
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

#if experimental
	/* code to allocate force expect to get a controlling tty */
	/* even if it doesn't start with one (i.e., under cron). */
	/* This code is not necessary, but helpful for testing odd things. */
	if (exp_dev_tty == -1) {
		/* give ourselves a controlling tty */
		int master = getptymaster();
		fcntl(master,F_SETFD,1);	/* close-on-exec */
		setpgrp(0,0);
		close(0);
		close(1);
		getptyslave(exp_get_var(exp_interp,"stty_init"));
		close(2);
		fcntl(0,F_DUPFD,2);		/* dup 0 onto 2 */
	}
#endif

	knew_dev_tty = (exp_dev_tty != -1);
	if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0);
}

/* returns fd of master end of pseudotty */
int
getptymaster()
{
	int master = -1;
	char *hex, *bank;
	struct stat statbuf;

	exp_pty_error = 0;








|




|











|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

#if experimental
	/* code to allocate force expect to get a controlling tty */
	/* even if it doesn't start with one (i.e., under cron). */
	/* This code is not necessary, but helpful for testing odd things. */
	if (exp_dev_tty == -1) {
		/* give ourselves a controlling tty */
		int master = exp_getptymaster();
		fcntl(master,F_SETFD,1);	/* close-on-exec */
		setpgrp(0,0);
		close(0);
		close(1);
		exp_getptyslave(exp_get_var(exp_interp,"stty_init"));
		close(2);
		fcntl(0,F_DUPFD,2);		/* dup 0 onto 2 */
	}
#endif

	knew_dev_tty = (exp_dev_tty != -1);
	if (knew_dev_tty) ttytype(GET_TTYTYPE,exp_dev_tty,0,0,(char *)0);
}

/* returns fd of master end of pseudotty */
int
exp_getptymaster()
{
	int master = -1;
	char *hex, *bank;
	struct stat statbuf;

	exp_pty_error = 0;

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
exp_slave_control(master,control)
int master;
int control;
{
}

int
getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave;

	if (0 > (slave = open(slave_name, O_RDWR))) return(-1);







|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
exp_slave_control(master,control)
int master;
int control;
{
}

int
exp_getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave;

	if (0 > (slave = open(slave_name, O_RDWR))) return(-1);

Changes to pty_termios.c.

23
24
25
26
27
28
29










30






31
32
33
34
35
36
37

   The functions are relatively small but painful enough that I don't care
   to recode them.  You may, if you absolutely want to get rid of any
   vestiges of Tcl.
*/
extern char *TclGetRegError();



















#if defined(HAVE_PTYM) && defined(HAVE_PTMX)
/*
 * HP-UX 10.0 with streams (optional) have both PTMX and PTYM.  I don't
 * know which is preferred but seeing as how the HP trap stuff is so
 * unusual, it is probably safer to stick with the native HP pty support,
 * too.







>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

   The functions are relatively small but painful enough that I don't care
   to recode them.  You may, if you absolutely want to get rid of any
   vestiges of Tcl.
*/
extern char *TclGetRegError();

#if defined(HAVE_PTMX_BSD) && defined(HAVE_PTMX)
/*
 * Some systems have both PTMX and PTMX_BSD.
 * In fact, alphaev56-dec-osf4.0e has /dev/pts, /dev/pty, /dev/ptym,
 * /dev/ptm, /dev/ptmx, and /dev/ptmx_bsd
 * Suggestion from Martin Buchholz <[email protected]> is that BSD
 * is usually deprecated and so should be here.
 */
#undef HAVE_PTMX_BSD
#endif

/* Linux and Digital systems can be configured to have both.
According to Ashley Pittman <[email protected]>, Digital works better
with openpty which supports 4000 while ptmx supports 60. */
#if defined(HAVE_OPENPTY) && defined(HAVE_PTMX)
#undef HAVE_PTMX
#endif

#if defined(HAVE_PTYM) && defined(HAVE_PTMX)
/*
 * HP-UX 10.0 with streams (optional) have both PTMX and PTYM.  I don't
 * know which is preferred but seeing as how the HP trap stuff is so
 * unusual, it is probably safer to stick with the native HP pty support,
 * too.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
#  include <fcntl.h>
#endif

#if defined(_SEQUENT_)
#  include <sys/strpty.h>
#endif

#ifdef HAVE_PTMX
#  include <sys/stropts.h>
#endif

#include "exp_win.h"

#include "exp_tty_in.h"
#include "exp_rename.h"
#include "exp_pty.h"

void debuglog();


#include <errno.h>
/*extern char *sys_errlist[];*/

#ifndef TRUE
#define TRUE 1
#define FALSE 0







|









|
>







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#  include <fcntl.h>
#endif

#if defined(_SEQUENT_)
#  include <sys/strpty.h>
#endif

#if defined(HAVE_PTMX) && defined(HAVE_STROPTS_H)
#  include <sys/stropts.h>
#endif

#include "exp_win.h"

#include "exp_tty_in.h"
#include "exp_rename.h"
#include "exp_pty.h"

void expDiagLog();
void expDiagLogPtr();

#include <errno.h>
/*extern char *sys_errlist[];*/

#ifndef TRUE
#define TRUE 1
#define FALSE 0
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/* Apollo Domain doesn't need this */
#ifdef DFLT_STTY
		if (ttyinit) {
			/* overlay parms originally supplied by Makefile */
/* As long as BSD stty insists on stdout == stderr, we can no longer write */
/* diagnostics to parent stderr, since stderr has is now child's */
/* Maybe someday they will fix stty? */
/*			debuglog("getptyslave: (default) stty %s\n",DFLT_STTY);*/
			pty_stty(DFLT_STTY,slave_name);
		}
#endif

		/* lastly, give user chance to override any terminal parms */
		if (s) {
			/* give user a chance to override any terminal parms */
/*			debuglog("getptyslave: (user-requested) stty %s\n",s);*/
			pty_stty(s,slave_name);
		}
	}
}

void
exp_init_pty()







|







|







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
/* Apollo Domain doesn't need this */
#ifdef DFLT_STTY
		if (ttyinit) {
			/* overlay parms originally supplied by Makefile */
/* As long as BSD stty insists on stdout == stderr, we can no longer write */
/* diagnostics to parent stderr, since stderr has is now child's */
/* Maybe someday they will fix stty? */
/*			expDiagLogPtrStr("exp_getptyslave: (default) stty %s\n",DFLT_STTY);*/
			pty_stty(DFLT_STTY,slave_name);
		}
#endif

		/* lastly, give user chance to override any terminal parms */
		if (s) {
			/* give user a chance to override any terminal parms */
/*			expDiagLogPtrStr("exp_getptyslave: (user-requested) stty %s\n",s);*/
			pty_stty(s,slave_name);
		}
	}
}

void
exp_init_pty()
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#ifndef R_OK
/* 3b2 doesn't define these according to [email protected]. */
#define R_OK 04
#define W_OK 02
#endif

int
getptymaster()
{
	char *hex, *bank;
	struct stat stat_buf;
	int master = -1;
	int slave = -1;
	int num;








|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
#ifndef R_OK
/* 3b2 doesn't define these according to [email protected]. */
#define R_OK 04
#define W_OK 02
#endif

int
exp_getptymaster()
{
	char *hex, *bank;
	struct stat stat_buf;
	int master = -1;
	int slave = -1;
	int num;

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
#endif
	if ((slave_name = (char *)ptsname(master)) == NULL || unlockpt(master)) {
		close(master);
		return(-1);
	} else if (grantpt(master)) {
		static char buf[500];
		exp_pty_error = buf;
		sprintf(exp_pty_error,"grantpt(%d) failed - likely reason is that your system administrator (in a rage of blind passion to rid the system of security holes) removed setuid from the utility used internally by grantpt to change pty permissions.  Tell your system admin to reestablish setuid on the utility.  Get the utility name by running Expect under truss or trace.");
		close(master);
		return(-1);
	}
#ifdef TIOCFLUSH
	(void) ioctl(master,TIOCFLUSH,(char *)0);
#endif /* TIOCFLUSH */








|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#endif
	if ((slave_name = (char *)ptsname(master)) == NULL || unlockpt(master)) {
		close(master);
		return(-1);
	} else if (grantpt(master)) {
		static char buf[500];
		exp_pty_error = buf;
		sprintf(exp_pty_error,"grantpt(%s) failed - likely reason is that your system administrator (in a rage of blind passion to rid the system of security holes) removed setuid from the utility used internally by grantpt to change pty permissions.  Tell your system admin to reestablish setuid on the utility.  Get the utility name by running Expect under truss or trace.", expErrnoMsg(errno));
		close(master);
		return(-1);
	}
#ifdef TIOCFLUSH
	(void) ioctl(master,TIOCFLUSH,(char *)0);
#endif /* TIOCFLUSH */

480
481
482
483
484
485
486
487
488
489
490
491
492
493
494

            sprintf (num_str, "%d", num);
            sprintf (master_name, "%s%s", "/dev/ptyp", num_str);
            if (stat (master_name, &stat_buf) < 0)
                break;
            sprintf (slave_name, "%s%s", "/dev/ttyp", num_str);

            master = exp_pty_test (master_name, slave_name, 0, num_str);
            if (master >= 0)
                goto done;
        }
#endif

#ifdef HAVE_PTYM
	/* systems with PTYM follow this idea:







|







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

            sprintf (num_str, "%d", num);
            sprintf (master_name, "%s%s", "/dev/ptyp", num_str);
            if (stat (master_name, &stat_buf) < 0)
                break;
            sprintf (slave_name, "%s%s", "/dev/ttyp", num_str);

            master = exp_pty_test(master_name,slave_name,'0',num_str);
            if (master >= 0)
                goto done;
        }
#endif

#ifdef HAVE_PTYM
	/* systems with PTYM follow this idea:
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
		*tty_bank = *bank;
		sprintf(tty_num,"00");
		if (stat(master_name, &stat_buf) < 0) break;
		for (num = 0; num<100; num++) {
			*slave_bank = *tty_bank;
			sprintf(tty_num,"%02d",num);
			strcpy(slave_num,tty_num);
			master = exp_pty_test(master_name,slave_name,tty_bank,tty_num);
			if (master >= 0) goto done;
		}
	}

	/*
	 * tty[p-za-ce-o][0-9][0-9][0-9]
	 */
	for (bank = banks;*bank;bank++) {
		*tty_bank = *bank;
		sprintf(tty_num,"000");
		if (stat(master_name, &stat_buf) < 0) break;
		for (num = 0; num<1000; num++) {
			*slave_bank = *tty_bank;
			sprintf(tty_num,"%03d",num);
			strcpy(slave_num,tty_num);
			master = exp_pty_test(master_name,slave_name,tty_bank,tty_num);
			if (master >= 0) goto done;
		}
	}

#endif /* HAVE_PTYM */

#if defined(HAVE_CONVEX_GETPTY)







|















|







554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
		*tty_bank = *bank;
		sprintf(tty_num,"00");
		if (stat(master_name, &stat_buf) < 0) break;
		for (num = 0; num<100; num++) {
			*slave_bank = *tty_bank;
			sprintf(tty_num,"%02d",num);
			strcpy(slave_num,tty_num);
			master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num);
			if (master >= 0) goto done;
		}
	}

	/*
	 * tty[p-za-ce-o][0-9][0-9][0-9]
	 */
	for (bank = banks;*bank;bank++) {
		*tty_bank = *bank;
		sprintf(tty_num,"000");
		if (stat(master_name, &stat_buf) < 0) break;
		for (num = 0; num<1000; num++) {
			*slave_bank = *tty_bank;
			sprintf(tty_num,"%03d",num);
			strcpy(slave_num,tty_num);
			master = exp_pty_test(master_name,slave_name,*tty_bank,tty_num);
			if (master >= 0) goto done;
		}
	}

#endif /* HAVE_PTYM */

#if defined(HAVE_CONVEX_GETPTY)
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613





614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
{
#ifdef HAVE_PTYTRAP
	ioctl(master, TIOCTRAP, &control);
#endif /* HAVE_PTYTRAP */
}

int
getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave, slave2;
	char buf[10240];

	if (0 > (slave = open(slave_name, O_RDWR))) return(-1);






#if defined(HAVE_PTMX_BSD)
	if (ioctl (slave, I_LOOK, buf) != 0)
		if (ioctl (slave, I_PUSH, "ldterm")) {
			debuglog("ioctl(%s,I_PUSH,\"ldterm\") = %s\n",Tcl_ErrnoMsg(errno));
	}
#else
#if defined(HAVE_PTMX)
	if (ioctl(slave, I_PUSH, "ptem")) {
		debuglog("ioctl(%s,I_PUSH,\"ptem\") = %s\n",Tcl_ErrnoMsg(errno));
	}
	if (ioctl(slave, I_PUSH, "ldterm")) {
		debuglog("ioctl(%s,I_PUSH,\"ldterm\") = %s\n",Tcl_ErrnoMsg(errno));
	}
	if (ioctl(slave, I_PUSH, "ttcompat")) {
		debuglog("ioctl(%s,I_PUSH,\"ttcompat\") = %s\n",Tcl_ErrnoMsg(errno));
	}
#endif
#endif

	if (0 == slave) {
		/* if opened in a new process, slave will be 0 (and */
		/* ultimately, 1 and 2 as well) */







|







|
>
>
>
>
>




|




|


|


|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
{
#ifdef HAVE_PTYTRAP
	ioctl(master, TIOCTRAP, &control);
#endif /* HAVE_PTYTRAP */
}

int
exp_getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave, slave2;
	char buf[10240];

	if (0 > (slave = open(slave_name, O_RDWR))) {
		static char buf[500];
		exp_pty_error = buf;
		sprintf(exp_pty_error,"open(%s,rw) = %d (%s)",slave_name,slave,expErrnoMsg(errno));
		return(-1);
	}

#if defined(HAVE_PTMX_BSD)
	if (ioctl (slave, I_LOOK, buf) != 0)
		if (ioctl (slave, I_PUSH, "ldterm")) {
			expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ldterm\") = %s\n",slave,expErrnoMsg(errno));
	}
#else
#if defined(HAVE_PTMX)
	if (ioctl(slave, I_PUSH, "ptem")) {
		expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ptem\") = %s\n",slave,expErrnoMsg(errno));
	}
	if (ioctl(slave, I_PUSH, "ldterm")) {
		expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ldterm\") = %s\n",slave,expErrnoMsg(errno));
	}
	if (ioctl(slave, I_PUSH, "ttcompat")) {
		expDiagLogPtrStrStr("ioctl(%d,I_PUSH,\"ttcompat\") = %s\n",slave,expErrnoMsg(errno));
	}
#endif
#endif

	if (0 == slave) {
		/* if opened in a new process, slave will be 0 (and */
		/* ultimately, 1 and 2 as well) */
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748

	rc = select(maxfds,
		(SELECT_MASK_TYPE *)0,
		(SELECT_MASK_TYPE *)0,
		(SELECT_MASK_TYPE *)&excep,
		&t);
	if (rc != 1) {
		debuglog("spawned process never started, errno = %d\n",errno);
		return(-1);
	}
	if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) {
		debuglog("ioctl(TIOCREQCHECK) failed, errno = %d\n",errno);
		return(-1);
	}

	found = ioctl_info.request;

	debuglog("trapped pty op = %x",found);
	if (found == TIOCOPEN) {
		debuglog(" TIOCOPEN");
	} else if (found == TIOCCLOSE) {
		debuglog(" TIOCCLOSE");
	}

#ifdef TIOCSCTTY
	if (found == TIOCSCTTY) {
		debuglog(" TIOCSCTTY");
	}
#endif

	if (found & IOC_IN) {
		debuglog(" IOC_IN (set)");
	} else if (found & IOC_OUT) {
		debuglog(" IOC_OUT (get)");
	}

	debuglog("\n");

	if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) {
		debuglog("ioctl(TIOCREQSET) failed, errno = %d\n",errno);
		return(-1);
	}
	return(found);
}
#endif

void
exp_pty_exit()
{
	/* a stub so we can do weird things on the cray */
}







|



|





|

|

|




|




|

|


|


|











720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770

	rc = select(maxfds,
		(SELECT_MASK_TYPE *)0,
		(SELECT_MASK_TYPE *)0,
		(SELECT_MASK_TYPE *)&excep,
		&t);
	if (rc != 1) {
		expDiagLogPtrStr("spawned process never started: %s\r\n",expErrnoMsg(errno));
		return(-1);
	}
	if (ioctl(fd,TIOCREQCHECK,&ioctl_info) < 0) {
		expDiagLogPtrStr("ioctl(TIOCREQCHECK) failed: %s\r\n",expErrnoMsg(errno));
		return(-1);
	}

	found = ioctl_info.request;

	expDiagLogPtrX("trapped pty op = %x",found);
	if (found == TIOCOPEN) {
		expDiagLogPtr(" TIOCOPEN");
	} else if (found == TIOCCLOSE) {
		expDiagLogPtr(" TIOCCLOSE");
	}

#ifdef TIOCSCTTY
	if (found == TIOCSCTTY) {
		expDiagLogPtr(" TIOCSCTTY");
	}
#endif

	if (found & IOC_IN) {
		expDiagLogPtr(" IOC_IN (set)");
	} else if (found & IOC_OUT) {
		expDiagLogPtr(" IOC_OUT (get)");
	}

	expDiagLogPtr("\n");

	if (ioctl(fd, TIOCREQSET, &ioctl_info) < 0) {
		expDiagLogPtrStr("ioctl(TIOCREQSET) failed: %s\r\n",expErrnoMsg(errno));
		return(-1);
	}
	return(found);
}
#endif

void
exp_pty_exit()
{
	/* a stub so we can do weird things on the cray */
}

Changes to pty_unicos.c.

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "exp_tty_in.h"
#include "exp_rename.h"

#ifdef HAVE_SYSCONF_H
#include <sys/sysconfig.h>
#endif

void debuglog();

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#ifndef MAXHOSTNAMELEN







|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "exp_tty_in.h"
#include "exp_rename.h"

#ifdef HAVE_SYSCONF_H
#include <sys/sysconfig.h>
#endif

void expDiagLog();

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#ifndef MAXHOSTNAMELEN
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	 */
	setuid(0);
	setreuid(realuid,realuid);
}

/* returns fd of master end of pseudotty */
int
getptymaster()
{
	struct stat sb;
	int master;
	int npty;

	exp_pty_error = 0;

	debuglog("getptymaster:  lowpty=%d  highpty=%d\n",lowpty,highpty);
	for (npty = lowpty; npty <= highpty; npty++) {
		if (seteuid(0) == -1) {		/* we need to be root! */
			debuglog("getptymaster:  seteuid root errno=%d\n",
				errno);
		}
		(void) sprintf(linep, "/dev/pty/%03d", npty);
		master = open(linep, O_RDWR);

		if (master < 0) {
			debuglog("getptymaster:  open linep=%s errno=%d\n",
				linep,errno);
			continue;
		}

		(void) sprintf(linet, "/dev/ttyp%03d", npty);
		if(stat(linet, &sb) < 0) {
			debuglog("getptymaster:  stat linet=%s errno=%d\n",
				linet,errno);
			(void) close(master);
			continue;
		}
		if (sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
                        if (chown(linet, realuid, realgid) == -1) {
				debuglog("getptymaster:  chown linet=%s errno=%d\n",
					linet,errno);
			}
                        if (chmod(linet, 0600) == -1) {
				debuglog("getptymaster:  chmod linet=%s errno=%d\n",
					linet,errno);
			}
                        (void)close(master);
                        master = open(linep, 2);
                        if (master < 0) {
				debuglog("getptymaster:  reopen linep=%s errno=%d\n",
					linep,errno);
                                continue;
			}
                }
		if (seteuid(realuid) == -1) {	/* back to who we are! */
			debuglog("getptymaster:  seteuid user errno=%d\n",
				errno);
		}
		if (access(linet, R_OK|W_OK) != 0) {
			debuglog("getptymaster:  access linet=%s errno=%d\n",
				linet,errno);
			(void) close(master);
			continue;
		}
		debuglog("getptymaster:  allocated %s\n",linet);
		ptys[npty] = -1;
		exp_pty_slave_name = linet;
		return(master);
	}
	if (seteuid(realuid) == -1) {		/* back to who we are! */
		debuglog("getptymaster:  seteuid user errno=%d\n",errno);
	}
	return(-1);
}

/* see comment in pty_termios.c */
/*ARGSUSED*/
void
exp_slave_control(master,control)
int master;
int control;
{
}

int
getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave;

	if (0 > (slave = open(linet, O_RDWR))) {
		debuglog("getptyslave:  open linet=%s errno=%d\n",linet,errno);
		return(-1);
	}

	/* sanity check - if slave not 0, skip rest of this and return */
	/* to what will later be detected as an error in caller */
	if (0 != slave) {
		debuglog("getptyslave:  slave fd not 0\n");
		 return(slave);
	}

	if (0 == slave) {
		/* if opened in a new process, slave will be 0 (and */
		/* ultimately, 1 and 2 as well) */








|







|


|






|






|






|



|





|





|



|




|





|














|







|






|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
	 */
	setuid(0);
	setreuid(realuid,realuid);
}

/* returns fd of master end of pseudotty */
int
exp_getptymaster()
{
	struct stat sb;
	int master;
	int npty;

	exp_pty_error = 0;

	expDiagLog("exp_getptymaster:  lowpty=%d  highpty=%d\n",lowpty,highpty);
	for (npty = lowpty; npty <= highpty; npty++) {
		if (seteuid(0) == -1) {		/* we need to be root! */
			expDiagLog("exp_getptymaster:  seteuid root errno=%d\n",
				errno);
		}
		(void) sprintf(linep, "/dev/pty/%03d", npty);
		master = open(linep, O_RDWR);

		if (master < 0) {
			expDiagLog("exp_getptymaster:  open linep=%s errno=%d\n",
				linep,errno);
			continue;
		}

		(void) sprintf(linet, "/dev/ttyp%03d", npty);
		if(stat(linet, &sb) < 0) {
			expDiagLog("exp_getptymaster:  stat linet=%s errno=%d\n",
				linet,errno);
			(void) close(master);
			continue;
		}
		if (sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
                        if (chown(linet, realuid, realgid) == -1) {
				expDiagLog("exp_getptymaster:  chown linet=%s errno=%d\n",
					linet,errno);
			}
                        if (chmod(linet, 0600) == -1) {
				expDiagLog("exp_getptymaster:  chmod linet=%s errno=%d\n",
					linet,errno);
			}
                        (void)close(master);
                        master = open(linep, 2);
                        if (master < 0) {
				expDiagLog("exp_getptymaster:  reopen linep=%s errno=%d\n",
					linep,errno);
                                continue;
			}
                }
		if (seteuid(realuid) == -1) {	/* back to who we are! */
			expDiagLog("exp_getptymaster:  seteuid user errno=%d\n",
				errno);
		}
		if (access(linet, R_OK|W_OK) != 0) {
			expDiagLog("exp_getptymaster:  access linet=%s errno=%d\n",
				linet,errno);
			(void) close(master);
			continue;
		}
		expDiagLog("exp_getptymaster:  allocated %s\n",linet);
		ptys[npty] = -1;
		exp_pty_slave_name = linet;
		return(master);
	}
	if (seteuid(realuid) == -1) {		/* back to who we are! */
		expDiagLog("exp_getptymaster:  seteuid user errno=%d\n",errno);
	}
	return(-1);
}

/* see comment in pty_termios.c */
/*ARGSUSED*/
void
exp_slave_control(master,control)
int master;
int control;
{
}

int
exp_getptyslave(ttycopy,ttyinit,stty_args)
int ttycopy;
int ttyinit;
char *stty_args;
{
	int slave;

	if (0 > (slave = open(linet, O_RDWR))) {
		expDiagLog("exp_getptyslave:  open linet=%s errno=%d\n",linet,errno);
		return(-1);
	}

	/* sanity check - if slave not 0, skip rest of this and return */
	/* to what will later be detected as an error in caller */
	if (0 != slave) {
		expDiagLog("exp_getptyslave:  slave fd not 0\n");
		 return(slave);
	}

	if (0 == slave) {
		/* if opened in a new process, slave will be 0 (and */
		/* ultimately, 1 and 2 as well) */

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
}

setptyutmp()
{
	struct utmp utmp;

	if (seteuid(0) == -1) {		/* Need to be root */
		debuglog("setptyutmp:  setuid root errno=%d\n",errno);
		return(-1);
	}
	(void) time(&utmp.ut_time);
	utmp.ut_type = USER_PROCESS;
	utmp.ut_pid = getpid();
	strncpy(utmp.ut_user,myname,sizeof(utmp.ut_user));
	strncpy(utmp.ut_host,hostname,sizeof(utmp.ut_host));
	strncpy(utmp.ut_line,linet+5,sizeof(utmp.ut_line));
	strncpy(utmp.ut_id,linet+8,sizeof(utmp.ut_id));
	if (pututline(&utmp) == NULL) {
		debuglog("setptyutmp:  pututline failed\n");
	}
	endutent();
	if (seteuid(realuid) == -1)
		debuglog("setptyutmp:  seteuid user errno=%d\n",errno);
	return(0);
}

setptypid(pid)
int pid;
{
        int npty;

        for (npty = lowpty; npty <= highpty; npty++) {
                if (ptys[npty] < 0) {
                        debuglog("setptypid:  ttyp%03d pid=%d\n",npty,pid);
                        ptys[npty] = pid;
                        break;
                }
        }
}

ttyp_reset()
{
        int npty;

        if (seteuid(0) == -1) {		/* we need to be root! */
                debuglog("ttyp_reset:  seteuid root errno=%d\n",errno);
        }
        for (npty = lowpty; npty <= highpty; npty++) {
                if (ptys[npty] <= 0)
                        continue;

                (void) sprintf(linet, "/dev/ttyp%03d", npty);
                debuglog("ttyp_reset:  resetting %s, killing %d\n",
			linet,ptys[npty]);
                if (chown(linet,0,0) == -1) {
                        debuglog("ttyp_reset: chown %s errno=%d\n",linet,errno);
                }
                if (chmod(linet, 0666) == -1) {
                        debuglog("ttyp_reset: chmod %s errno=%d\n",linet,errno);
                }
                resetptyutmp();
                if (kill(ptys[npty],SIGKILL) == -1) {
                        debuglog("ttyp_reset:  kill pid=%d errno=%d\n",
                                ptys[npty],errno);
                }
        }
        if (seteuid(realuid) == -1) {   /* Back to who we really are */
                debuglog("ttyp_reset:  seteuid user errno=%d\n",errno);
        }
}

void
exp_pty_exit()
{
	ttyp_reset();







|










|



|










|











|






|


|


|



|




|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
}

setptyutmp()
{
	struct utmp utmp;

	if (seteuid(0) == -1) {		/* Need to be root */
		expDiagLog("setptyutmp:  setuid root errno=%d\n",errno);
		return(-1);
	}
	(void) time(&utmp.ut_time);
	utmp.ut_type = USER_PROCESS;
	utmp.ut_pid = getpid();
	strncpy(utmp.ut_user,myname,sizeof(utmp.ut_user));
	strncpy(utmp.ut_host,hostname,sizeof(utmp.ut_host));
	strncpy(utmp.ut_line,linet+5,sizeof(utmp.ut_line));
	strncpy(utmp.ut_id,linet+8,sizeof(utmp.ut_id));
	if (pututline(&utmp) == NULL) {
		expDiagLog("setptyutmp:  pututline failed\n");
	}
	endutent();
	if (seteuid(realuid) == -1)
		expDiagLog("setptyutmp:  seteuid user errno=%d\n",errno);
	return(0);
}

setptypid(pid)
int pid;
{
        int npty;

        for (npty = lowpty; npty <= highpty; npty++) {
                if (ptys[npty] < 0) {
                        expDiagLog("setptypid:  ttyp%03d pid=%d\n",npty,pid);
                        ptys[npty] = pid;
                        break;
                }
        }
}

ttyp_reset()
{
        int npty;

        if (seteuid(0) == -1) {		/* we need to be root! */
                expDiagLog("ttyp_reset:  seteuid root errno=%d\n",errno);
        }
        for (npty = lowpty; npty <= highpty; npty++) {
                if (ptys[npty] <= 0)
                        continue;

                (void) sprintf(linet, "/dev/ttyp%03d", npty);
                expDiagLog("ttyp_reset:  resetting %s, killing %d\n",
			linet,ptys[npty]);
                if (chown(linet,0,0) == -1) {
                        expDiagLog("ttyp_reset: chown %s errno=%d\n",linet,errno);
                }
                if (chmod(linet, 0666) == -1) {
                        expDiagLog("ttyp_reset: chmod %s errno=%d\n",linet,errno);
                }
                resetptyutmp();
                if (kill(ptys[npty],SIGKILL) == -1) {
                        expDiagLog("ttyp_reset:  kill pid=%d errno=%d\n",
                                ptys[npty],errno);
                }
        }
        if (seteuid(realuid) == -1) {   /* Back to who we really are */
                expDiagLog("ttyp_reset:  seteuid user errno=%d\n",errno);
        }
}

void
exp_pty_exit()
{
	ttyp_reset();
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
        /* set up entry to search for */
        (void) strncpy(utmp.ut_id, linet + strlen(linet) - 4,
                 sizeof (utmp.ut_id));
        utmp.ut_type = USER_PROCESS;

        /* position to entry in utmp file */
        if(getutid(&utmp) == NULL) {
                debuglog("resetptyutmp:  no utmp entry for %s\n",linet);
                return(-1);     /* no utmp entry for this line ??? */
        }

        /* set up the new entry */
        strncpy(utmp.ut_name,"",sizeof(utmp.ut_name));
        strncpy(utmp.ut_host,"",sizeof(utmp.ut_host));
        time(&utmp.ut_time);







|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
        /* set up entry to search for */
        (void) strncpy(utmp.ut_id, linet + strlen(linet) - 4,
                 sizeof (utmp.ut_id));
        utmp.ut_type = USER_PROCESS;

        /* position to entry in utmp file */
        if(getutid(&utmp) == NULL) {
                expDiagLog("resetptyutmp:  no utmp entry for %s\n",linet);
                return(-1);     /* no utmp entry for this line ??? */
        }

        /* set up the new entry */
        strncpy(utmp.ut_name,"",sizeof(utmp.ut_name));
        strncpy(utmp.ut_host,"",sizeof(utmp.ut_host));
        time(&utmp.ut_time);

Changes to tcldbg.h.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  ClientData data;
} Dbg_OutputStruct;

EXTERN char *Dbg_VarName;
EXTERN char *Dbg_DefaultCmdName;

/* trivial interface, creates a "debug" command in your interp */
EXTERN int Dbg_Init _ANSI_ARGS_((Tcl_Interp *));

EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp *interp,
					int immediate));
EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc,char *argv[],
					int copy));
EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp *interp));







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  ClientData data;
} Dbg_OutputStruct;

EXTERN char *Dbg_VarName;
EXTERN char *Dbg_DefaultCmdName;

/* trivial interface, creates a "debug" command in your interp */
EXTERN int Tcldbg_Init _ANSI_ARGS_((Tcl_Interp *));

EXTERN void Dbg_On _ANSI_ARGS_((Tcl_Interp *interp,
					int immediate));
EXTERN void Dbg_Off _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN char **Dbg_ArgcArgv _ANSI_ARGS_((int argc,char *argv[],
					int copy));
EXTERN int Dbg_Active _ANSI_ARGS_((Tcl_Interp *interp));

Changes to tests/.Sanitize.

21
22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
# called.  Directories not listed will be removed in their entirety
# with rm -rf.

Things-to-keep:

.Sanitize
README
all
defs


spawn.test
pid.test
cat.test
expect.test
stty.test

# The lines between the "Do-last:" line and the end of the file







|

>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# called.  Directories not listed will be removed in their entirety
# with rm -rf.

Things-to-keep:

.Sanitize
README
all.tcl
defs
logfile.test
send.test
spawn.test
pid.test
cat.test
expect.test
stty.test

# The lines between the "Do-last:" line and the end of the file

Changes to tests/README.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18

19
20

21
22

23
24

25
26
27
28




29
30
31

32
33

34
35


36
37
38
39
40

41
42
43
44
45
46
47
48
49

50



51

52



53

54
55


56


57
58
59
60
61
62





63
64


65
66
67

68
69

70



71
72
73
74
75
76
77
78
79
80
81
82

83
84

85
86

87

88
89



90
91
Expect Test Suite
--------------

This directory contains a set of validation tests for the Expect
commands.  Each of the files whose name ends in ".test" is intended to
fully exercise one or a few Expect commands.  The commands tested by a
given file are listed in the first line of the file.

You can run the tests in two ways:

    (a) type "make test" in the parent directory to this one; this
        will run all of the tests.
    (b) start up expect in this directory, then "source" the test
        file (for example, type "source parse.test").  To run all
	of the tests, type "source all".
In either case no output will be generated if all goes well, except
for a listing of the tests.  If there are errors then additional
messages will appear in the format described below.


The rest of this file provides additional information on the
features of the testing environment.


This approach to testing (and most of this file) was copied from the

Tcl distribution.


Definitions file:
-----------------

The file "defs" defines a collection of procedures and variables




used to run the tests.  It is read in automatically by each of the
.test files if needed, but once it has been read once it will not
be read again by the .test files.  If you change defs while running

tests you'll have to "source" it by hand to load its new contents.


Test output:
------------



Normally, output only appears when there are errors.  However, if
the variable VERBOSE is set to 1 then tests will be run in "verbose"
mode and output will be generated for each test regardless of
whether it succeeded or failed.  Test output consists of the

following information:

    - the test identifier (which can be used to locate the test code
	    in the .test file)
    - a brief description of the test
    - the contents of the test code
    - the actual results produced by the tests
    - a "PASSED" or "FAILED" message
    - the expected results (if the test failed)





You can set VERBOSE either interactively (after the defs file has been

read in), or you can change the default value in "defs".





Selecting tests for execution:
------------------------------





Normally, all the tests in a file are run whenever the file is
"source"d.  However, you can select a specific set of tests using
the global variable TESTS.  This variable contains a pattern;  any
test whose identifier matches TESTS will be run.  For example,
the following interactive command causes all of the "for" tests in
groups 2 and 4 to be executed:






    set TESTS {for-[24]*}



TESTS defaults to *, but you can change the default in "defs" if
you wish.


Saving keystrokes:

------------------




A convenience procedure named "dotests" is included in file
"defs".  It takes two arguments--the name of the test file (such
as "parse.test"), and a pattern selecting the tests you want to
execute.  It sets TESTS to the second argument, calls "source" on
the file specified in the first argument, and restores TESTS to
its pre-call value at the end.

Batch vs. interactive execution:
--------------------------------

The tests can be run in either batch or interactive mode.  Batch

mode refers to using I/O redirection from a UNIX shell.  For example,
the following command causes the tests in the file named "parse.test"

to be executed:


    expect < parse.test > parse.test.results


Users who want to execute the tests in this fashion need to first



ensure that the file "defs" has proper values for the global
variables that control the testing environment (VERBOSE and TESTS).

|






|
>


|
|
|
|
<
|

>
|
|
>

<
>
|

>
|
<

|
>
>
>
>
|
|
|
>
|
|
>
|
<
>
>

<
|
<
|
>
|

<
|
|
|
|
<
|
>

>
>
>
|
>
|
>
>
>
|
>
|
<
>
>
|
>
>
|
|
|
|
<
<
>
>
>
>
>

<
>
>

<
<
>

<
>
|
>
>
>

<
|
|
|
|
|

|
<

|
>
|
|
>
|

>
|
>

|
>
>
>
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23

24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45

46

47
48
49
50

51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78


79
80
81
82
83
84

85
86
87


88
89

90
91
92
93
94
95

96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Expect Test Suite
-----------------

This directory contains a set of validation tests for the Expect
commands.  Each of the files whose name ends in ".test" is intended to
fully exercise one or a few Expect commands.  The commands tested by a
given file are listed in the first line of the file.

You can run the tests in three ways:

    (a) type "make test" in the parent directory to this one; this
        will run all of the tests.

    (b) type "expect <testFile> ?<option> <value>?
	Command line options include:


	-help                display usage information

	-verbose <level>     set the level of verbosity to a substring
			     of "bps".  See the "Test output" section
			     of the tcltest man page for an
			     explanation of this option. 


	-match <matchList>   only run tests that match one or more of
			     the glob patterns in <matchList>

	-skip <skipList>     do not run tests that match one or more
			     of the glob patterns in <skipList>


	-file <globPatternList>  
		             only source test files that match one or
		             more of the glob patterns in
		             <globPatternList> (relative to the
		             "tests" directory).  This option only
		             applies when you run the test suite with
		             the "all.tcl" file.

	-notfile <globPatternList>  
	                     do not source test files that match one
	                     or more of the patterns in
	                     <globPatternList> (relative to the
	                     "tests" directory).  This option only

	                     applies when you run the test suite with
	                     the "all.tcl" file.


	-constraints <list>  tests with any constraints in <list> will

			     not be skipped.  Not that elements of
			     <list> must exactly match the existing
			     constraints.


        -limitconstraints <bool>
                             If 1, limit test runs to those tests that
                             match the constraints listed using the
                             -constraints flag.  Use of this flag

                             requires use of the -constraints flag.
                             The default value is 0.

        -tmpdir <dirname>    put temporary files created by
                             ::tcltest::makeFile and
                             ::tcltest::makeDirectory in the named
                             directory.  The default location is
                             ::tcltest::workingDirectory.

        -preservecore <level>
                             check for core files.  If level is 0,
                             check for core files only when
                             cleanupTests is called from an all.tcl
                             file.  If 1, also check at the end of
                             every test command.  If 2, also save core

                             files in ::tcltest::temporaryDirectory.
                             The default level is 0.
 
    (c) start up expect in this directory, then "source" the test
        file (for example, type "source parse.test").  To run all
	of the tests, type "source all.tcl".  To use the options in
	interactive mode, you can set their corresponding tcltest
	namespace variables after loading the tcltest package.
	For example, some of the tcltest variables are:


		  ::tcltest::match
		  ::tcltest::skip
		  ::tcltest::testConstraints(nonPortable)
		  ::tcltest::testConstraints(knownBug)
		  ::tcltest::testConstraints(userInteractive)


Please see the man page for the 'tcltest' package for more detailed
information on the features of the testing environment.



This approach to testing was copied from the Tcl distribution.


Incompatibilities with prior versions
-------------------------------------

1) Global variables such as VERBOSE, TESTS, and testConfig are now
   renamed to use the new "tcltest" namespace.


   old name   new name
   --------   --------
   VERBOSE    ::tcltest::verbose
   TESTS      ::tcltest::match
   testConfig ::tcltest::testConstraints

2) VERBOSE values are no longer numeric.  


3) When you run "make test", the working dir for the test suite is now
   the one from which you called "make test", rather than the "tests"
   directory.  This change allows for both unix and windows test
   suites to be run simultaneously without interference with each
   other or with existing files.  All tests must now run independently
   of their working directory.

4) The "all" file is now called all.tcl.

5) The "defs" file no longer exists.

6) Instead of creating a doAllTests file in the tests directory, to
   run all nonPortable tests, just use the "-constraints nonPortable"
   command line flag.  If you are running interactively, you can set
   the ::tcltest::testConstraints(nonPortable) variable to 1 (after
   loading the tcltest package).

Deleted tests/all.

1
2
3
4
5
6
7
8
9
10
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all" when running tclTest
# in this directory.
#

foreach i [lsort [glob *.test]] {
    puts stdout $i
    source $i
}
exit	;# required for DejaGNU, I don't know why - DEL 
<
<
<
<
<
<
<
<
<
<




















Added tests/all.tcl.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# all.tcl --
#
# This file contains a top-level script to run all of the Tcl
# tests.  Execute it by invoking "source all" when running tclTest
# in this directory.

package require tcltest
# do this in a way that is backward compatible for Tcl 8.3
namespace import ::tcltest::test ::tcltest::cleanupTests

set ::tcltest::testSingleFile false
set ::tcltest::testsDirectory [file dirname [info script]]

foreach file [lsort [::tcltest::getMatchingFiles]] {
    set tail [file tail $file]
    puts stdout $tail
    if {[catch {source $file} msg]} {
	puts stdout $msg
    }
}

::tcltest::cleanupTests 1 
return

Changes to tests/cat.test.

1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


# Commands covered:  cat (UNIX)
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[string compare test [info procs test]] == 1} then {source defs}





#exp_internal -f /dev/ttyp5 0

catch {unset x}

log_user 0

test cat-1.1 {basic cat operation} {
	exp_spawn cat -u
	exp_send "\r"
	set timeout 10
	expect \r {set x 1} timeout {set x 0}
	exp_close
	exp_wait
	set x
} {1}

#exp_internal 0









|
>
>
>
>



















>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Commands covered:  cat (UNIX)
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

#exp_internal -f /dev/ttyp5 0

catch {unset x}

log_user 0

test cat-1.1 {basic cat operation} {
	exp_spawn cat -u
	exp_send "\r"
	set timeout 10
	expect \r {set x 1} timeout {set x 0}
	exp_close
	exp_wait
	set x
} {1}

#exp_internal 0

cleanupTests
return

Deleted tests/defs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# This file contains support code for the Tcl test suite.  It is
# normally sourced by the individual files in the test suite before
# they run their tests.  This improved approach to testing was designed
# and initially implemented by Mary Ann May-Pumphrey of Sun Microsystems.

if ![info exists VERBOSE] {
	set VERBOSE 0
}
set TESTS {}
set auto_noexec 1
set auto_noload 1
catch {rename unknown ""}

# If tests are being run as root, issue a warning message and set a
# variable to prevent some tests from running at all.

set user {}
catch {set user [exec whoami]}
if {$user == "root"} {
    puts stdout "Warning: you're executing as root.  I'll have to"
    puts stdout "skip some of the tests, since they'll fail as root."
}

# Some of the tests don't work on some system configurations due to
# configuration quirks, not due to Tcl problems;  in order to prevent
# false alarms, these tests are only run in the master source directory
# at Berkeley.  The presence of a file "Berkeley" in this directory is
# used to indicate that these tests should be run.

set atBerkeley [file exists Berkeley]

proc print_verbose {test_name test_description contents_of_test code answer} {
    puts stdout "\n"
    puts stdout "==== $test_name $test_description"
    puts stdout "==== Contents of test case:"
    puts stdout "$contents_of_test"
    if {$code != 0} {
	if {$code == 1} {
	    puts stdout "==== Test generated error:"
	    puts stdout $answer
	} elseif {$code == 2} {
	    puts stdout "==== Test generated return exception;  result was:"
	    puts stdout $answer
	} elseif {$code == 3} {
	    puts stdout "==== Test generated break exception"
	} elseif {$code == 4} {
	    puts stdout "==== Test generated continue exception"
	} else {
	    puts stdout "==== Test generated exception $code;  message was:"
	    puts stdout $answer
	}
    } else {
	puts stdout "==== Result was:"
	puts stdout "$answer"
    }
}

proc test {test_name test_description contents_of_test passing_results} {
    global VERBOSE
    global TESTS
    if {[string compare $TESTS ""] != 0} then {
	set ok 0
	foreach test $TESTS {
	    if [string match $test $test_name] then {
		set ok 1
		break
	    }
        }
	if !$ok then return
    }
    set code [catch {uplevel $contents_of_test} answer]
    if {$code != 0} {
	print_verbose $test_name $test_description $contents_of_test \
		$code $answer
    } elseif {[string compare $answer $passing_results] == 0} then { 
	if $VERBOSE then {
	    print_verbose $test_name $test_description $contents_of_test \
		    $code $answer
	    puts stdout "++++ $test_name PASSED"
	}
    } else {
	print_verbose $test_name $test_description $contents_of_test $code \
		$answer 
	puts stdout "---- Result should have been:"
	puts stdout "$passing_results"
	puts stdout "---- $test_name FAILED" 
    }
}

# stick it in a file, run, and test by looking at output
proc ftest {test_name test_description contents_of_test passing_results} {
    global VERBOSE
    global TESTS
    global objdir
    if {[string compare $TESTS ""] != 0} then {
	set ok 0
	foreach test $TESTS {
	    if [string match $test $test_name] then {
		set ok 1
		break
	    }
        }
	if !$ok then return
    }

    set file [open /tmp/[pid] w]
    puts $file $contents_of_test
    close $file

    set code [catch {exec $objdir/expect /tmp/[pid]} answer]
    if {$code != 0} {
	print_verbose $test_name $test_description $contents_of_test \
		$code $answer
    } elseif {[string compare $answer $passing_results] == 0} then { 
	if $VERBOSE then {
	    print_verbose $test_name $test_description $contents_of_test \
		    $code $answer
	    puts stdout "++++ $test_name PASSED"
	}
    } else {
	print_verbose $test_name $test_description $contents_of_test $code \
		$answer 
	puts stdout "---- Result should have been:"
	puts stdout "$passing_results"
	puts stdout "---- $test_name FAILED" 
    }
    catch {exec rm -f /tmp/[pid]}
}

proc dotests {file args} {
    global TESTS
    set savedTests $TESTS
    set TESTS $args
    source $file
    set TESTS $savedTests
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















































































































































































































































































Changes to tests/expect.test.

1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96




































# Commands covered:  cat (UNIX), expect
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[string compare test [info procs test]] == 1} then {source defs}





catch {unset x}

log_user 0

exp_spawn cat -u
exp_stty -echo < $spawn_out(slave,name)

test expect-1.1 {exact pattern} {
	expect "*"
	exp_send "a\r"
	
	set timeout 10
	set x 0
	expect -ex a {set x 1}
	set x
} {1}

test expect-1.2 {exact pattern buffering} {
	expect "*"
	exp_send "hiahi\r"
	
	set timeout 10
	set x 0
	expect -ex hi
	expect -ex hi {set x 1}
	set x
} {1}

# if only this test fails, then configure has guessed incorrectly and
# stty accesses the control terminal from stdout.  The quick fix is
# to edit expect_cf.h and define STTY_READS_STDOUT to 1.  (It should
# be commented out.)  If you figure out a way to fix the configure test,
# let me know.  Else, let me know a way to test for your particular
# machine and os version so it can be hardwired.
test expect-1.3 {exact pattern failure} {
	expect "*"
	exp_send "hiahi\r"
	
	set timeout 10
	set x 0
	expect -ex hi {set x 1}
	expect -ex hi {set x 2}
	expect -ex hi {set x 3}
	set x
} {2}

test expect-1.4 {glob pattern} {
	expect "*"
	exp_send "a\r"
	
	set timeout 10
	set x 0
	expect "a" {set x 1}
	set x
} {1}

test expect-1.5 {glob pattern buffering} {
	expect "*"
	exp_send "a\r"
	
	set timeout 10
	set x 0
	expect "*" {set x 1}
	set x
} {1}

test expect-1.6 {glob buffer} {
	expect "*"
	exp_send "philosophic\r"
	
	set timeout 10
	set x 0
	expect "hi"
	set x [string match *phi $expect_out(buffer)]
} {1}

test expect-1.7 {glob string} {
	expect "*"
	exp_send "philosophic\r"
	
	set timeout 10
	set x 0
	expect "hi"
	set expect_out(0,string)
} {hi}

close
wait










































|
>
>
>
>









|
|
|
|
|
|
|



|
|
|
|
|
|
|
|









|
|
|
|
|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|
|



|
|
|
|
|
|
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# Commands covered:  cat (UNIX), expect
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

catch {unset x}

log_user 0

exp_spawn cat -u
exp_stty -echo < $spawn_out(slave,name)

test expect-1.1 {exact pattern} {
    expect "*"
    exp_send "a\r"
    
    set timeout 10
    set x 0
    expect -ex a {set x 1}
    set x
} {1}

test expect-1.2 {exact pattern buffering} {
    expect "*"
    exp_send "hiahi\r"
    
    set timeout 10
    set x 0
    expect -ex hi
    expect -ex hi {set x 1}
    set x
} {1}

# if only this test fails, then configure has guessed incorrectly and
# stty accesses the control terminal from stdout.  The quick fix is
# to edit expect_cf.h and define STTY_READS_STDOUT to 1.  (It should
# be commented out.)  If you figure out a way to fix the configure test,
# let me know.  Else, let me know a way to test for your particular
# machine and os version so it can be hardwired.
test expect-1.3 {exact pattern failure} {
    expect "*"
    exp_send "hiahi\r"
    
    set timeout 10
    set x 0
    expect -ex hi {set x 1}
    expect -ex hi {set x 2}
    expect -ex hi {set x 3}
    set x
} {2}

test expect-1.4 {glob pattern} {
    expect "*"
    exp_send "a\r"
    
    set timeout 10
    set x 0
    expect "a" {set x 1}
    set x
} {1}

test expect-1.5 {glob pattern buffering} {
    expect "*"
    exp_send "a\r"
    
    set timeout 10
    set x 0
    expect "*" {set x 1}
    set x
} {1}

test expect-1.6 {glob buffer} {
    expect "*"
    exp_send "philosophic\r"
    
    set timeout 10
    set x 0
    expect "hi"
    set x [string match *phi $expect_out(buffer)]
} {1}

test expect-1.7 {glob string} {
    expect "*"
    exp_send "philosophic\r"
    
    set timeout 10
    set x 0
    expect "hi"
    set expect_out(0,string)
} {hi}

close
wait

set filename /tmp/null.[pid]
set fid [open $filename w]
puts $fid "a\u0000b"
close $fid

test expect-1.8 {default remove null behavior} {
    spawn cat $filename
    expect a\u0000b
    set rc [regexp $expect_out(buffer) "ab"]
    wait
    set rc
} {0}

test expect-1.8b {default remove null behavior} {
    spawn cat $filename
    expect ab
    set rc [regexp $expect_out(buffer) "ab"]
    wait
    set rc
} {1}

test expect-1.9 {match null inline} {
    spawn cat $filename
    remove_nulls 0
    expect a\u0000b
    set rc [regexp $expect_out(buffer) "a\u0000b"]
    close
    wait
    set rc
} {1}

file delete -force $filename

cleanupTests
return

Added tests/logfile.test.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Commands covered:  log_file
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

test logfile-1.1 {basic logfile} {
    set filename /tmp/logfile.[pid]
    file delete -force $filename
    log_file $filename
    unset spawn_id   ;# clean up results of previous test
    send "via send"
    send_user "via send_user"
    send_error "via send_stdout"
    send_tty "via send_tty"
    send_log "via send_log"
    log_file
    set fid [open $filename]
    gets $fid buffer
    close $fid
    file delete -force $filename
    # verify everything but "send" is logged
    regexp "via send_uservia send_stdoutvia send_ttyvia send_log" $buffer
} {1}

cleanupTests
return

Changes to tests/pid.test.

1
2
3
4
5
6
7




8
9
10
11
12
13
14
# Commands covered:  pid
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[string compare test [info procs test]] == 1} then {source defs}





catch {unset x}

#exp_internal -f /dev/ttyp5 0

test pid-1.2 {basic pid operation} {
    set cat [exp_spawn -noecho cat]






|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Commands covered:  pid
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

catch {unset x}

#exp_internal -f /dev/ttyp5 0

test pid-1.2 {basic pid operation} {
    set cat [exp_spawn -noecho cat]
24
25
26
27
28
29
30
31
32
33
34
35
36


    set x [expr {0!=[string compare [exp_pid -i $cat2] [exp_pid -i $cat]]}]
    exp_close -i $cat;exp_wait -i $cat;exp_close -i $cat2;exp_wait -i $cat2
    set x
} {1}

test pid-1.4 {basic pid operation} {
    list [catch {exp_pid -i 100} msg] $msg
} {1 {exp_pid: invalid spawn id (100)}}

test pid-1.5 {basic pid operation} {
	list [catch {exp_pid -j} msg] $msg
} {1 {usage: -i spawn_id}}










|





>
>
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    set x [expr {0!=[string compare [exp_pid -i $cat2] [exp_pid -i $cat]]}]
    exp_close -i $cat;exp_wait -i $cat;exp_close -i $cat2;exp_wait -i $cat2
    set x
} {1}

test pid-1.4 {basic pid operation} {
    list [catch {exp_pid -i 100} msg] $msg
} {1 {can not find channel named "100"}}

test pid-1.5 {basic pid operation} {
	list [catch {exp_pid -j} msg] $msg
} {1 {usage: -i spawn_id}}

cleanupTests
return

Added tests/send.test.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Commands covered:  send
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

log_user 0

#exp_internal -f /dev/ttyp5 0

test send-1.1 {basic send operation} {
    spawn cat
    after 1000
    send "foo\r"
    expect foo
    after 1000
    send "\u0004"
    expect eof
    regexp "\r\nfoo\r\n" $expect_out(buffer)
} {1}

test send-1.2 {send null} {
    spawn od -c
    send "a\u0000b\r"
    after 1000
    send \u0004
    expect eof
    regexp "a  \\\\0   b" $expect_out(buffer)
} {1}

cleanupTests
return

Changes to tests/spawn.test.

1
2
3
4
5
6
7




8
9
10
11
12
13
14
# Commands covered:  spawn
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[string compare test [info procs test]] == 1} then {source defs}





log_user 0

#exp_internal -f /dev/ttyp5 0

test spawn-1.1 {basic spawn operation} {
	set x [catch {exp_spawn cat}]






|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Commands covered:  spawn
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

log_user 0

#exp_internal -f /dev/ttyp5 0

test spawn-1.1 {basic spawn operation} {
	set x [catch {exp_spawn cat}]
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65



	exec rm /tmp/[pid]
	exp_wait
	list $x $y $pid
} {1 1 0}

test spawn-1.5 {spawn with no fd leak} {
	exp_spawn cat
	set x [expr $first_spawn_id==$spawn_id]
	exp_close; exp_wait
	set x
} {1}	

# looks to be some control-char problem
#ftest spawn-1.6 {spawn with echo} {
#	exp_spawn cat
#} {spawn cat}
	
#ftest spawn-1.7 {spawn with -noecho} {
#	exp_spawn -noecho cat
#} {}










|












>
>
>
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
	exec rm /tmp/[pid]
	exp_wait
	list $x $y $pid
} {1 1 0}

test spawn-1.5 {spawn with no fd leak} {
	exp_spawn cat
	set x [expr {"$first_spawn_id"=="$spawn_id"}]
	exp_close; exp_wait
	set x
} {1}	

# looks to be some control-char problem
#ftest spawn-1.6 {spawn with echo} {
#	exp_spawn cat
#} {spawn cat}
	
#ftest spawn-1.7 {spawn with -noecho} {
#	exp_spawn -noecho cat
#} {}

cleanupTests
return

Changes to tests/stty.test.

1
2
3
4
5
6
7




8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


# Commands covered:  stty
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[string compare test [info procs test]] == 1} then {source defs}





#exp_internal -f /dev/ttyp5 0

catch {unset x}

log_user 0

test stty-1.1 {basic stty operation} {
	exp_spawn cat -u
	catch {exp_stty < $spawn_out(slave,name)}
} {0}

test stty-1.2 {basic stty operation} {
	exp_spawn cat -u
	catch {exp_stty -echo < $spawn_out(slave,name)}
} {0}

#exp_internal 0









|
>
>
>
>



















>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Commands covered:  stty
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    # do this in a way that is backward compatible for Tcl 8.3
    namespace import ::tcltest::test ::tcltest::cleanupTests
}

#exp_internal -f /dev/ttyp5 0

catch {unset x}

log_user 0

test stty-1.1 {basic stty operation} {
	exp_spawn cat -u
	catch {exp_stty < $spawn_out(slave,name)}
} {0}

test stty-1.2 {basic stty operation} {
	exp_spawn cat -u
	catch {exp_stty -echo < $spawn_out(slave,name)}
} {0}

#exp_internal 0

cleanupTests
return

Changes to testsuite/Makefile.in.

35
36
37
38
39
40
41




42
43
44
45
46
47
48
  if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \
    echo ${srcdir}/../../dejagnu/runtest ; \
  else echo runtest ;  fi`
RUNTESTFLAGS =

all:





.PHONY: info install-info check installcheck
info:
install-info:
check:
installcheck:
.NOEXPORT:








>
>
>
>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \
    echo ${srcdir}/../../dejagnu/runtest ; \
  else echo runtest ;  fi`
RUNTESTFLAGS =

all:

binaries:

libraries:

.PHONY: info install-info check installcheck
info:
install-info:
check:
installcheck:
.NOEXPORT:

Changes to testsuite/configure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.10 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
  --with-tclconfig           directory containing tcl configuration (tclConfig.sh)"
ac_help="$ac_help
  --with-tclinclude       directory where tcl private headers are"

# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE



|









<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13




14
15
16
17
18
19
20
#! /bin/sh

# Guess values for system-dependent variables and create Makefiles.
# Generated automatically using autoconf version 2.13 
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.

# Defaults:
ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:





# Initialize some variables set by options.
# The variables have the same names as the options, with
# dashes changed to underlines.
build=NONE
cache_file=./config.cache
exec_prefix=NONE
49
50
51
52
53
54
55



56
57
58
59
60
61
62
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=




ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then







>
>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'

# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
SHELL=${CONFIG_SHELL-/bin/sh}
# Maximum number of lines to put in a shell here document.
ac_max_here_lines=12

ac_prev=
for ac_option
do

  # If the previous option needs an argument, assign it.
  if test -n "$ac_prev"; then
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.10"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }







|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
    target="$ac_optarg" ;;

  -v | -verbose | --verbose | --verbos | --verbo | --verb)
    verbose=yes ;;

  -version | --version | --versio | --versi | --vers)
    echo "configure generated by autoconf version 2.13"
    exit 0 ;;

  -with-* | --with-*)
    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
    # Reject names that are not valid shell variable names.
    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
432
433
434
435
436
437
438
439
440
441



442
443

444
445
446
447
448
449
450
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.
# Only set LANG and LC_ALL to C if already set.
# These must not be set unconditionally because not all systems understand
# e.g. LANG=C (notably SCO).



if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi


# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that







<
|
|
>
>
>

|
>







431
432
433
434
435
436
437

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
  esac
done

# NLS nuisances.

# Only set these to C if already set.  These must not be set unconditionally
# because not all systems understand e.g. LANG=C (notably SCO).
# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
# Non-C LC_CTYPE values break the ctype check.
if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi

# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -rf conftest* confdefs.h
# AIX cpp loses on an empty file, so make sure it contains at least a newline.
echo > confdefs.h

# A filename unique to this package, relative to the directory that
497
498
499
500
501
502
503
504

505


506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

631
632
633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
  > $cache_file
fi

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'




if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says [email protected].
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi




#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.  
# the alternative search directory is invoked by --with-tclconfig
#

if test x"${no_tcl}" = x ; then
  # we reset no_tcl in case something fails here
  no_tcl=true
  # Check whether --with-tclconfig or --without-tclconfig was given.
if test "${with_tclconfig+set}" = set; then
  withval="$with_tclconfig"
  with_tclconfig=${withval}
fi

  echo $ac_n "checking for Tcl configuration""... $ac_c" 1>&6
  if eval "test \"`echo '$''{'ac_cv_c_tclconfig'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  

  # First check to see if --with-tclconfig was specified.
  if test x"${with_tclconfig}" != x ; then
    if test -f "${with_tclconfig}/tclConfig.sh" ; then
      ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
    else
      { echo "configure: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" 1>&2; exit 1; }
    fi
  fi

  # then check for a private Tcl installation
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		../tcl \
		`ls -dr ../tcl[7-9]* 2>/dev/null` \
		../../tcl \
		`ls -dr ../../tcl[7-9]* 2>/dev/null` \
		../../../tcl \
		`ls -dr ../../../tcl[7-9]* 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  # check in a few common install locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
      if test -f "$i/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i; pwd)`
	break
      fi
    done
  fi
  # check in a few other private locations
  if test x"${ac_cv_c_tclconfig}" = x ; then
    for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[7-9]* 2>/dev/null` ; do
      if test -f "$i/unix/tclConfig.sh" ; then
        ac_cv_c_tclconfig=`(cd $i/unix; pwd)`
	break
      fi
    done
  fi
  
fi

  if test x"${ac_cv_c_tclconfig}" = x ; then
    TCLCONFIG="# no Tcl configs found"
    echo "configure: warning: Can't find Tcl configuration definitions" 1>&2
  else
    no_tcl=
    TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
    echo "$ac_t""found $TCLCONFIG" 1>&6
  fi
fi


    . $TCLCONFIG

    
    
    
    
    




    
    
    
    
    
    
    
    
    
    
    
    



CC=$TCL_CC

# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"

  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
  ac_prog_rejected=no

  for ac_dir in $PATH; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"







|
>

>
>














|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>






|
>
|




















>






|

>
|







499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525















































































526

























527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  > $cache_file
fi

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

ac_exeext=
ac_objext=o
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
  # Stardent Vistra SVR4 grep lacks -e, says [email protected].
  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
    ac_n= ac_c='
' ac_t='	'
  else
    ac_n=-n ac_c= ac_t=
  fi
else
  ac_n= ac_c='\c' ac_t=
fi



CY_AC_PATH_TCLCONFIG















































































CY_AC_LOAD_TCLCONFIG

























CC=$TCL_CC

# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:533: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="gcc"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

if test -z "$CC"; then
  # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:563: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_prog_rejected=no
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
	continue
      fi
      ac_cv_prog_CC="cc"
695
696
697
698
699
700
701


































702
703
704















































705

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721

722
723




724


725

726
727
728
729
730
731
732
733
734
735
736
737
738
739


740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi



































  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi
















































echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:715: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes




  if test "${CFLAGS+set}" != set; then


    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6

if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_gcc_g=yes
else
  ac_cv_prog_gcc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6


    if test $ac_cv_prog_gcc_g = yes; then

      CFLAGS="-g -O"
    else
      CFLAGS="-O"
    fi
  fi
else
  GCC=
  test "${CFLAGS+set}" = set || CFLAGS="-g"
fi

# If we cannot compile and link a trivial program, we can't expect anything to work
echo $ac_n "checking whether the compiler ($CC) actually works""... $ac_c" 1>&6
cat > conftest.$ac_ext <<EOF
#line 755 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:763: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  c_compiles=yes
else
  rm -rf conftest*
  c_compiles=no
fi
rm -f conftest*


cat > conftest.$ac_ext <<EOF
#line 774 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {
/* don't need anything here */
; return 0; }
EOF
if { (eval echo configure:782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
  rm -rf conftest*
  c_links=yes
else
  rm -rf conftest*
  c_links=no
fi
rm -f conftest*


if test x"${c_compiles}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't compile." 1>&2; exit 1; }
fi

if test x"${c_links}" = x"no" ; then
  { echo "configure: error: the native compiler is broken and won't link." 1>&2; exit 1; }
fi
echo "$ac_t""yes" 1>&6

 
# This is for LynxOS, which needs a flag to force true POSIX when
# building. It's weirder than that, cause the flag varies depending
# how old the compiler is. So...
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
  CPP=
fi
if test -z "$CPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
    # This must be in double quotes, not single quotes, because CPP may get
  # substituted into the Makefile and "${CC-cc}" will confuse make.
  CPP="${CC-cc} -E"
  # On the NeXT, cc -E runs the code through the compiler's parser,
  # not just through cpp.
  cat > conftest.$ac_ext <<EOF
#line 824 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:830: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  rm -rf conftest*
  CPP="${CC-cc} -E -traditional-cpp"
  cat > conftest.$ac_ext <<EOF
#line 839 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:845: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  :
else
  echo "$ac_err" >&5
  rm -rf conftest*
  CPP=/lib/cpp
fi
rm -f conftest*
fi
rm -f conftest*
  ac_cv_prog_CPP="$CPP"
fi
  CPP="$ac_cv_prog_CPP"
else
  ac_cv_prog_CPP="$CPP"
fi
echo "$ac_t""$CPP" 1>&6


echo $ac_n "checking if running LynxOS""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_os_lynx'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 871 "configure"
#include "confdefs.h"
/*
 * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
 */
#if defined(__Lynx__) || defined(Lynx)
yes
#endif

EOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
  egrep "yes" >/dev/null 2>&1; then
  rm -rf conftest*
  ac_cv_os_lynx=yes
else
  rm -rf conftest*
  ac_cv_os_lynx=no
fi
rm -f conftest*

fi

#
if test "$ac_cv_os_lynx" = "yes" ; then
  echo "$ac_t""yes" 1>&6
  cat >> confdefs.h <<\EOF
#define LYNX 1
EOF

  echo $ac_n "checking whether -mposix or -X is available""... $ac_c" 1>&6
  if eval "test \"`echo '$''{'ac_cv_c_posix_flag'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 905 "configure"
#include "confdefs.h"

int main() { return 0; }
int t() {

  /*
   * This flag varies depending on how old the compiler is.
   * -X is for the old "cc" and "gcc" (based on 1.42).
   * -mposix is for the new gcc (at least 2.5.8).
   */
  #if defined(__GNUC__) && __GNUC__ >= 2
  choke me
  #endif
  
; return 0; }
EOF
if { (eval echo configure:922: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
  rm -rf conftest*
  ac_cv_c_posix_flag=" -mposix"
else
  rm -rf conftest*
  ac_cv_c_posix_flag=" -X"
fi
rm -f conftest*

fi

  CC="$CC $ac_cv_c_posix_flag"
  echo "$ac_t""$ac_cv_c_posix_flag" 1>&6
  else
  echo "$ac_t""no" 1>&6
fi


#
# Ok, lets find the tcl source trees so we can use the headers
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
echo $ac_n "checking for Tcl private headers""... $ac_c" 1>&6
# Check whether --with-tclinclude or --without-tclinclude was given.
if test "${with_tclinclude+set}" = set; then
  withval="$with_tclinclude"
  with_tclinclude=${withval}
fi

if eval "test \"`echo '$''{'ac_cv_c_tclh'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  
# first check to see if --with-tclinclude was specified
if test x"${with_tclinclude}" != x ; then
  if test -f ${with_tclinclude}/tclInt.h ; then
    ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
  elif test -f ${with_tclinclude}/generic/tclInt.h ; then
    ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
  else
    { echo "configure: error: ${with_tclinclude} directory doesn't contain private headers" 1>&2; exit 1; }
  fi
fi

# next check if it came with Tcl configuration file
if test x"${ac_cv_c_tclconfig}" = x ; then
  if test -f $ac_cv_c_tclconfig/../generic/tclInt.h ; then
    ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/..; pwd)`
  fi
fi

# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		${srcdir}/../tcl \
		`ls -dr ${srcdir}/../tcl[7-9]* 2>/dev/null` \
		${srcdir}/../../tcl \
		`ls -dr ${srcdir}/../../tcl[7-9]* 2>/dev/null` \
		${srcdir}/../../../tcl \
		`ls -dr ${srcdir}/../../../tcl[7-9]* 2>/dev/null ` ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
  for i in \
		`ls -dr /usr/local/src/tcl[7-9]* 2>/dev/null` \
		`ls -dr /usr/local/lib/tcl[7-9]* 2>/dev/null` \
		/usr/local/src/tcl \
		/usr/local/lib/tcl \
		${prefix}/include ; do
    if test -f $i/generic/tclInt.h ; then
      ac_cv_c_tclh=`(cd $i/generic; pwd)`
      break
    fi
  done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
   ac_safe=`echo "tclInt.h" | tr './\055' '___'`
echo $ac_n "checking for tclInt.h""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.$ac_ext <<EOF
#line 1018 "configure"
#include "confdefs.h"
#include <tclInt.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=yes"
else
  echo "$ac_err" >&5
  rm -rf conftest*
  eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
  echo "$ac_t""yes" 1>&6
  ac_cv_c_tclh=installed
else
  echo "$ac_t""no" 1>&6
ac_cv_c_tclh=""
fi

fi

fi

if test x"${ac_cv_c_tclh}" = x ; then
  TCLHDIR="# no Tcl private headers found"
  { echo "configure: error: Can't find Tcl private headers" 1>&2; exit 1; }
fi
if test x"${ac_cv_c_tclh}" != x ; then
  no_tcl=""
  if test x"${ac_cv_c_tclh}" = x"installed" ; then
    echo "$ac_t""is installed" 1>&6
    TCLHDIR=""
  else
    echo "$ac_t""found in ${ac_cv_c_tclh}" 1>&6
    # this hack is cause the TCLHDIR won't print if there is a "-I" in it.
    TCLHDIR="-I${ac_cv_c_tclh}"
  fi
fi







trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>








|







>


>
>
>
>
|
>
>
|
>
|




|

|





|
>
>
|
>
|
|
|
|
<

<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<


<
<
<
<
|








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

743



744





745








746




747
















748





749
750




751
752
753
754
755
756
757
758
759























































760
761







































































































































































































762
763
764
765
766
767
768
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi

  if test -z "$CC"; then
    case "`uname -s`" in
    *win32* | *WIN32*)
      # Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:614: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  if test -n "$CC"; then
  ac_cv_prog_CC="$CC" # Let the user override the test.
else
  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
  ac_dummy="$PATH"
  for ac_dir in $ac_dummy; do
    test -z "$ac_dir" && ac_dir=.
    if test -f $ac_dir/$ac_word; then
      ac_cv_prog_CC="cl"
      break
    fi
  done
  IFS="$ac_save_ifs"
fi
fi
CC="$ac_cv_prog_CC"
if test -n "$CC"; then
  echo "$ac_t""$CC" 1>&6
else
  echo "$ac_t""no" 1>&6
fi
 ;;
    esac
  fi
  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
fi

echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:646: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5

ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

cat > conftest.$ac_ext << EOF

#line 657 "configure"
#include "confdefs.h"

main(){return(0);}
EOF
if { (eval echo configure:662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
  ac_cv_prog_cc_works=yes
  # If we can't run a trivial program, we are probably using a cross compiler.
  if (./conftest; exit) 2>/dev/null; then
    ac_cv_prog_cc_cross=no
  else
    ac_cv_prog_cc_cross=yes
  fi
else
  echo "configure: failed program was:" >&5
  cat conftest.$ac_ext >&5
  ac_cv_prog_cc_works=no
fi
rm -fr conftest*
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
cross_compiling=$ac_cv_prog_cc_cross

echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
if test $ac_cv_prog_cc_works = no; then
  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:688: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross

echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:693: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  cat > conftest.c <<EOF
#ifdef __GNUC__
  yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
  ac_cv_prog_gcc=yes
else
  ac_cv_prog_gcc=no
fi
fi

echo "$ac_t""$ac_cv_prog_gcc" 1>&6

if test $ac_cv_prog_gcc = yes; then
  GCC=yes
else
  GCC=
fi

ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:721: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
  echo $ac_n "(cached) $ac_c" 1>&6
else
  echo 'void f(){}' > conftest.c
if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
  ac_cv_prog_cc_g=yes
else
  ac_cv_prog_cc_g=no
fi
rm -f conftest*

fi

echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
if test "$ac_test_CFLAGS" = set; then
  CFLAGS="$ac_save_CFLAGS"
elif test $ac_cv_prog_cc_g = yes; then
  if test "$GCC" = yes; then
    CFLAGS="-g -O2"
  else
    CFLAGS="-g"
  fi

else



  if test "$GCC" = yes; then





    CFLAGS="-O2"








  else




    CFLAGS=
















  fi





fi





CY_AC_C_WORKS
 
# This is for LynxOS, which needs a flag to force true POSIX when
# building. It's weirder than that, cause the flag varies depending
# how old the compiler is. So...
# -X is for the old "cc" and "gcc" (based on 1.42)
# -mposix is for the new gcc (at least 2.5.8)
# This modifies the value of $CC to have the POSIX flag added
# so it'll configure correctly























































CY_AC_TCL_LYNX_POSIX
CY_AC_PATH_TCLH











































































































































































































trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
1078
1079
1080
1081
1082
1083
1084



1085
1086
1087










1088

1089
1090
1091
1092
1093
1094
1095
1096
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF



# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |










  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \

  >> confcache
if cmp -s $cache_file confcache; then
  :
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file
  else







>
>
>



>
>
>
>
>
>
>
>
>
>
|
>
|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
# what configure does when it calls configure scripts in
# subdirectories, so they share the cache.
# Giving --cache-file=/dev/null disables caching, for debugging configure.
# config.status only pays attention to the cache file if you give it the
# --recheck option to rerun configure.
#
EOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(set) 2>&1 |
  case `(ac_space=' '; set | grep ac_space) 2>&1` in
  *ac_space=\ *)
    # `set' does not quote correctly, so add quotes (double-quote substitution
    # turns \\\\ into \\, and sed turns \\ into \).
    sed -n \
      -e "s/'/'\\\\''/g" \
      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
    ;;
  *)
    # `set' quotes correctly as required by POSIX, so do not add quotes.
    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
    ;;
  esac >> confcache
if cmp -s $cache_file confcache; then
  :
else
  if test -w $cache_file; then
    echo "updating cache $cache_file"
    cat confcache > $cache_file
  else
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219




































1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.10"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir

trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF

# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
 s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub

s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g

s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@TCL_VERSION@%$TCL_VERSION%g
s%@TCL_MAJOR_VERSION@%$TCL_MAJOR_VERSION%g
s%@TCL_MINOR_VERSION@%$TCL_MINOR_VERSION%g
s%@TCL_CC@%$TCL_CC%g
s%@TCL_DEFS@%$TCL_DEFS%g
s%@TCL_SHLIB_CFLAGS@%$TCL_SHLIB_CFLAGS%g
s%@TCL_SHLIB_LD@%$TCL_SHLIB_LD%g
s%@TCL_SHLIB_LD_LIBS@%$TCL_SHLIB_LD_LIBS%g
s%@TCL_SHLIB_SUFFIX@%$TCL_SHLIB_SUFFIX%g
s%@TCL_DL_LIBS@%$TCL_DL_LIBS%g
s%@TCL_LD_FLAGS@%$TCL_LD_FLAGS%g
s%@TCL_LD_SEARCH_FLAGS@%$TCL_LD_SEARCH_FLAGS%g
s%@TCL_COMPAT_OBJS@%$TCL_COMPAT_OBJS%g
s%@TCL_RANLIB@%$TCL_RANLIB%g
s%@TCL_BUILD_LIB_SPEC@%$TCL_BUILD_LIB_SPEC%g
s%@TCL_LIB_SPEC@%$TCL_LIB_SPEC%g
s%@TCL_LIB_VERSIONS_OK@%$TCL_LIB_VERSIONS_OK%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@TCLHDIR@%$TCLHDIR%g
s%@host@%$host%g

CEOF
EOF




































cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust relative srcdir, etc. for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"







|


















>



>


















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|

|




|







861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909

















910

911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
for ac_option
do
  case "\$ac_option" in
  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
    echo "$CONFIG_STATUS generated by autoconf version 2.13"
    exit 0 ;;
  -help | --help | --hel | --he | --h)
    echo "\$ac_cs_usage"; exit 0 ;;
  *) echo "\$ac_cs_usage"; exit 1 ;;
  esac
done

ac_given_srcdir=$srcdir

trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF

# Protect against being on the right side of a sed subst in config.status.
sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
 s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
$ac_vpsub
$extrasub
s%@SHELL@%$SHELL%g
s%@CFLAGS@%$CFLAGS%g
s%@CPPFLAGS@%$CPPFLAGS%g
s%@CXXFLAGS@%$CXXFLAGS%g
s%@FFLAGS@%$FFLAGS%g
s%@DEFS@%$DEFS%g
s%@LDFLAGS@%$LDFLAGS%g
s%@LIBS@%$LIBS%g
s%@exec_prefix@%$exec_prefix%g
s%@prefix@%$prefix%g
s%@program_transform_name@%$program_transform_name%g
s%@bindir@%$bindir%g
s%@sbindir@%$sbindir%g
s%@libexecdir@%$libexecdir%g
s%@datadir@%$datadir%g
s%@sysconfdir@%$sysconfdir%g
s%@sharedstatedir@%$sharedstatedir%g
s%@localstatedir@%$localstatedir%g
s%@libdir@%$libdir%g
s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g

















s%@CC@%$CC%g

s%@TCLHDIR@%$TCLHDIR%g
s%@host@%$host%g

CEOF
EOF

cat >> $CONFIG_STATUS <<\EOF

# Split the substitutions into bite-sized pieces for seds with
# small command number limits, like on Digital OSF/1 and HP-UX.
ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
ac_file=1 # Number of current file.
ac_beg=1 # First line for current file.
ac_end=$ac_max_sed_cmds # Line after last line for current file.
ac_more_lines=:
ac_sed_cmds=""
while $ac_more_lines; do
  if test $ac_beg -gt 1; then
    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
  else
    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
  fi
  if test ! -s conftest.s$ac_file; then
    ac_more_lines=false
    rm -f conftest.s$ac_file
  else
    if test -z "$ac_sed_cmds"; then
      ac_sed_cmds="sed -f conftest.s$ac_file"
    else
      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
    fi
    ac_file=`expr $ac_file + 1`
    ac_beg=$ac_end
    ac_end=`expr $ac_end + $ac_max_sed_cmds`
  fi
done
if test -z "$ac_sed_cmds"; then
  ac_sed_cmds=cat
fi
EOF

cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
  case "$ac_file" in
  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
  *) ac_file_in="${ac_file}.in" ;;
  esac

  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.

  # Remove last slash and all that follows it.  Not all systems have dirname.
  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
    # The file is in a subdirectory.
    test ! -d "$ac_dir" && mkdir "$ac_dir"
    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1263
1264


1265
1266
1267
1268
1269
1270
1271
1272


1273


1274
1275
1276
1277
1278
1279
1280
      if test -z "$ac_dots"; then top_srcdir=.
      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
  *) # Relative path.
    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac


  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac


  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
fi; done
rm -f conftest.subs







exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1








>









>
>




|

|

>
>

>
>







981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
      if test -z "$ac_dots"; then top_srcdir=.
      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
  *) # Relative path.
    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
    top_srcdir="$ac_dots$ac_given_srcdir" ;;
  esac


  echo creating "$ac_file"
  rm -f "$ac_file"
  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
  case "$ac_file" in
  *Makefile*) ac_comsub="1i\\
# $configure_input" ;;
  *) ac_comsub= ;;
  esac

  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
  sed -e "$ac_comsub
s%@configure_input@%$configure_input%g
s%@srcdir@%$srcdir%g
s%@top_srcdir@%$top_srcdir%g
" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
rm -f conftest.s*

EOF
cat >> $CONFIG_STATUS <<EOF

EOF
cat >> $CONFIG_STATUS <<\EOF

exit 0
EOF
chmod +x $CONFIG_STATUS
rm -fr confdefs* $ac_clean_files
test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1