Expect

Check-in Differences
Login

Check-in Differences

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

Difference From f8e8464f14c728cf To 0a2dd35d85cdf625

2020-05-31
14:16
errorfd file descriptors should be closed when forking, otherwize a fd leak occurs. This patch make use of F_DUPFD_CLOEXEC if available or fcntl setting FD_CLOEXEC flag if not. Patch by ClĂ©ment Chigot. Leaf check-in: f8e8464f14 user: pyssling tags: trunk
2020-05-21
16:55
Replace CONST84 with const. CONST84 is deprecated. Reported by multiple users including Peter da Silva. check-in: 4aa905d5e2 user: pyssling tags: trunk
16:43
Apply patch "patch-warnings" from Mikhail T. Fixes many compiler warnings. Also do some additional cleanup of pre-ansi C function definitions and ensure build on Linux still works. check-in: 35d0b2bdfe user: pyssling tags: trunk
2018-02-04
13:55
Add ChangeLog for 5.45.4 release check-in: 0a2dd35d85 user: pyssling tags: trunk, expect-5-45-4
10:45
Bump version to 5.45.4 for release. check-in: 1a99d091a8 user: pyssling tags: trunk

Changes to Dbg.c.

169
170
171
172
173
174
175
176
177
178
179
180
181



182
183
184
185
186
187
188

	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 
 * cmd: command about to be executed
 * bp: breakpoint to test
 */
static int
breakpoint_test(Tcl_Interp *interp,const char *cmd,struct breakpoint *bp)



{
    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);







|
<
<
<

|
>
>
>







169
170
171
172
173
174
175
176



177
178
179
180
181
182
183
184
185
186
187
188

	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);
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    char *string;		/* String describing frame. */
    CallFrame **framePtrPtr;	/* Store pointer to frame here (or NULL
				 * if global frame indicated). */
    enum debug_cmd dir;	/* look up or down the stack */
{
    Interp *iPtr = (Interp *) interp;
    int level, result;
    CallFrame *framePtr = NULL;	/* frame currently being searched */

    CallFrame *curFramePtr = iPtr->varFramePtr;

    /*
     * Parse string to figure out which level number to go to.
     */








|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    char *string;		/* String describing frame. */
    CallFrame **framePtrPtr;	/* Store pointer to frame here (or NULL
				 * if global frame indicated). */
    enum debug_cmd dir;	/* look up or down the stack */
{
    Interp *iPtr = (Interp *) interp;
    int level, result;
    CallFrame *framePtr;	/* frame currently being searched */

    CallFrame *curFramePtr = iPtr->varFramePtr;

    /*
     * Parse string to figure out which level number to go to.
     */

297
298
299
300
301
302
303

304
305
306
307
308
309
310
	if (framePtr == NULL) {
	    goto levelError;
	}
    }
    *framePtrPtr = framePtr;
    return result;
}


static char *printify(s)
char *s;
{
    static int destlen = 0;
    char *d;		/* ptr into dest */
    unsigned int need;







>







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	if (framePtr == NULL) {
	    goto levelError;
	}
    }
    *framePtrPtr = framePtr;
    return result;
}


static char *printify(s)
char *s;
{
    static int destlen = 0;
    char *d;		/* ptr into dest */
    unsigned int need;
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
		if (step_count > 0) goto finish;
		goto start_interact;
	case ret:
		/* same comment as in "case next" */
		if (goalFramePtr != iPtr->varFramePtr) goto finish;
		goto start_interact;
    /* DANGER: unhandled cases! none, up, down, where */
	default:
		break; /* Silence compiler warning */
	}

start_interact:
	if (print_command_first_time) {
		print(interp,"%s: %s\n",
				level_text,print_argv(interp,1,&command));
		print_command_first_time = FALSE;







<
<







654
655
656
657
658
659
660


661
662
663
664
665
666
667
		if (step_count > 0) goto finish;
		goto start_interact;
	case ret:
		/* same comment as in "case next" */
		if (goalFramePtr != iPtr->varFramePtr) goto finish;
		goto start_interact;
    /* DANGER: unhandled cases! none, up, down, where */


	}

start_interact:
	if (print_command_first_time) {
		print(interp,"%s: %s\n",
				level_text,print_argv(interp,1,&command));
		print_command_first_time = FALSE;
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
			break;
		}
		goalFramePtr = goalFramePtr->callerVarPtr;
		goto finish;
	case where:
	PrintStack(interp,iPtr->varFramePtr,viewFramePtr,objc,objv,level_text);
		break;
	default:
		break; /* Silence compiler warning */
	}

	/* restore view and restart interactor */
	iPtr->varFramePtr = viewFramePtr;
	goto start_interact;

 finish:







<
<







712
713
714
715
716
717
718


719
720
721
722
723
724
725
			break;
		}
		goalFramePtr = goalFramePtr->callerVarPtr;
		goto finish;
	case where:
	PrintStack(interp,iPtr->varFramePtr,viewFramePtr,objc,objv,level_text);
		break;


	}

	/* restore view and restart interactor */
	iPtr->varFramePtr = viewFramePtr;
	goto start_interact;

 finish:

Changes to configure.in.

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
	# the default behavior, we must also handle augment LIBS too.
	# This needn't be done in the 2nd and 3rd tests.
	AC_DEFINE(HAVE_OPENPTY)
	LIBS="$LIBS -lutil"
  ])
fi

AC_CHECK_HEADER(libutil.h,AC_DEFINE(HAVE_LIBUTIL_H))

######################################################################
# 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.







<
<







216
217
218
219
220
221
222


223
224
225
226
227
228
229
	# the default behavior, we must also handle augment LIBS too.
	# This needn't be done in the 2nd and 3rd tests.
	AC_DEFINE(HAVE_OPENPTY)
	LIBS="$LIBS -lutil"
  ])
fi



######################################################################
# 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.

Changes to exp_chan.c.

21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include <errno.h>

#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"
#include "exp_event.h"
#include "tcldbg.h" /* Dbg_StdinMode */

extern int		expSetBlockModeProc _ANSI_ARGS_((int fd, int mode));
static int		ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData,
			    int mode));
static int		ExpCloseProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_Interp *interp));







|
>
|







<







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include <errno.h>

#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"

#include "tcldbg.h" /* Dbg_StdinMode */

extern int		expSetBlockModeProc _ANSI_ARGS_((int fd, int mode));
static int		ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData,
			    int mode));
static int		ExpCloseProc _ANSI_ARGS_((ClientData instanceData,
			    Tcl_Interp *interp));
53
54
55
56
57
58
59
60
61
62
63
64
65



66
67

68
69
70
71
72
73
74
		            int direction, ClientData *handlePtr));

/*
 * This structure describes the channel type structure for Expect-based IO:
 */

Tcl_ChannelType expChannelType = {
    .typeName = "exp",			/* Type name. */
    .version = TCL_CHANNEL_VERSION_2,
    .blockModeProc = ExpBlockModeProc,	/* Set blocking/nonblocking mode.*/
    .closeProc = ExpCloseProc,		/* Close proc. */
    .inputProc = ExpInputProc,		/* Input proc. */
    .outputProc = ExpOutputProc,	/* Output proc. */



    .watchProc = ExpWatchProc,		/* Initialize notifier. */
    .getHandleProc = ExpGetHandleProc	/* Get OS handles out of channel. */

};

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.
     */







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







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
		            int direction, ClientData *handlePtr));

/*
 * This structure describes the channel type structure for Expect-based IO:
 */

Tcl_ChannelType expChannelType = {
    "exp",				/* Type name. */

    ExpBlockModeProc,			/* 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.
     */
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
    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)(intptr_t)esPtr->fdin;
    }
    if (direction & TCL_READABLE) {
	*handlePtr = (ClientData)(intptr_t)esPtr->fdin;
    } else {
	return TCL_ERROR;
    }
    return TCL_OK;
}

int







|


|







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    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

Changes to exp_clib.c.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#ifdef HAVE_STRREDIR_H
#include <sys/strredir.h>
# ifdef SRIOCSREDIR
#  undef TIOCCONS
# endif
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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







<
<
<
<







46
47
48
49
50
51
52




53
54
55
56
57
58
59
#ifdef HAVE_STRREDIR_H
#include <sys/strredir.h>
# ifdef SRIOCSREDIR
#  undef TIOCCONS
# endif
#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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

#else
#include <stdlib.h>		/* for malloc */
#endif

#include <tcl.h>
#include "expect.h"
#include "exp_command.h"
#define TclRegError exp_TclRegError

/*
 * regexp code - from tcl8.0.4/generic/regexp.c
 */

/*







<







112
113
114
115
116
117
118

119
120
121
122
123
124
125

#else
#include <stdlib.h>		/* for malloc */
#endif

#include <tcl.h>
#include "expect.h"

#define TclRegError exp_TclRegError

/*
 * regexp code - from tcl8.0.4/generic/regexp.c
 */

/*
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
	}
	fp->buffer_end = fp->buffer;
	fp->match_end = fp->buffer;
	return fp;

}

/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */
/* is called.  setpgrp works though.  */
#if defined(POSIX) && !defined(ultrix) || defined(__convex__)
#define DO_SETSID
#endif

#if !defined(DO_SETSID) && (!defined(SYSV3) || defined(CRAY)) /* { */
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
}
#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 */
#if defined(TIOCNOTTY) && !defined(SYSV3) && !defined(DO_SETSID)
	int ttyfd;
#endif
	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;







<
<
<
<
<
<
<
















<










<

<







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
	}
	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;
2018
2019
2020
2021
2022
2023
2024









2025
2026
2027
2028
2029
2030
2031
	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










#ifdef DO_SETSID
	setsid();
#else
#ifdef SYSV3
#ifndef CRAY
	exp_setpgrp();







>
>
>
>
>
>
>
>
>







2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
	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();
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
	}
#endif /* TIOCNOTTY */

#endif /* SYSV3 */
#endif /* DO_SETSID */

	/* save error fd while we're setting up new one */
#ifdef F_DUPFD_CLOEXEC
	errorfd = fcntl(2,F_DUPFD_CLOEXEC,3);
#else
	errorfd = fcntl(2,F_DUPFD,3);
	fcntl(errorfd, F_SETFD, FD_CLOEXEC);
#endif /* F_DUPFD_CLOXEC */
	/* and here is the macro to restore it */
#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);}

	if (exp_autoallocpty) {

	    close(0);
	    close(1);







<
<
<

<
<







2035
2036
2037
2038
2039
2040
2041



2042


2043
2044
2045
2046
2047
2048
2049
	}
#endif /* TIOCNOTTY */

#endif /* SYSV3 */
#endif /* DO_SETSID */

	/* save error fd while we're setting up new one */



	errorfd = fcntl(2,F_DUPFD,3);


	/* and here is the macro to restore it */
#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);}

	if (exp_autoallocpty) {

	    close(0);
	    close(1);
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
	time_t end_time;	/* future time at which to give up */
	int remtime;		/* remaining time in timeout */

	struct f *f;
	int return_val;
	int sys_error = 0;
#define return_normally(x)	{return_val = x; goto cleanup;}
#define return_errno(x)	{sys_error = x; return_val = -1; goto cleanup;}

	f = fdfp2f(fd,fp);
	if (!f) return_errno(ENOMEM);

	exp_buffer = f->buffer;
	exp_buffer_end = f->buffer_end;
	exp_match_end = f->match_end;







|







2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
	time_t end_time;	/* future time at which to give up */
	int remtime;		/* remaining time in timeout */

	struct f *f;
	int return_val;
	int sys_error = 0;
#define return_normally(x)	{return_val = x; goto cleanup;}
#define return_errno(x)	{sys_error = x; goto cleanup;}

	f = fdfp2f(fd,fp);
	if (!f) return_errno(ENOMEM);

	exp_buffer = f->buffer;
	exp_buffer_end = f->buffer_end;
	exp_match_end = f->match_end;
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
	setbuf(fp,(char *)0);
	return(fp);
}

int
exp_disconnect()
{
#if defined(TIOCNOTTY) && !defined(SYSV3) && !defined(POSIX)
	int ttyfd;
#endif

#ifndef EALREADY
#define EALREADY 37
#endif

	/* presumably, no stderr, so don't bother with error message */
	if (exp_disconnected) sysreturn(EALREADY);







<

<







2849
2850
2851
2852
2853
2854
2855

2856

2857
2858
2859
2860
2861
2862
2863
	setbuf(fp,(char *)0);
	return(fp);
}

int
exp_disconnect()
{

	int ttyfd;


#ifndef EALREADY
#define EALREADY 37
#endif

	/* presumably, no stderr, so don't bother with error message */
	if (exp_disconnected) sysreturn(EALREADY);

Changes to exp_command.c.

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
    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

/* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */
/* is called.  setpgrp works though.  */
#if defined(POSIX) && !defined(ultrix) || defined(__convex__)
#define DO_SETSID
#endif

#if !defined(DO_SETSID) && (!defined(SYSV3) || defined(CRAY)) /* { */
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
}
#endif /* } */

/*ARGSUSED*/
static void
set_slave_name(
    ExpState *esPtr,
    char *name)
{







<
<
<
<
<
<
<
















|







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
    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(
    ExpState *esPtr,
    char *name)
{
584
585
586
587
588
589
590
591


592
593
594
595
596
597
598
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])		/* Argument objects. */
{
    ExpState *esPtr = 0;
    int slave;
    int pid;
#if defined(TIOCNOTTY) && !defined(SYSV3) && !defined(DO_SETSID)


    int ttyfd;
#endif /* TIOCNOTTY */
    int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
    int master, k;
    int write_master;	/* write fd of Tcl-opened files */
    int ttyinit = TRUE;







|
>
>







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])		/* Argument objects. */
{
    ExpState *esPtr = 0;
    int slave;
    int pid;
#ifdef TIOCNOTTY
    /* tell Saber to ignore non-use of ttyfd */
    /*SUPPRESS 591*/
    int ttyfd;
#endif /* TIOCNOTTY */
    int errorfd;	/* place to stash fileno(stderr) in child */
			/* while we're setting up new stderr */
    int master, k;
    int write_master;	/* write fd of Tcl-opened files */
    int ttyinit = TRUE;
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
	    exp_error(interp,"channel is neither readable nor writable");
	    return TCL_ERROR;
	}
	if (mode & TCL_READABLE) {
	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_READABLE, &rfdc)) {
		return TCL_ERROR;
	    }
	    rfd = (int)(intptr_t) rfdc;
	} else {
	    rfd = -1;
	}
	if (mode & TCL_WRITABLE) {
	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_WRITABLE, &wfdc)) {
		return TCL_ERROR;
	    }
	    wfd = (int)(intptr_t) wfdc;
	} else {
	    wfd = -1;
	}
	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;







|
<
<





|
<
<







899
900
901
902
903
904
905
906


907
908
909
910
911
912


913
914
915
916
917
918
919
	    exp_error(interp,"channel is neither readable nor writable");
	    return TCL_ERROR;
	}
	if (mode & TCL_READABLE) {
	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_READABLE, &rfdc)) {
		return TCL_ERROR;
	    }
	    rfd = (int)(long) rfdc;


	}
	if (mode & TCL_WRITABLE) {
	    if (TCL_ERROR == Tcl_GetChannelHandle(channel, TCL_WRITABLE, &wfdc)) {
		return TCL_ERROR;
	    }
	    wfd = (int)(long) wfdc;


	}
	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;
1130
1131
1132
1133
1134
1135
1136









1137
1138
1139
1140
1141
1142
1143
	close(exp_dev_tty);
	exp_dev_tty = -1;
    }

#ifdef CRAY
    (void) close(master);
#endif










#ifdef DO_SETSID
    setsid();
#else
#ifdef SYSV3
#ifndef CRAY
    expSetpgrp();







>
>
>
>
>
>
>
>
>







1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
	close(exp_dev_tty);
	exp_dev_tty = -1;
    }

#ifdef CRAY
    (void) close(master);
#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
    expSetpgrp();
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
#endif /* SYSV3 */
#endif /* DO_SETSID */

    /* save stderr elsewhere to avoid BSD4.4 bogosity that warns */
    /* if stty finds dev(stderr) != dev(stdout) */

    /* save error fd while we're setting up new one */
#ifdef F_DUPFD_CLOEXEC
    errorfd = fcntl(2,F_DUPFD_CLOEXEC,3);
#else
    errorfd = fcntl(2,F_DUPFD,3);
    fcntl(errorfd, F_SETFD, FD_CLOEXEC);
#endif /* F_DUPFD_CLOXEC */
    /* and here is the macro to restore it */
#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);}

    close(0);
    close(1);
    close(2);








<
<
<

<
<







1157
1158
1159
1160
1161
1162
1163



1164


1165
1166
1167
1168
1169
1170
1171
#endif /* SYSV3 */
#endif /* DO_SETSID */

    /* save stderr elsewhere to avoid BSD4.4 bogosity that warns */
    /* if stty finds dev(stderr) != dev(stdout) */

    /* save error fd while we're setting up new one */



    errorfd = fcntl(2,F_DUPFD,3);


    /* and here is the macro to restore it */
#define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);}

    close(0);
    close(1);
    close(2);

1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
#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 = NULL;		/* 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;







|







1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
#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;
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    /* Magic configuration stuff. */
    int i, opt, val;

    static const char* options [] = {
	"-strictwrite", NULL
    };
    enum options {
	EXP_STRICTWRITE
    };

    if ((objc < 3) || (objc % 2 == 0)) {







|







2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    /* Magic configuration stuff. */
    int i, opt, val;

    static CONST84 char* options [] = {
	"-strictwrite", NULL
    };
    enum options {
	EXP_STRICTWRITE
    };

    if ((objc < 3) || (objc % 2 == 0)) {
3115
3116
3117
3118
3119
3120
3121
3122


3123
3124
3125
3126
3127
3128
3129
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])		/* Argument objects. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    
#if defined(TIOCNOTTY) && !defined(SYSV3) && !defined(DO_SETSID)


    int ttyfd;
#endif /* TIOCNOTTY */

    if (objc > 1) {
	exp_error(interp,"usage: disconnect");
	return(TCL_ERROR);
    }







|
>
>







3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST objv[])		/* Argument objects. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    
#ifdef TIOCNOTTY
    /* tell CenterLine to ignore non-use of ttyfd */
    /*SUPPRESS 591*/
    int ttyfd;
#endif /* TIOCNOTTY */

    if (objc > 1) {
	exp_error(interp,"usage: disconnect");
	return(TCL_ERROR);
    }

Changes to exp_event.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#  include <sys/ptyio.h>
#endif

#include "tcl.h"
#include "exp_prog.h"
#include "exp_command.h"	/* for ExpState defs */
#include "exp_event.h"
#include "exp_log.h"

typedef struct ThreadSpecificData {
    int rr;		/* round robin ptr */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;








<







20
21
22
23
24
25
26

27
28
29
30
31
32
33
#  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;

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    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;
	default:
	    expDiagLog("Unexpected value %d of bg-handler in %s",
		esPtr->bg_status, __func__);
    }
}

/* 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)







<
<
<







116
117
118
119
120
121
122



123
124
125
126
127
128
129
    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)

Changes to exp_inter.c.

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
static void
intEcho(
    ExpState *esPtr,
    int skipBytes,
    int matchBytes)
{
    int seenBytes;	/* either printed or echoed */
    int echoBytes = 0;
    int offsetBytes = 0;

    /* 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) {







|
|







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
static void
intEcho(
    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) {
702
703
704
705
706
707
708



709
710
711
712
713
714
715
{
	exp_configure_count++;
	return 0;
}
			
#define finish(x)	{ status = x; goto done; }




/*ARGSUSED*/
int
Exp_InteractObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST initial_objv[])		/* Argument objects. */







>
>
>







702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
{
	exp_configure_count++;
	return 0;
}
			
#define finish(x)	{ status = x; goto done; }

static char return_cmd[] = "return";
static char interpreter_cmd[] = "interpreter";

/*ARGSUSED*/
int
Exp_InteractObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *CONST initial_objv[])		/* Argument objects. */
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
#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 = 0;
	time_t current_time;
	int matchLen = 0;	/* # 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 = NULL;
	int timeout;	/* current as opposed to default_timeout */
	Tcl_Time temp_time;

	/* calculate how long to wait */
	/* by finding shortest remaining timeout */
	if (timeout_simple) {
	    timeout = default_timeout;







|

|





|







1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
#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 */
	Tcl_Time temp_time;

	/* calculate how long to wait */
	/* by finding shortest remaining timeout */
	if (timeout_simple) {
	    timeout = default_timeout;

Changes to exp_log.c.

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    int lenChars;
{
    int wc;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (esPtr->valid)
	wc = expWriteCharsUni(esPtr,buf,lenChars);
    else
	wc = -1;

    if (tsdPtr->logChannel && ((esPtr->fdout == 1) || expDevttyIs(esPtr))) {
      Tcl_DString ds;
      Tcl_DStringInit (&ds);
      Tcl_UniCharToUtfDString (buf,lenChars,&ds);
      Tcl_WriteChars(tsdPtr->logChannel,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds));
      Tcl_DStringFree (&ds);







<
<







86
87
88
89
90
91
92


93
94
95
96
97
98
99
    int lenChars;
{
    int wc;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (esPtr->valid)
	wc = expWriteCharsUni(esPtr,buf,lenChars);



    if (tsdPtr->logChannel && ((esPtr->fdout == 1) || expDevttyIs(esPtr))) {
      Tcl_DString ds;
      Tcl_DStringInit (&ds);
      Tcl_UniCharToUtfDString (buf,lenChars,&ds);
      Tcl_WriteChars(tsdPtr->logChannel,Tcl_DStringValue (&ds), Tcl_DStringLength (&ds));
      Tcl_DStringFree (&ds);

Changes to exp_pty.c.

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	i_read_errno = errno;	/* errno can be overwritten by the */
				/* time we return */
	alarm(0);
	return(cc);
}

static RETSIGTYPE (*oldAlarmHandler)();
#ifndef O_NOCTTY
static RETSIGTYPE (*oldHupHandler)();
#endif
static time_t current_time;	/* time when testing began */

/* if TRUE, begin testing, else end testing */
/* returns -1 for failure, 0 for success */
int
exp_pty_test_start()
{







<

<







131
132
133
134
135
136
137

138

139
140
141
142
143
144
145
	i_read_errno = errno;	/* errno can be overwritten by the */
				/* time we return */
	alarm(0);
	return(cc);
}

static RETSIGTYPE (*oldAlarmHandler)();

static RETSIGTYPE (*oldHupHandler)();

static time_t current_time;	/* time when testing began */

/* if TRUE, begin testing, else end testing */
/* returns -1 for failure, 0 for success */
int
exp_pty_test_start()
{

Changes to exp_trap.c.

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
	exp_error(interp,"invalid signal %s",s);
	
	return -1;
}

/*ARGSUSED*/
int

Exp_TrapObjCmd(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++;

	if (objc <= 0) goto usage_error;

	do {
	  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;
	} while(objc);


	if (show_name || show_number || show_max) {
		if (objc > 0) goto usage_error;
		if (show_max) {
		  Tcl_SetObjResult(interp,Tcl_NewIntObj(NSIG-1));
		}








>
|
|
|
|

















<
|
<


















<
>







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
	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));
		}

Changes to exp_tty.c.

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
;
	int abnormalExit = FALSE;
	char buf[MAX_ARGLIST];
	char *bufp = buf;
	int total_len = 0, arg_len;

	int stty_args_recognized = TRUE;
	int cmd_is_stty;
	int cooked = FALSE;
	const char *was_raw = "-raw", *was_echo = "-echo";

	if (argc == 1) return TCL_OK;

	cmd_is_stty = streq(argv[1],"stty");
	if (cmd_is_stty) {
		expDiagLogU("system stty is deprecated, use stty\r\n");

		if (exp_israw())
			was_raw++;
		if (exp_isecho())
			was_echo++;
	}

	if (argc > 2 && cmd_is_stty) {
		exp_ioctled_devtty = TRUE;

		for (i=2;i<argc;i++) {
			if (streq(argv[i],"raw") ||







|

|



|
<


|
|
<
|







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
;
	int abnormalExit = FALSE;
	char buf[MAX_ARGLIST];
	char *bufp = buf;
	int total_len = 0, arg_len;

	int stty_args_recognized = TRUE;
	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) {
		exp_ioctled_devtty = TRUE;

		for (i=2;i<argc;i++) {
			if (streq(argv[i],"raw") ||
633
634
635
636
637
638
639




640
641
642
643
644
645
646
647
				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) {




			    Tcl_AppendResult (interp, was_raw, " ", was_echo, NULL);
			}
			return(TCL_OK);
		}
	}

	for (i = 1;i<argc;i++) {
		total_len += (1 + (arg_len = strlen(argv[i])));







>
>
>
>
|







631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
				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) {
			    char buf [11];
			    sprintf(buf,"%sraw %secho",
				    (was_raw?"":"-"),
				    (was_echo?"":"-"));
			    Tcl_SetResult (interp, buf, TCL_VOLATILE);
			}
			return(TCL_OK);
		}
	}

	for (i = 1;i<argc;i++) {
		total_len += (1 + (arg_len = strlen(argv[i])));
693
694
695
696
697
698
699




700
701
702
703
704
705
706
707
		if (cooked) {
			/* find out user's new defn of 'cooked' */
			tty_cooked = tty_current;
		}
	}

	if (cmd_is_stty) {




	    Tcl_AppendResult (interp, was_raw, " ", was_echo, NULL);
	}

/* following macros stolen from Tcl's tclUnix.h file */
/* we can't include the whole thing because it depends on other macros */
/* that come out of Tcl's Makefile, sigh */

#if 0







>
>
>
>
|







695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
		if (cooked) {
			/* find out user's new defn of 'cooked' */
			tty_cooked = tty_current;
		}
	}

	if (cmd_is_stty) {
	    char buf [11];
	    sprintf(buf,"%sraw %secho",
		    (was_raw?"":"-"),
		    (was_echo?"":"-"));
	    Tcl_SetResult (interp, buf, TCL_VOLATILE);
	}

/* following macros stolen from Tcl's tclUnix.h file */
/* we can't include the whole thing because it depends on other macros */
/* that come out of Tcl's Makefile, sigh */

#if 0

Changes to exp_tty.h.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
extern int exp_stdin_is_tty;
extern int exp_stdout_is_tty;

void exp_tty_raw(int set);
void exp_tty_echo(int set);
void exp_tty_break(Tcl_Interp *interp, int fd);
int exp_tty_raw_noecho(Tcl_Interp *interp, exp_tty *tty_old, int *was_raw, int *was_echo);
int exp_tty_cooked_echo(Tcl_Interp *interp, exp_tty *tty_old, int *was_raw, int *was_echo);
int exp_israw(void);
int exp_isecho(void);

void exp_tty_set(Tcl_Interp *interp, exp_tty *tty, int raw, int echo);
int exp_tty_set_simple(exp_tty *tty);
int exp_tty_get_simple(exp_tty *tty);








<







15
16
17
18
19
20
21

22
23
24
25
26
27
28
extern int exp_stdin_is_tty;
extern int exp_stdout_is_tty;

void exp_tty_raw(int set);
void exp_tty_echo(int set);
void exp_tty_break(Tcl_Interp *interp, int fd);
int exp_tty_raw_noecho(Tcl_Interp *interp, exp_tty *tty_old, int *was_raw, int *was_echo);

int exp_israw(void);
int exp_isecho(void);

void exp_tty_set(Tcl_Interp *interp, exp_tty *tty, int raw, int echo);
int exp_tty_set_simple(exp_tty *tty);
int exp_tty_get_simple(exp_tty *tty);

Changes to exp_win.c.

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
	int rows;
} exp_winsize;
#endif

static exp_winsize winsize = {0, 0};
static exp_winsize win2size = {0, 0};

int exp_window_size_set(int fd)

{
	return
#ifdef TIOCSWINSZ
	ioctl(fd,TIOCSWINSZ,&winsize);
#endif
#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
	ioctl(fd,TIOCSSIZE,&winsize);
#endif
}

int exp_window_size_get(int fd)

{
	return
#ifdef TIOCGWINSZ
	ioctl(fd,TIOCGWINSZ,&winsize);
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
	ioctl(fd,TIOCGSIZE,&winsize);
#endif
#if !defined(EXP_WIN)
	winsize.rows = 0;
	winsize.columns = 0;
#endif
}

void
exp_win_rows_set(const char *rows)

{
	winsize.rows = atoi(rows);
	exp_window_size_set(exp_dev_tty);
}

char*
exp_win_rows_get()
{
    static char rows [20];
	exp_window_size_get(exp_dev_tty);
	sprintf(rows,"%d",winsize.rows);
    return rows;
}

void
exp_win_columns_set(const char *columns)

{
	winsize.columns = atoi(columns);
	exp_window_size_set(exp_dev_tty);
}

char*
exp_win_columns_get()
{
    static char columns [20];
	exp_window_size_get(exp_dev_tty);
	sprintf(columns,"%d",winsize.columns);
    return columns;
}

/*
 * separate copy of everything above - used for handling user stty requests
 */

static void
exp_win2_size_set(int fd)

{
#ifdef TIOCSWINSZ
			ioctl(fd,TIOCSWINSZ,&win2size);
#endif
#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
			ioctl(fd,TIOCSSIZE,&win2size);
#endif
}

static void
exp_win2_size_get(int fd)

{
#ifdef TIOCGWINSZ
	ioctl(fd,TIOCGWINSZ,&win2size);
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
	ioctl(fd,TIOCGSIZE,&win2size);
#endif
}

void
exp_win2_rows_set(int fd,const char *rows)


{
	exp_win2_size_get(fd);
	win2size.rows = atoi(rows);
	exp_win2_size_set(fd);
}

char*
exp_win2_rows_get(int fd)

{
    static char rows [20];
	exp_win2_size_get(fd);
	sprintf(rows,"%d",win2size.rows);
#if !defined(EXP_WIN)
	win2size.rows = 0;
	win2size.columns = 0;
#endif
    return rows;
}

void
exp_win2_columns_set(int fd,const char *columns)


{
	exp_win2_size_get(fd);
	win2size.columns = atoi(columns);
	exp_win2_size_set(fd);
}

char*
exp_win2_columns_get(int fd)

{
    static char columns [20];
	exp_win2_size_get(fd);
	sprintf(columns,"%d",win2size.columns);
    return columns;
}








|
>

<








|
>

<













|
>















|
>


















<
|
>









<
|
>










|
>
>







|
>












|
>
>







|
>







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
	int rows;
} exp_winsize;
#endif

static exp_winsize winsize = {0, 0};
static exp_winsize win2size = {0, 0};

int exp_window_size_set(fd)
int fd;
{

#ifdef TIOCSWINSZ
	ioctl(fd,TIOCSWINSZ,&winsize);
#endif
#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
	ioctl(fd,TIOCSSIZE,&winsize);
#endif
}

int exp_window_size_get(fd)
int fd;
{

#ifdef TIOCGWINSZ
	ioctl(fd,TIOCGWINSZ,&winsize);
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
	ioctl(fd,TIOCGSIZE,&winsize);
#endif
#if !defined(EXP_WIN)
	winsize.rows = 0;
	winsize.columns = 0;
#endif
}

void
exp_win_rows_set(rows)
char *rows;
{
	winsize.rows = atoi(rows);
	exp_window_size_set(exp_dev_tty);
}

char*
exp_win_rows_get()
{
    static char rows [20];
	exp_window_size_get(exp_dev_tty);
	sprintf(rows,"%d",winsize.rows);
    return rows;
}

void
exp_win_columns_set(columns)
char *columns;
{
	winsize.columns = atoi(columns);
	exp_window_size_set(exp_dev_tty);
}

char*
exp_win_columns_get()
{
    static char columns [20];
	exp_window_size_get(exp_dev_tty);
	sprintf(columns,"%d",winsize.columns);
    return columns;
}

/*
 * separate copy of everything above - used for handling user stty requests
 */


int exp_win2_size_set(fd)
int fd;
{
#ifdef TIOCSWINSZ
			ioctl(fd,TIOCSWINSZ,&win2size);
#endif
#if defined(TIOCSSIZE) && !defined(TIOCSWINSZ)
			ioctl(fd,TIOCSSIZE,&win2size);
#endif
}


int exp_win2_size_get(fd)
int fd;
{
#ifdef TIOCGWINSZ
	ioctl(fd,TIOCGWINSZ,&win2size);
#endif
#if defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
	ioctl(fd,TIOCGSIZE,&win2size);
#endif
}

void
exp_win2_rows_set(fd,rows)
int fd;
char *rows;
{
	exp_win2_size_get(fd);
	win2size.rows = atoi(rows);
	exp_win2_size_set(fd);
}

char*
exp_win2_rows_get(fd)
int fd;
{
    static char rows [20];
	exp_win2_size_get(fd);
	sprintf(rows,"%d",win2size.rows);
#if !defined(EXP_WIN)
	win2size.rows = 0;
	win2size.columns = 0;
#endif
    return rows;
}

void
exp_win2_columns_set(fd,columns)
int fd;
char *columns;
{
	exp_win2_size_get(fd);
	win2size.columns = atoi(columns);
	exp_win2_size_set(fd);
}

char*
exp_win2_columns_get(fd)
int fd;
{
    static char columns [20];
	exp_win2_size_get(fd);
	sprintf(columns,"%d",win2size.columns);
    return columns;
}


Changes to exp_win.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* exp_win.h - window support

Written by: Don Libes, NIST, 10/25/93

This file is in the public domain.  However, the author and NIST
would appreciate credit if you use this file or parts of it.
*/

#include <tcl.h> /* For _ANSI_ARGS_ */

int exp_window_size_set();
int exp_window_size_get();

void  exp_win_rows_set    _ANSI_ARGS_ ((const char* rows));
char* exp_win_rows_get    _ANSI_ARGS_ ((void));
void  exp_win_columns_set _ANSI_ARGS_ ((const char* columns));
char* exp_win_columns_get _ANSI_ARGS_ ((void));

void  exp_win2_rows_set    _ANSI_ARGS_ ((int fd, const char* rows));
char* exp_win2_rows_get    _ANSI_ARGS_ ((int fd));
void  exp_win2_columns_set _ANSI_ARGS_ ((int fd, const char* columns));
char* exp_win2_columns_get _ANSI_ARGS_ ((int fd));













|

|


|

|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* exp_win.h - window support

Written by: Don Libes, NIST, 10/25/93

This file is in the public domain.  However, the author and NIST
would appreciate credit if you use this file or parts of it.
*/

#include <tcl.h> /* For _ANSI_ARGS_ */

int exp_window_size_set();
int exp_window_size_get();

void  exp_win_rows_set    _ANSI_ARGS_ ((char* rows));
char* exp_win_rows_get    _ANSI_ARGS_ ((void));
void  exp_win_columns_set _ANSI_ARGS_ ((char* columns));
char* exp_win_columns_get _ANSI_ARGS_ ((void));

void  exp_win2_rows_set    _ANSI_ARGS_ ((int fd, char* rows));
char* exp_win2_rows_get    _ANSI_ARGS_ ((int fd));
void  exp_win2_columns_set _ANSI_ARGS_ ((int fd, char* columns));
char* exp_win2_columns_get _ANSI_ARGS_ ((int fd));

Changes to expect.c.

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
    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 = 0;		/* 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 = 0;	/* 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 = 0;	/* monitor exp_configure_count */

    int timeout;		/* seconds */
    int remtime;		/* remaining time in timeout */
    int reset_timer;		/* should timer be reset after continue? */
    Tcl_Time temp_time;
    Tcl_Obj* new_cmd = NULL;








|








|







|







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
    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? */
    Tcl_Time temp_time;
    Tcl_Obj* new_cmd = NULL;

2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957

2958
2959
2960
2961
2962
2963
2964
	    
    if (!def) {
	if (!chan) {
	    esPtr = expStateCurrent(interp,0,0,0);
	} else {
	    esPtr = expStateFromChannelName(interp,chan,0,0,0,(char*)cmd);
	}
	if (!esPtr)
	    return(TCL_ERROR);

	*esOut = esPtr;
    }

    *at = i;
    *Default = def;

    return TCL_OK;
}


/*ARGSUSED*/
int
Exp_MatchMaxObjCmd(







|
<
<
<




>







2943
2944
2945
2946
2947
2948
2949
2950



2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
	    
    if (!def) {
	if (!chan) {
	    esPtr = expStateCurrent(interp,0,0,0);
	} else {
	    esPtr = expStateFromChannelName(interp,chan,0,0,0,(char*)cmd);
	}
	if (!esPtr) return(TCL_ERROR);



    }

    *at = i;
    *Default = def;
    *esOut = esPtr;
    return TCL_OK;
}


/*ARGSUSED*/
int
Exp_MatchMaxObjCmd(

Changes to pty_termios.c.

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#  include <unistd.h>
#endif
#ifdef HAVE_INTTYPES_H
#  include <inttypes.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#if defined(HAVE_OPENPTY)
#include <termios.h>
#if defined(HAVE_LIBUTIL_H)
#include <libutil.h>
#else
#include <pty.h>
#endif
#endif

#ifdef NO_STDLIB_H
#include "../compat/stdlib.h"
#else
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H







<
<
<
<
<
<
<
<







59
60
61
62
63
64
65








66
67
68
69
70
71
72
#  include <unistd.h>
#endif
#ifdef HAVE_INTTYPES_H
#  include <inttypes.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>









#ifdef NO_STDLIB_H
#include "../compat/stdlib.h"
#else
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#endif

#include "exp_win.h"

#include "exp_tty_in.h"
#include "exp_rename.h"
#include "exp_pty.h"
#include "exp_int.h"

void expDiagLog();
void expDiagLogPtr();

#include <errno.h>
/*extern char *sys_errlist[];*/








<







98
99
100
101
102
103
104

105
106
107
108
109
110
111
#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[];*/

377
378
379
380
381
382
383
384
385
386

387
388
389
390
391
392
393
394
395
396
397
398
#define R_OK 04
#define W_OK 02
#endif

int
exp_getptymaster()
{
#if !defined(HAVE_CONVEX_GETPTY) && !defined(HAVE_PTYM) && !defined(HAVE_SCO_CLIST_PTYS) && defined(TEST_PTY)
	char *hex, *bank;
#endif

	int master = -1;
	int slave = -1;
#ifdef HAVE_SCO_CLIST_PTYS
	int num;
#endif

	exp_pty_error = 0;

#define TEST_PTY 1

#if defined(HAVE_PTMX) || defined(HAVE_PTMX_BSD)
#undef TEST_PTY







<

<
>


<

<







368
369
370
371
372
373
374

375

376
377
378

379

380
381
382
383
384
385
386
#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;


	exp_pty_error = 0;

#define TEST_PTY 1

#if defined(HAVE_PTMX) || defined(HAVE_PTMX_BSD)
#undef TEST_PTY
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#endif

#if defined(HAVE_PTC) && !defined(HAVE__GETPTY)	/* old SGI, version 3 */
#undef TEST_PTY
	master = open("/dev/ptc", O_RDWR);
	if (master >= 0) {
		int ptynum;
		struct stat stat_buf;

		if (fstat(master, &stat_buf) < 0) {
			close(master);
			return(-1);
		}
		ptynum = minor(stat_buf.st_rdev);
		sprintf(slave_name,"/dev/ttyq%d",ptynum);







<







425
426
427
428
429
430
431

432
433
434
435
436
437
438
#endif

#if defined(HAVE_PTC) && !defined(HAVE__GETPTY)	/* old SGI, version 3 */
#undef TEST_PTY
	master = open("/dev/ptc", O_RDWR);
	if (master >= 0) {
		int ptynum;


		if (fstat(master, &stat_buf) < 0) {
			close(master);
			return(-1);
		}
		ptynum = minor(stat_buf.st_rdev);
		sprintf(slave_name,"/dev/ttyq%d",ptynum);
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

int
exp_getptyslave(
    int ttycopy,
    int ttyinit,
    CONST char *stty_args)
{
	int slave;
#if defined(HAVE_PTMX_BSD)
	char buf[10240];
#endif

	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);
	}







|
<

<







631
632
633
634
635
636
637
638

639

640
641
642
643
644
645
646

int
exp_getptyslave(
    int ttycopy,
    int ttyinit,
    CONST 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);
	}