Blame exp_main_sub.c

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