|
Packit |
a69f91 |
/* exp_main_sub.c - miscellaneous subroutines for Expect or Tk main() */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "expect_cf.h"
|
|
Packit |
a69f91 |
#include <stdio.h>
|
|
Packit |
a69f91 |
#include <errno.h>
|
|
Packit |
a69f91 |
#ifdef HAVE_INTTYPES_H
|
|
Packit |
a69f91 |
# include <inttypes.h>
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
#include <sys/types.h>
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
a69f91 |
# include <unistd.h>
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef HAVE_SYS_WAIT_H
|
|
Packit |
a69f91 |
#include <sys/wait.h>
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "tcl.h"
|
|
Packit |
a69f91 |
#include "tclInt.h"
|
|
Packit |
a69f91 |
#include "exp_rename.h"
|
|
Packit |
a69f91 |
#include "exp_prog.h"
|
|
Packit |
a69f91 |
#include "exp_command.h"
|
|
Packit |
a69f91 |
#include "exp_tty_in.h"
|
|
Packit |
a69f91 |
#include "exp_log.h"
|
|
Packit |
a69f91 |
#include "exp_event.h"
|
|
Packit |
a69f91 |
#ifdef TCL_DEBUGGER
|
|
Packit |
a69f91 |
#include "tcldbg.h"
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifndef EXP_VERSION
|
|
Packit |
a69f91 |
#define EXP_VERSION PACKAGE_VERSION
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
#ifdef __CENTERLINE__
|
|
Packit |
a69f91 |
#undef EXP_VERSION
|
|
Packit |
a69f91 |
#define EXP_VERSION "5.45.4" /* I give up! */
|
|
Packit |
a69f91 |
/* It is not necessary that number */
|
|
Packit |
a69f91 |
/* be accurate. It is just here to */
|
|
Packit |
a69f91 |
/* pacify Centerline which doesn't */
|
|
Packit |
a69f91 |
/* seem to be able to get it from */
|
|
Packit |
a69f91 |
/* the Makefile. */
|
|
Packit |
a69f91 |
#undef SCRIPTDIR
|
|
Packit |
a69f91 |
#define SCRIPTDIR "example/"
|
|
Packit |
a69f91 |
#undef EXECSCRIPTDIR
|
|
Packit |
a69f91 |
#define EXECSCRIPTDIR "example/"
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
char exp_version[] = PACKAGE_VERSION;
|
|
Packit |
a69f91 |
#define NEED_TCL_MAJOR 7
|
|
Packit |
a69f91 |
#define NEED_TCL_MINOR 5
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
char *exp_argv0 = "this program"; /* default program name */
|
|
Packit |
a69f91 |
void (*exp_app_exit)() = 0;
|
|
Packit |
a69f91 |
void (*exp_event_exit)() = 0;
|
|
Packit |
a69f91 |
FILE *exp_cmdfile = 0;
|
|
Packit |
a69f91 |
char *exp_cmdfilename = 0;
|
|
Packit |
a69f91 |
int exp_cmdlinecmds = FALSE;
|
|
Packit |
a69f91 |
int exp_interactive = FALSE;
|
|
Packit |
a69f91 |
int exp_buffer_command_input = FALSE;/* read in entire cmdfile at once */
|
|
Packit |
a69f91 |
int exp_fgets();
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Interp *exp_interp; /* for use by signal handlers who can't figure out */
|
|
Packit |
a69f91 |
/* the interpreter directly */
|
|
Packit |
a69f91 |
int exp_tcl_debugger_available = FALSE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int exp_getpid;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int exp_strict_write = 0;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
usage(interp)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char buffer [] = "exit 1";
|
|
Packit |
a69f91 |
expErrorLog("usage: expect [-div] [-c cmds] [[-f] cmdfile] [args]\r\n");
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* this clumsiness because pty routines don't know Tcl definitions */
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
static
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_pty_exit_for_tcl(clientData)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
exp_pty_exit();
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_pty_exit()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
Tcl_CreateExitHandler(exp_pty_exit_for_tcl,(ClientData)0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* This can be called twice or even recursively - it's safe. */
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_exit_handlers(clientData)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
extern int exp_forked;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Interp *interp = (Tcl_Interp *)clientData;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* use following checks to prevent recursion in exit handlers */
|
|
Packit |
a69f91 |
/* if this code ever supports multiple interps, these should */
|
|
Packit |
a69f91 |
/* become interp-specific */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static int did_app_exit = FALSE;
|
|
Packit |
a69f91 |
static int did_expect_exit = FALSE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!did_expect_exit) {
|
|
Packit |
a69f91 |
did_expect_exit = TRUE;
|
|
Packit |
a69f91 |
/* called user-defined exit routine if one exists */
|
|
Packit |
a69f91 |
if (exp_onexit_action) {
|
|
Packit |
a69f91 |
int result = Tcl_GlobalEval(interp,exp_onexit_action);
|
|
Packit |
a69f91 |
if (result != TCL_OK) Tcl_BackgroundError(interp);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
expDiagLogU("onexit handler called recursively - forcing exit\r\n");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_app_exit) {
|
|
Packit |
a69f91 |
if (!did_app_exit) {
|
|
Packit |
a69f91 |
did_app_exit = TRUE;
|
|
Packit |
a69f91 |
(*exp_app_exit)(interp);
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
expDiagLogU("application exit handler called recursively - forcing exit\r\n");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!exp_disconnected
|
|
Packit |
a69f91 |
&& !exp_forked
|
|
Packit |
a69f91 |
&& (exp_dev_tty != -1)
|
|
Packit |
a69f91 |
&& isatty(exp_dev_tty)) {
|
|
Packit |
a69f91 |
if (exp_ioctled_devtty) {
|
|
Packit |
a69f91 |
exp_tty_set(interp,&exp_tty_original,exp_dev_tty,0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
/* all other files either don't need to be flushed or will be
|
|
Packit |
a69f91 |
implicitly closed at exit. Spawned processes are free to continue
|
|
Packit |
a69f91 |
running, however most will shutdown after seeing EOF on stdin.
|
|
Packit |
a69f91 |
Some systems also deliver SIGHUP and other sigs to idle processes
|
|
Packit |
a69f91 |
which will blow them away if not prepared.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_close_all(interp);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static int
|
|
Packit |
a69f91 |
history_nextid(interp)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
/* unncessarily tricky coding - if nextid isn't defined,
|
|
Packit |
a69f91 |
maintain our own static version */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static int nextid = 0;
|
|
Packit |
a69f91 |
CONST char *nextidstr = Tcl_GetVar2(interp,"tcl::history","nextid",0);
|
|
Packit |
a69f91 |
if (nextidstr) {
|
|
Packit |
a69f91 |
/* intentionally ignore failure */
|
|
Packit |
a69f91 |
(void) sscanf(nextidstr,"%d",&nextid);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
return ++nextid;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* this stupidity because Tcl needs commands in writable space */
|
|
Packit |
a69f91 |
static char prompt1[] = "prompt1";
|
|
Packit |
a69f91 |
static char prompt2[] = "prompt2";
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static char *prompt2_default = "+> ";
|
|
Packit |
a69f91 |
static char prompt1_default[] = "expect%d.%d> ";
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
Exp_Prompt1ObjCmd(clientData, interp, objc, objv)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int objc;
|
|
Packit |
a69f91 |
Tcl_Obj *CONST objv[]; /* Argument objects. */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static char buffer[200];
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Interp *iPtr = (Interp *)interp;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
sprintf(buffer,prompt1_default,iPtr->numLevels,history_nextid(interp));
|
|
Packit |
a69f91 |
Tcl_SetResult(interp,buffer,TCL_STATIC);
|
|
Packit |
a69f91 |
return(TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
Exp_Prompt2ObjCmd(clientData, interp, objc, objv)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int objc;
|
|
Packit |
a69f91 |
Tcl_Obj *CONST objv[];
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
Tcl_SetResult(interp,prompt2_default,TCL_STATIC);
|
|
Packit |
a69f91 |
return(TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
static int
|
|
Packit |
a69f91 |
ignore_procs(interp,s)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
char *s; /* function name */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
return ((s[0] == 'p') &&
|
|
Packit |
a69f91 |
(s[1] == 'r') &&
|
|
Packit |
a69f91 |
(s[2] == 'o') &&
|
|
Packit |
a69f91 |
(s[3] == 'm') &&
|
|
Packit |
a69f91 |
(s[4] == 'p') &&
|
|
Packit |
a69f91 |
(s[5] == 't') &&
|
|
Packit |
a69f91 |
((s[6] == '1') ||
|
|
Packit |
a69f91 |
(s[6] == '2')) &&
|
|
Packit |
a69f91 |
(s[7] == '\0')
|
|
Packit |
a69f91 |
);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* handle an error from Tcl_Eval or Tcl_EvalFile */
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
handle_eval_error(interp,check_for_nostack)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int check_for_nostack;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char *msg;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if errorInfo has something, print it */
|
|
Packit |
a69f91 |
/* else use what's in the interp result */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
msg = Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY);
|
|
Packit |
a69f91 |
if (!msg) msg = Tcl_GetStringResult (interp);
|
|
Packit |
a69f91 |
else if (check_for_nostack) {
|
|
Packit |
a69f91 |
/* suppress errorInfo if generated via */
|
|
Packit |
a69f91 |
/* error ... -nostack */
|
|
Packit |
a69f91 |
if (0 == strncmp("-nostack",msg,8)) return;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* This shouldn't be necessary, but previous test fails
|
|
Packit |
a69f91 |
* because of recent change John made - see eval_trap_action()
|
|
Packit |
a69f91 |
* in exp_trap.c for more info
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
if (exp_nostack_dump) {
|
|
Packit |
a69f91 |
exp_nostack_dump = FALSE;
|
|
Packit |
a69f91 |
return;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* no \n at end, since ccmd will already have one. */
|
|
Packit |
a69f91 |
/* Actually, this is not true if command is last in */
|
|
Packit |
a69f91 |
/* file and has no newline after it, oh well */
|
|
Packit |
a69f91 |
expErrorLogU(exp_cook(msg,(int *)0));
|
|
Packit |
a69f91 |
expErrorLogU("\r\n");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* user has pressed escape char from interact or somehow requested expect.
|
|
Packit |
a69f91 |
If a user-supplied command returns:
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
TCL_ERROR, assume user is experimenting and reprompt
|
|
Packit |
a69f91 |
TCL_OK, ditto
|
|
Packit |
a69f91 |
TCL_RETURN, return TCL_OK (assume user just wants to escape() to return)
|
|
Packit |
a69f91 |
EXP_TCL_RETURN, return TCL_RETURN
|
|
Packit |
a69f91 |
anything else return it
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_interpreter(interp,eofObj)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
Tcl_Obj *eofObj;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
Tcl_Obj *commandPtr = NULL;
|
|
Packit |
a69f91 |
int code;
|
|
Packit |
a69f91 |
int gotPartial;
|
|
Packit |
a69f91 |
Interp *iPtr = (Interp *)interp;
|
|
Packit |
a69f91 |
int tty_changed = FALSE;
|
|
Packit |
a69f91 |
exp_tty tty_old;
|
|
Packit |
a69f91 |
int was_raw, was_echo;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Channel inChannel, outChannel;
|
|
Packit |
a69f91 |
ExpState *esPtr = expStdinoutGet();
|
|
Packit |
a69f91 |
/* int fd = fileno(stdin);*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
expect_key++;
|
|
Packit |
a69f91 |
commandPtr = Tcl_NewObj();
|
|
Packit |
a69f91 |
Tcl_IncrRefCount(commandPtr);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
gotPartial = 0;
|
|
Packit |
a69f91 |
while (TRUE) {
|
|
Packit |
a69f91 |
if (Tcl_IsShared(commandPtr)) {
|
|
Packit |
a69f91 |
Tcl_DecrRefCount(commandPtr);
|
|
Packit |
a69f91 |
commandPtr = Tcl_DuplicateObj(commandPtr);
|
|
Packit |
a69f91 |
Tcl_IncrRefCount(commandPtr);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
outChannel = expStdinoutGet()->channel;
|
|
Packit |
a69f91 |
if (outChannel) {
|
|
Packit |
a69f91 |
Tcl_Flush(outChannel);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (!esPtr->open) {
|
|
Packit |
a69f91 |
code = EXP_EOF;
|
|
Packit |
a69f91 |
goto eof;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* force terminal state */
|
|
Packit |
a69f91 |
tty_changed = exp_tty_cooked_echo(interp,&tty_old,&was_raw,&was_echo);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!gotPartial) {
|
|
Packit |
a69f91 |
code = Tcl_Eval(interp,prompt1);
|
|
Packit |
a69f91 |
if (code == TCL_OK) {
|
|
Packit |
a69f91 |
expStdoutLogU(Tcl_GetStringResult(interp),1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
else expStdoutLog(1,prompt1_default,iPtr->numLevels,history_nextid(interp));
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
code = Tcl_Eval(interp,prompt2);
|
|
Packit |
a69f91 |
if (code == TCL_OK) {
|
|
Packit |
a69f91 |
expStdoutLogU(Tcl_GetStringResult(interp),1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
else expStdoutLogU(prompt2_default,1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
esPtr->force_read = 1;
|
|
Packit |
a69f91 |
code = exp_get_next_event(interp,&esPtr,1,&esPtr,EXP_TIME_INFINITY,
|
|
Packit |
a69f91 |
esPtr->key);
|
|
Packit |
a69f91 |
/* check for code == EXP_TCLERROR? */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (code != EXP_EOF) {
|
|
Packit |
a69f91 |
inChannel = expStdinoutGet()->channel;
|
|
Packit |
a69f91 |
code = Tcl_GetsObj(inChannel, commandPtr);
|
|
Packit |
a69f91 |
#ifdef SIMPLE_EVENT
|
|
Packit |
a69f91 |
if (code == -1 && errno == EINTR) {
|
|
Packit |
a69f91 |
if (Tcl_AsyncReady()) {
|
|
Packit |
a69f91 |
(void) Tcl_AsyncInvoke(interp,TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
if (code < 0) code = EXP_EOF;
|
|
Packit |
a69f91 |
if ((code == 0) && Tcl_Eof(inChannel) && !gotPartial) code = EXP_EOF;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
eof:
|
|
Packit |
a69f91 |
if (code == EXP_EOF) {
|
|
Packit |
a69f91 |
if (eofObj) {
|
|
Packit |
a69f91 |
code = Tcl_EvalObjEx(interp,eofObj,0);
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
code = TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
goto done;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
expDiagWriteObj(commandPtr);
|
|
Packit |
a69f91 |
/* intentionally always write to logfile */
|
|
Packit |
a69f91 |
if (expLogChannelGet()) {
|
|
Packit |
a69f91 |
Tcl_WriteObj(expLogChannelGet(),commandPtr);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
/* no need to write to stdout, since they will see */
|
|
Packit |
a69f91 |
/* it just from it having been echoed as they are */
|
|
Packit |
a69f91 |
/* typing it */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* Add the newline removed by Tcl_GetsObj back to the string.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (Tcl_IsShared(commandPtr)) {
|
|
Packit |
a69f91 |
Tcl_DecrRefCount(commandPtr);
|
|
Packit |
a69f91 |
commandPtr = Tcl_DuplicateObj(commandPtr);
|
|
Packit |
a69f91 |
Tcl_IncrRefCount(commandPtr);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
Tcl_AppendToObj(commandPtr, "\n", 1);
|
|
Packit |
a69f91 |
if (!TclObjCommandComplete(commandPtr)) {
|
|
Packit |
a69f91 |
gotPartial = 1;
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_AppendToObj(commandPtr, "\n", 1);
|
|
Packit |
a69f91 |
if (!TclObjCommandComplete(commandPtr)) {
|
|
Packit |
a69f91 |
gotPartial = 1;
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
gotPartial = 0;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
code = Tcl_RecordAndEvalObj(interp, commandPtr, 0);
|
|
Packit |
a69f91 |
Tcl_DecrRefCount(commandPtr);
|
|
Packit |
a69f91 |
commandPtr = Tcl_NewObj();
|
|
Packit |
a69f91 |
Tcl_IncrRefCount(commandPtr);
|
|
Packit |
a69f91 |
switch (code) {
|
|
Packit |
a69f91 |
char *str;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
case TCL_OK:
|
|
Packit |
a69f91 |
str = Tcl_GetStringResult(interp);
|
|
Packit |
a69f91 |
if (*str != 0) {
|
|
Packit |
a69f91 |
expStdoutLogU(exp_cook(str,(int *)0),1);
|
|
Packit |
a69f91 |
expStdoutLogU("\r\n",1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
case TCL_ERROR:
|
|
Packit |
a69f91 |
handle_eval_error(interp,1);
|
|
Packit |
a69f91 |
/* since user is typing by hand, we expect lots */
|
|
Packit |
a69f91 |
/* of errors, and want to give another chance */
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
#define finish(x) {code = x; goto done;}
|
|
Packit |
a69f91 |
case TCL_BREAK:
|
|
Packit |
a69f91 |
case TCL_CONTINUE:
|
|
Packit |
a69f91 |
finish(code);
|
|
Packit |
a69f91 |
case EXP_TCL_RETURN:
|
|
Packit |
a69f91 |
finish(TCL_RETURN);
|
|
Packit |
a69f91 |
case TCL_RETURN:
|
|
Packit |
a69f91 |
finish(TCL_OK);
|
|
Packit |
a69f91 |
default:
|
|
Packit |
a69f91 |
/* note that ccmd has trailing newline */
|
|
Packit |
a69f91 |
expErrorLog("error %d: ",code);
|
|
Packit |
a69f91 |
expErrorLogU(Tcl_GetString(Tcl_GetObjResult(interp)));
|
|
Packit |
a69f91 |
expErrorLogU("\r\n");
|
|
Packit |
a69f91 |
continue;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
/* cannot fall thru here, must jump to label */
|
|
Packit |
a69f91 |
done:
|
|
Packit |
a69f91 |
if (tty_changed) exp_tty_set(interp,&tty_old,was_raw,was_echo);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_DecrRefCount(commandPtr);
|
|
Packit |
a69f91 |
return(code);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
Exp_ExpVersionObjCmd(clientData, interp, objc, objv)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int objc;
|
|
Packit |
a69f91 |
Tcl_Obj *CONST objv[]; /* Argument objects. */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int emajor, umajor;
|
|
Packit |
a69f91 |
char *user_version; /* user-supplied version string */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (objc == 1) {
|
|
Packit |
a69f91 |
Tcl_SetResult(interp,exp_version,TCL_STATIC);
|
|
Packit |
a69f91 |
return(TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (objc > 3) {
|
|
Packit |
a69f91 |
exp_error(interp,"usage: expect_version [[-exit] version]");
|
|
Packit |
a69f91 |
return(TCL_ERROR);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
user_version = Tcl_GetString (objv[objc==2?1:2]);
|
|
Packit |
a69f91 |
emajor = atoi(exp_version);
|
|
Packit |
a69f91 |
umajor = atoi(user_version);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* first check major numbers */
|
|
Packit |
a69f91 |
if (emajor == umajor) {
|
|
Packit |
a69f91 |
int u, e;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* now check minor numbers */
|
|
Packit |
a69f91 |
char *dot = strchr(user_version,'.');
|
|
Packit |
a69f91 |
if (!dot) {
|
|
Packit |
a69f91 |
exp_error(interp,"version number must include a minor version number");
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
u = atoi(dot+1);
|
|
Packit |
a69f91 |
dot = strchr(exp_version,'.');
|
|
Packit |
a69f91 |
e = atoi(dot+1);
|
|
Packit |
a69f91 |
if (e >= u) return(TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (objc == 2) {
|
|
Packit |
a69f91 |
exp_error(interp,"%s requires Expect version %s (but using %s)",
|
|
Packit |
a69f91 |
exp_argv0,user_version,exp_version);
|
|
Packit |
a69f91 |
return(TCL_ERROR);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
expErrorLog("%s requires Expect version %s (but is using %s)\r\n",
|
|
Packit |
a69f91 |
exp_argv0,user_version,exp_version);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char buffer [] = "exit 1";
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
/*NOTREACHED, but keep compiler from complaining*/
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static char init_auto_path[] = "\
|
|
Packit |
a69f91 |
if {$exp_library != \"\"} {\n\
|
|
Packit |
a69f91 |
lappend auto_path $exp_library\n\
|
|
Packit |
a69f91 |
}\n\
|
|
Packit |
a69f91 |
if {$exp_exec_library != \"\"} {\n\
|
|
Packit |
a69f91 |
lappend auto_path $exp_exec_library\n\
|
|
Packit |
a69f91 |
}";
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
DeleteCmdInfo (clientData, interp)
|
|
Packit |
a69f91 |
ClientData clientData;
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
ckfree (clientData);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
Expect_Init(interp)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static int first_time = TRUE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_CmdInfo* close_info = NULL;
|
|
Packit |
a69f91 |
Tcl_CmdInfo* return_info = NULL;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (first_time) {
|
|
Packit |
a69f91 |
#ifndef USE_TCL_STUBS
|
|
Packit |
a69f91 |
int tcl_major = atoi(TCL_VERSION);
|
|
Packit |
a69f91 |
char *dot = strchr(TCL_VERSION,'.');
|
|
Packit |
a69f91 |
int tcl_minor = atoi(dot+1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (tcl_major < NEED_TCL_MAJOR ||
|
|
Packit |
a69f91 |
(tcl_major == NEED_TCL_MAJOR && tcl_minor < NEED_TCL_MINOR)) {
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
char bufa [20];
|
|
Packit |
a69f91 |
char bufb [20];
|
|
Packit |
a69f91 |
Tcl_Obj* s = Tcl_NewStringObj (exp_argv0,-1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
sprintf(bufa,"%d.%d",tcl_major,tcl_minor);
|
|
Packit |
a69f91 |
sprintf(bufb,"%d.%d",NEED_TCL_MAJOR,NEED_TCL_MINOR);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_AppendStringsToObj (s,
|
|
Packit |
a69f91 |
" compiled with Tcl ", bufa,
|
|
Packit |
a69f91 |
" but needs at least Tcl ", bufb,
|
|
Packit |
a69f91 |
"\n", NULL);
|
|
Packit |
a69f91 |
Tcl_SetObjResult (interp, s);
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifndef USE_TCL_STUBS
|
|
Packit |
a69f91 |
if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* Save initial close and return for later use
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
close_info = (Tcl_CmdInfo*) ckalloc (sizeof (Tcl_CmdInfo));
|
|
Packit |
a69f91 |
if (Tcl_GetCommandInfo(interp, "close", close_info) == 0) {
|
|
Packit |
a69f91 |
ckfree ((char*) close_info);
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
return_info = (Tcl_CmdInfo*) ckalloc (sizeof (Tcl_CmdInfo));
|
|
Packit |
a69f91 |
if (Tcl_GetCommandInfo(interp, "return", return_info) == 0){
|
|
Packit |
a69f91 |
ckfree ((char*) close_info);
|
|
Packit |
a69f91 |
ckfree ((char*) return_info);
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
Tcl_SetAssocData (interp, EXP_CMDINFO_CLOSE, DeleteCmdInfo, (ClientData) close_info);
|
|
Packit |
a69f91 |
Tcl_SetAssocData (interp, EXP_CMDINFO_RETURN, DeleteCmdInfo, (ClientData) return_info);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* Expect redefines close so we need to save the original (pre-expect)
|
|
Packit |
a69f91 |
* definition so it can be restored before exiting.
|
|
Packit |
a69f91 |
*
|
|
Packit |
a69f91 |
* Needed when expect is dynamically loaded after close has
|
|
Packit |
a69f91 |
* been redefined e.g. the virtual file system in tclkit
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
if (TclRenameCommand(interp, "close", "_close.pre_expect") != TCL_OK) {
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (Tcl_PkgProvide(interp, "Expect", PACKAGE_VERSION) != TCL_OK) {
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Preserve(interp);
|
|
Packit |
a69f91 |
Tcl_CreateExitHandler(Tcl_Release,(ClientData)interp);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (first_time) {
|
|
Packit |
a69f91 |
exp_getpid = getpid();
|
|
Packit |
a69f91 |
exp_init_pty();
|
|
Packit |
a69f91 |
exp_init_pty_exit();
|
|
Packit |
a69f91 |
exp_init_tty(); /* do this only now that we have looked at */
|
|
Packit |
a69f91 |
/* original tty state */
|
|
Packit |
a69f91 |
exp_init_stdio();
|
|
Packit |
a69f91 |
exp_init_sig();
|
|
Packit |
a69f91 |
exp_init_event();
|
|
Packit |
a69f91 |
exp_init_trap();
|
|
Packit |
a69f91 |
exp_init_unit_random();
|
|
Packit |
a69f91 |
exp_init_spawn_ids(interp);
|
|
Packit |
a69f91 |
expChannelInit();
|
|
Packit |
a69f91 |
expDiagInit();
|
|
Packit |
a69f91 |
expLogInit();
|
|
Packit |
a69f91 |
expDiagLogPtrSet(expDiagLogU);
|
|
Packit |
a69f91 |
expErrnoMsgSet(Tcl_ErrnoMsg);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_CreateExitHandler(exp_exit_handlers,(ClientData)interp);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
first_time = FALSE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* save last known interp for emergencies */
|
|
Packit |
a69f91 |
exp_interp = interp;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* initialize commands */
|
|
Packit |
a69f91 |
exp_init_most_cmds(interp); /* add misc cmds to interpreter */
|
|
Packit |
a69f91 |
exp_init_expect_cmds(interp); /* add expect cmds to interpreter */
|
|
Packit |
a69f91 |
exp_init_main_cmds(interp); /* add main cmds to interpreter */
|
|
Packit |
a69f91 |
exp_init_trap_cmds(interp); /* add trap cmds to interpreter */
|
|
Packit |
a69f91 |
exp_init_tty_cmds(interp); /* add tty cmds to interpreter */
|
|
Packit |
a69f91 |
exp_init_interact_cmds(interp); /* add interact cmds to interpreter */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* initialize variables */
|
|
Packit |
a69f91 |
exp_init_spawn_id_vars(interp);
|
|
Packit |
a69f91 |
expExpectVarsInit();
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* For each of the the Tcl variables, "expect_library",
|
|
Packit |
a69f91 |
*"exp_library", and "exp_exec_library", set the variable
|
|
Packit |
a69f91 |
* if it does not already exist. This mechanism allows the
|
|
Packit |
a69f91 |
* application calling "Expect_Init()" to set these varaibles
|
|
Packit |
a69f91 |
* to alternate locations from where Expect was built.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (Tcl_GetVar(interp, "expect_library", TCL_GLOBAL_ONLY) == NULL) {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"expect_library",SCRIPTDIR,0);/* deprecated */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (Tcl_GetVar(interp, "exp_library", TCL_GLOBAL_ONLY) == NULL) {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"exp_library",SCRIPTDIR,0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (Tcl_GetVar(interp, "exp_exec_library", TCL_GLOBAL_ONLY) == NULL) {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"exp_exec_library",EXECSCRIPTDIR,0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Eval(interp,init_auto_path);
|
|
Packit |
a69f91 |
Tcl_ResetResult(interp);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef TCL_DEBUGGER
|
|
Packit |
a69f91 |
Dbg_IgnoreFuncs(interp,ignore_procs);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static char sigint_init_default[80];
|
|
Packit |
a69f91 |
static char sigterm_init_default[80];
|
|
Packit |
a69f91 |
static char debug_init_default[] = "trap {exp_debug 1} SIGINT";
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_parse_argv(interp,argc,argv)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int argc;
|
|
Packit |
a69f91 |
char **argv;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char argc_rep[10]; /* enough space for storing literal rep of argc */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int sys_rc = TRUE; /* read system rc file */
|
|
Packit |
a69f91 |
int my_rc = TRUE; /* read personal rc file */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int c;
|
|
Packit |
a69f91 |
int rc;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
extern int optind;
|
|
Packit |
a69f91 |
extern char *optarg;
|
|
Packit |
a69f91 |
char *args; /* ptr to string-rep of all args */
|
|
Packit |
a69f91 |
char *debug_init;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_argv0 = argv[0];
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef TCL_DEBUGGER
|
|
Packit |
a69f91 |
Dbg_ArgcArgv(argc,argv,1);
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* initially, we must assume we are not interactive */
|
|
Packit |
a69f91 |
/* this prevents interactive weirdness courtesy of unknown via -c */
|
|
Packit |
a69f91 |
/* after handling args, we can change our mind */
|
|
Packit |
a69f91 |
Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* there's surely a system macro to do this but I don't know what it is */
|
|
Packit |
a69f91 |
#define EXP_SIG_EXIT(signalnumber) (0x80|signalnumber)
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
sprintf(sigint_init_default, "trap {exit %d} SIGINT", EXP_SIG_EXIT(SIGINT));
|
|
Packit |
a69f91 |
Tcl_Eval(interp,sigint_init_default);
|
|
Packit |
a69f91 |
sprintf(sigterm_init_default,"trap {exit %d} SIGTERM",EXP_SIG_EXIT(SIGTERM));
|
|
Packit |
a69f91 |
Tcl_Eval(interp,sigterm_init_default);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* [#418892]. The '+' character in front of every other option
|
|
Packit |
a69f91 |
* declaration causes 'GNU getopt' to deactivate its
|
|
Packit |
a69f91 |
* non-standard behaviour and switch to POSIX. Other
|
|
Packit |
a69f91 |
* implementations of 'getopt' might recognize the option '-+'
|
|
Packit |
a69f91 |
* because of this, but the following switch will catch this
|
|
Packit |
a69f91 |
* and generate a usage message.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) {
|
|
Packit |
a69f91 |
switch(c) {
|
|
Packit |
a69f91 |
case '-':
|
|
Packit |
a69f91 |
/* getopt already handles -- internally, however */
|
|
Packit |
a69f91 |
/* this allows us to abort getopt when dash is at */
|
|
Packit |
a69f91 |
/* the end of another option which is required */
|
|
Packit |
a69f91 |
/* in order to allow things like -n- on #! line */
|
|
Packit |
a69f91 |
goto abort_getopt;
|
|
Packit |
a69f91 |
case 'c': /* command */
|
|
Packit |
a69f91 |
exp_cmdlinecmds = TRUE;
|
|
Packit |
a69f91 |
rc = Tcl_Eval(interp,optarg);
|
|
Packit |
a69f91 |
if (rc != TCL_OK) {
|
|
Packit |
a69f91 |
expErrorLogU(exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));
|
|
Packit |
a69f91 |
expErrorLogU("\r\n");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'd': expDiagToStderrSet(TRUE);
|
|
Packit |
a69f91 |
expDiagLog("expect version %s\r\n",exp_version);
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
#ifdef TCL_DEBUGGER
|
|
Packit |
a69f91 |
case 'D':
|
|
Packit |
a69f91 |
exp_tcl_debugger_available = TRUE;
|
|
Packit |
a69f91 |
if (Tcl_GetInt(interp,optarg,&rc) != TCL_OK) {
|
|
Packit |
a69f91 |
expErrorLog("%s: -D argument must be 0 or 1\r\n",exp_argv0);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char buffer [] = "exit 1";
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* set up trap handler before Dbg_On so user does */
|
|
Packit |
a69f91 |
/* not have to see it at first debugger prompt */
|
|
Packit |
a69f91 |
if (0 == (debug_init = getenv("EXPECT_DEBUG_INIT"))) {
|
|
Packit |
a69f91 |
debug_init = debug_init_default;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
Tcl_Eval(interp,debug_init);
|
|
Packit |
a69f91 |
if (rc == 1) Dbg_On(interp,0);
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
case 'f': /* name of cmd file */
|
|
Packit |
a69f91 |
exp_cmdfilename = optarg;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'b': /* read cmdfile one part at a time */
|
|
Packit |
a69f91 |
exp_cmdfilename = optarg;
|
|
Packit |
a69f91 |
exp_buffer_command_input = TRUE;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'i': /* interactive */
|
|
Packit |
a69f91 |
exp_interactive = TRUE;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'n': /* don't read personal rc file */
|
|
Packit |
a69f91 |
my_rc = FALSE;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'N': /* don't read system-wide rc file */
|
|
Packit |
a69f91 |
sys_rc = FALSE;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
case 'v':
|
|
Packit |
a69f91 |
printf("expect version %s\n", exp_version);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char buffer [] = "exit 0";
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
default: usage(interp);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
abort_getopt:
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (c = 0;c
|
|
Packit |
a69f91 |
expDiagLog("argv[%d] = ",c);
|
|
Packit |
a69f91 |
expDiagLogU(argv[c]);
|
|
Packit |
a69f91 |
expDiagLogU(" ");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
expDiagLogU("\r\n");
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if user hasn't explicitly requested we be interactive */
|
|
Packit |
a69f91 |
/* look for a file or some other source of commands */
|
|
Packit |
a69f91 |
if (!exp_interactive) {
|
|
Packit |
a69f91 |
/* get cmd file name, if we haven't got it already */
|
|
Packit |
a69f91 |
if (!exp_cmdfilename && (optind < argc)) {
|
|
Packit |
a69f91 |
exp_cmdfilename = argv[optind];
|
|
Packit |
a69f91 |
optind++;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* [#418892]. Skip a "--" found immediately
|
|
Packit |
a69f91 |
* behind the name of the script to
|
|
Packit |
a69f91 |
* execute. Don't try this if there are no
|
|
Packit |
a69f91 |
* arguments behind the "--" anymore. All
|
|
Packit |
a69f91 |
* other appearances of "--" are handled by
|
|
Packit |
a69f91 |
* the "getopt"-loop above.
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if ((optind < argc) &&
|
|
Packit |
a69f91 |
(0 == strcmp ("--", argv[optind]))) {
|
|
Packit |
a69f91 |
optind++;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_cmdfilename) {
|
|
Packit |
a69f91 |
if (streq(exp_cmdfilename,"-")) {
|
|
Packit |
a69f91 |
exp_cmdfile = stdin;
|
|
Packit |
a69f91 |
exp_cmdfilename = 0;
|
|
Packit |
a69f91 |
} else if (exp_buffer_command_input) {
|
|
Packit |
a69f91 |
errno = 0;
|
|
Packit |
a69f91 |
exp_cmdfile = fopen(exp_cmdfilename,"r");
|
|
Packit |
a69f91 |
if (exp_cmdfile) {
|
|
Packit |
a69f91 |
exp_cmdfilename = 0;
|
|
Packit |
a69f91 |
expCloseOnExec(fileno(exp_cmdfile));
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
CONST char *msg;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (errno == 0) {
|
|
Packit |
a69f91 |
msg = "could not read - odd file name?";
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
msg = Tcl_ErrnoMsg(errno);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
expErrorLog("%s: %s\r\n",exp_cmdfilename,msg);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char buffer [] = "exit 1";
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else if (!exp_cmdlinecmds) {
|
|
Packit |
a69f91 |
if (isatty(0)) {
|
|
Packit |
a69f91 |
/* no other source of commands, force interactive */
|
|
Packit |
a69f91 |
exp_interactive = TRUE;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
/* read cmds from redirected stdin */
|
|
Packit |
a69f91 |
exp_cmdfile = stdin;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_interactive) {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp, "tcl_interactive","1",TCL_GLOBAL_ONLY);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* collect remaining args and make into argc, argv0, and argv */
|
|
Packit |
a69f91 |
sprintf(argc_rep,"%d",argc-optind);
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"argc",argc_rep,0);
|
|
Packit |
a69f91 |
expDiagLog("set argc %s\r\n",argc_rep);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_cmdfilename) {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
|
|
Packit |
a69f91 |
expDiagLog("set argv0 \"%s\"\r\n",exp_cmdfilename);
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"argv0",exp_argv0,0);
|
|
Packit |
a69f91 |
expDiagLog("set argv0 \"%s\"\r\n",exp_argv0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
args = Tcl_Merge(argc-optind,argv+optind);
|
|
Packit |
a69f91 |
expDiagLogU("set argv \"");
|
|
Packit |
a69f91 |
expDiagLogU(args);
|
|
Packit |
a69f91 |
expDiagLogU("\"\r\n");
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"argv",args,0);
|
|
Packit |
a69f91 |
Tcl_Free(args);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_interpret_rcfiles(interp,my_rc,sys_rc);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
print_result (interp)
|
|
Packit |
a69f91 |
Tcl_Interp* interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
char* msg = Tcl_GetStringResult (interp);
|
|
Packit |
a69f91 |
if (msg[0] != 0) {
|
|
Packit |
a69f91 |
expErrorLogU(msg);
|
|
Packit |
a69f91 |
expErrorLogU("\r\n");
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static void
|
|
Packit |
a69f91 |
run_exit (interp)
|
|
Packit |
a69f91 |
Tcl_Interp* interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
/* SF #439042 -- Allow overide of "exit" by user / script
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
char buffer [] = "exit 1";
|
|
Packit |
a69f91 |
Tcl_Eval(interp, buffer);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* read rc files */
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_interpret_rcfiles(interp,my_rc,sys_rc)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
int my_rc;
|
|
Packit |
a69f91 |
int sys_rc;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int rc;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (sys_rc) {
|
|
Packit |
a69f91 |
char file[200];
|
|
Packit |
a69f91 |
int fd;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
sprintf(file,"%s/expect.rc",SCRIPTDIR);
|
|
Packit |
a69f91 |
if (-1 != (fd = open(file,0))) {
|
|
Packit |
a69f91 |
if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
|
|
Packit |
a69f91 |
expErrorLog("error executing system initialization file: %s\r\n",file);
|
|
Packit |
a69f91 |
if (rc != TCL_ERROR)
|
|
Packit |
a69f91 |
expErrorLog("Tcl_Eval = %d\r\n",rc);
|
|
Packit |
a69f91 |
print_result (interp);
|
|
Packit |
a69f91 |
run_exit (interp);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
close(fd);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (my_rc) {
|
|
Packit |
a69f91 |
char file[200];
|
|
Packit |
a69f91 |
char *home;
|
|
Packit |
a69f91 |
int fd;
|
|
Packit |
a69f91 |
char *getenv();
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if ((NULL != (home = getenv("DOTDIR"))) ||
|
|
Packit |
a69f91 |
(NULL != (home = getenv("HOME")))) {
|
|
Packit |
a69f91 |
sprintf(file,"%s/.expect.rc",home);
|
|
Packit |
a69f91 |
if (-1 != (fd = open(file,0))) {
|
|
Packit |
a69f91 |
if (TCL_ERROR == (rc = Tcl_EvalFile(interp,file))) {
|
|
Packit |
a69f91 |
expErrorLog("error executing file: %s\r\n",file);
|
|
Packit |
a69f91 |
if (rc != TCL_ERROR)
|
|
Packit |
a69f91 |
expErrorLog("Tcl_Eval = %d\r\n",rc);
|
|
Packit |
a69f91 |
print_result (interp);
|
|
Packit |
a69f91 |
run_exit (interp);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
close(fd);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_interpret_cmdfilename(interp,filename)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
char *filename;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int rc;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
expDiagLog("executing commands from command file %s\r\n",filename);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_ResetResult(interp);
|
|
Packit |
a69f91 |
if (TCL_OK != (rc = Tcl_EvalFile(interp,filename))) {
|
|
Packit |
a69f91 |
/* EvalFile doesn't bother to copy error to errorInfo */
|
|
Packit |
a69f91 |
/* so force it */
|
|
Packit |
a69f91 |
Tcl_AddErrorInfo(interp, "");
|
|
Packit |
a69f91 |
handle_eval_error(interp,0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
return rc;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_interpret_cmdfile(interp,fp)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
FILE *fp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int rc = 0;
|
|
Packit |
a69f91 |
int gotPartial;
|
|
Packit |
a69f91 |
int eof;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_DString dstring;
|
|
Packit |
a69f91 |
Tcl_DStringInit(&dstring);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
expDiagLogU("executing commands from command file\r\n");
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
gotPartial = 0;
|
|
Packit |
a69f91 |
eof = FALSE;
|
|
Packit |
a69f91 |
while (1) {
|
|
Packit |
a69f91 |
char line[BUFSIZ];/* buffer for partial Tcl command */
|
|
Packit |
a69f91 |
char *ccmd; /* pointer to complete Tcl command */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (fgets(line,BUFSIZ,fp) == NULL) {
|
|
Packit |
a69f91 |
if (!gotPartial) break;
|
|
Packit |
a69f91 |
eof = TRUE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
ccmd = Tcl_DStringAppend(&dstring,line,-1);
|
|
Packit |
a69f91 |
if (!Tcl_CommandComplete(ccmd) && !eof) {
|
|
Packit |
a69f91 |
gotPartial = 1;
|
|
Packit |
a69f91 |
continue; /* continue collecting command */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
gotPartial = 0;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
rc = Tcl_Eval(interp,ccmd);
|
|
Packit |
a69f91 |
Tcl_DStringFree(&dstring);
|
|
Packit |
a69f91 |
if (rc != TCL_OK) {
|
|
Packit |
a69f91 |
handle_eval_error(interp,0);
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (eof) break;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
Tcl_DStringFree(&dstring);
|
|
Packit |
a69f91 |
return rc;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static struct exp_cmd_data cmd_data[] = {
|
|
Packit |
a69f91 |
{"exp_version", Exp_ExpVersionObjCmd, 0, 0, 0},
|
|
Packit |
a69f91 |
{"prompt1", Exp_Prompt1ObjCmd, 0, 0, EXP_NOPREFIX},
|
|
Packit |
a69f91 |
{"prompt2", Exp_Prompt2ObjCmd, 0, 0, EXP_NOPREFIX},
|
|
Packit |
a69f91 |
{0}};
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_main_cmds(interp)
|
|
Packit |
a69f91 |
Tcl_Interp *interp;
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
exp_create_commands(interp,cmd_data);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* Local Variables:
|
|
Packit |
a69f91 |
* mode: c
|
|
Packit |
a69f91 |
* c-basic-offset: 4
|
|
Packit |
a69f91 |
* fill-column: 78
|
|
Packit |
a69f91 |
* End:
|
|
Packit |
a69f91 |
*/
|