|
Packit |
a69f91 |
/* exp_tty.c - tty support routines */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "expect_cf.h"
|
|
Packit |
a69f91 |
#include <stdio.h>
|
|
Packit |
a69f91 |
#include <signal.h>
|
|
Packit |
a69f91 |
#include "string.h"
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef HAVE_SYS_FCNTL_H
|
|
Packit |
a69f91 |
# include <sys/fcntl.h>
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
# include <fcntl.h>
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include <sys/stat.h>
|
|
Packit |
a69f91 |
|
|
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 |
#if defined(SIGCLD) && !defined(SIGCHLD)
|
|
Packit |
a69f91 |
#define SIGCHLD SIGCLD
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#include "tcl.h"
|
|
Packit |
a69f91 |
#include "exp_prog.h"
|
|
Packit |
a69f91 |
#include "exp_rename.h"
|
|
Packit |
a69f91 |
#include "exp_tty_in.h"
|
|
Packit |
a69f91 |
#include "exp_command.h"
|
|
Packit |
a69f91 |
#include "exp_log.h"
|
|
Packit |
a69f91 |
#include "exp_win.h"
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static int is_raw = FALSE;
|
|
Packit |
a69f91 |
static int is_noecho = FALSE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int exp_ioctled_devtty = FALSE;
|
|
Packit |
a69f91 |
int exp_stdin_is_tty;
|
|
Packit |
a69f91 |
int exp_stdout_is_tty;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*static*/ extern exp_tty exp_tty_current, exp_tty_cooked;
|
|
Packit |
a69f91 |
#define tty_current exp_tty_current
|
|
Packit |
a69f91 |
#define tty_cooked exp_tty_cooked
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_israw(void)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
return is_raw;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_isecho(void)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
return !is_noecho;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if set == 1, set it to raw, else unset it */
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_tty_raw(int set)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (set == 1) {
|
|
Packit |
a69f91 |
is_raw = TRUE;
|
|
Packit |
a69f91 |
#if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO) /* had POSIX too */
|
|
Packit |
a69f91 |
tty_current.c_iflag = 0;
|
|
Packit |
a69f91 |
tty_current.c_oflag = 0;
|
|
Packit |
a69f91 |
tty_current.c_lflag &= ECHO; /* disable everything but echo */
|
|
Packit |
a69f91 |
tty_current.c_cc[VMIN] = 1;
|
|
Packit |
a69f91 |
tty_current.c_cc[VTIME] = 0;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
tty_current.c_iflag = tty_cooked.c_iflag;
|
|
Packit |
a69f91 |
tty_current.c_oflag = tty_cooked.c_oflag;
|
|
Packit |
a69f91 |
/* tty_current.c_lflag = tty_cooked.c_lflag;*/
|
|
Packit |
a69f91 |
/* attempt 2 tty_current.c_lflag = tty_cooked.c_lflag & ~ECHO;*/
|
|
Packit |
a69f91 |
/* retain current echo setting */
|
|
Packit |
a69f91 |
tty_current.c_lflag = (tty_cooked.c_lflag & ~ECHO) | (tty_current.c_lflag & ECHO);
|
|
Packit |
a69f91 |
tty_current.c_cc[VMIN] = tty_cooked.c_cc[VMIN];
|
|
Packit |
a69f91 |
tty_current.c_cc[VTIME] = tty_cooked.c_cc[VTIME];
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
# if defined(HAVE_SGTTYB)
|
|
Packit |
a69f91 |
tty_current.sg_flags |= RAW;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
tty_current.sg_flags = tty_cooked.sg_flags;
|
|
Packit |
a69f91 |
# endif
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
is_raw = FALSE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_tty_echo(int set)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (set == 1) {
|
|
Packit |
a69f91 |
is_noecho = FALSE;
|
|
Packit |
a69f91 |
#if defined(HAVE_TERMIOS) || defined(HAVE_TERMIO) /* had POSIX too */
|
|
Packit |
a69f91 |
tty_current.c_lflag |= ECHO;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
tty_current.c_lflag &= ~ECHO;
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
tty_current.sg_flags |= ECHO;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
tty_current.sg_flags &= ~ECHO;
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
is_noecho = TRUE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_tty_set_simple(exp_tty *tty)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
#ifdef HAVE_TCSETATTR
|
|
Packit |
a69f91 |
return(tcsetattr(exp_dev_tty, TCSADRAIN,tty));
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
return(ioctl (exp_dev_tty, TCSETSW ,tty));
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_tty_get_simple(exp_tty *tty)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
#ifdef HAVE_TCSETATTR
|
|
Packit |
a69f91 |
return(tcgetattr(exp_dev_tty, tty));
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
return(ioctl (exp_dev_tty, TCGETS, tty));
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* returns 0 if nothing changed */
|
|
Packit |
a69f91 |
/* if something changed, the out parameters are changed as well */
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_tty_raw_noecho(
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
exp_tty *tty_old,
|
|
Packit |
a69f91 |
int *was_raw,
|
|
Packit |
a69f91 |
int *was_echo)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (exp_disconnected) return(0);
|
|
Packit |
a69f91 |
if (is_raw && is_noecho) return(0);
|
|
Packit |
a69f91 |
if (exp_dev_tty == -1) return(0);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
*tty_old = tty_current; /* save old parameters */
|
|
Packit |
a69f91 |
*was_raw = is_raw;
|
|
Packit |
a69f91 |
*was_echo = !is_noecho;
|
|
Packit |
a69f91 |
expDiagLog("tty_raw_noecho: was raw = %d echo = %d\r\n",is_raw,!is_noecho);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_tty_raw(1);
|
|
Packit |
a69f91 |
exp_tty_echo(-1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_tty_set_simple(&tty_current) == -1) {
|
|
Packit |
a69f91 |
expErrorLog("ioctl(raw): %s\r\n",Tcl_PosixError(interp));
|
|
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 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
return(1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* returns 0 if nothing changed */
|
|
Packit |
a69f91 |
/* if something changed, the out parameters are changed as well */
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_tty_cooked_echo(
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
exp_tty *tty_old,
|
|
Packit |
a69f91 |
int *was_raw,
|
|
Packit |
a69f91 |
int *was_echo)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (exp_disconnected) return(0);
|
|
Packit |
a69f91 |
if (!is_raw && !is_noecho) return(0);
|
|
Packit |
a69f91 |
if (exp_dev_tty == -1) return(0);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
*tty_old = tty_current; /* save old parameters */
|
|
Packit |
a69f91 |
*was_raw = is_raw;
|
|
Packit |
a69f91 |
*was_echo = !is_noecho;
|
|
Packit |
a69f91 |
expDiagLog("tty_cooked_echo: was raw = %d echo = %d\r\n",is_raw,!is_noecho);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
exp_tty_raw(-1);
|
|
Packit |
a69f91 |
exp_tty_echo(1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (exp_tty_set_simple(&tty_current) == -1) {
|
|
Packit |
a69f91 |
expErrorLog("ioctl(noraw): %s\r\n",Tcl_PosixError(interp));
|
|
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 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
return(1);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_tty_set(
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
exp_tty *tty,
|
|
Packit |
a69f91 |
int raw,
|
|
Packit |
a69f91 |
int echo)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
if (exp_tty_set_simple(tty) == -1) {
|
|
Packit |
a69f91 |
expErrorLog("ioctl(set): %s\r\n",Tcl_PosixError(interp));
|
|
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 |
is_raw = raw;
|
|
Packit |
a69f91 |
is_noecho = !echo;
|
|
Packit |
a69f91 |
tty_current = *tty;
|
|
Packit |
a69f91 |
expDiagLog("tty_set: raw = %d, echo = %d\r\n",is_raw,!is_noecho);
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#if 0
|
|
Packit |
a69f91 |
/* avoids scoping problems */
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_update_cooked_from_current() {
|
|
Packit |
a69f91 |
tty_cooked = tty_current;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_update_real_tty_from_current() {
|
|
Packit |
a69f91 |
return(exp_tty_set_simple(&tty_current));
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int
|
|
Packit |
a69f91 |
exp_update_current_from_real_tty() {
|
|
Packit |
a69f91 |
return(exp_tty_get_simple(&tty_current));
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_stdio()
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
exp_stdin_is_tty = isatty(0);
|
|
Packit |
a69f91 |
exp_stdout_is_tty = isatty(1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
setbuf(stdout,(char *)0); /* unbuffer stdout */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_tty_break(
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
int fd)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
#ifdef POSIX
|
|
Packit |
a69f91 |
tcsendbreak(fd,0);
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
# ifdef TIOCSBRK
|
|
Packit |
a69f91 |
ioctl(fd,TIOCSBRK,0);
|
|
Packit |
a69f91 |
exp_dsleep(interp,0.25); /* sleep for at least a quarter of a second */
|
|
Packit |
a69f91 |
ioctl(fd,TIOCCBRK,0);
|
|
Packit |
a69f91 |
# else
|
|
Packit |
a69f91 |
/* dunno how to do this - ignore */
|
|
Packit |
a69f91 |
# endif
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* take strings with newlines and insert carriage-returns. This allows user */
|
|
Packit |
a69f91 |
/* to write send_user strings without always putting in \r. */
|
|
Packit |
a69f91 |
/* If len == 0, use strlen to compute it */
|
|
Packit |
a69f91 |
/* NB: if terminal is not in raw mode, nothing is done. */
|
|
Packit |
a69f91 |
char *
|
|
Packit |
a69f91 |
exp_cook(
|
|
Packit |
a69f91 |
char *s,
|
|
Packit |
a69f91 |
int *len) /* current and new length of s */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
static int destlen = 0;
|
|
Packit |
a69f91 |
static char *dest = 0;
|
|
Packit |
a69f91 |
char *d; /* ptr into dest */
|
|
Packit |
a69f91 |
unsigned int need;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (s == 0) return("<null>");
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!is_raw) return(s);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* worst case is every character takes 2 to represent */
|
|
Packit |
a69f91 |
need = 1 + 2*(len?*len:strlen(s));
|
|
Packit |
a69f91 |
if (need > destlen) {
|
|
Packit |
a69f91 |
if (dest) ckfree(dest);
|
|
Packit |
a69f91 |
dest = ckalloc(need);
|
|
Packit |
a69f91 |
destlen = need;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (d = dest;*s;s++) {
|
|
Packit |
a69f91 |
if (*s == '\n') {
|
|
Packit |
a69f91 |
*d++ = '\r';
|
|
Packit |
a69f91 |
*d++ = '\n';
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
*d++ = *s;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
*d = '\0';
|
|
Packit |
a69f91 |
if (len) *len = d-dest;
|
|
Packit |
a69f91 |
return(dest);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static int /* returns TCL_whatever */
|
|
Packit |
a69f91 |
exec_stty(
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
int argc,
|
|
Packit |
a69f91 |
char **argv,
|
|
Packit |
a69f91 |
int devtty) /* if true, redirect to /dev/tty */
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int i;
|
|
Packit |
a69f91 |
int rc;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_Obj *cmdObj = Tcl_NewStringObj("",0);
|
|
Packit |
a69f91 |
Tcl_IncrRefCount(cmdObj);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_AppendStringsToObj(cmdObj,"exec ",(char *)0);
|
|
Packit |
a69f91 |
Tcl_AppendStringsToObj(cmdObj,STTY_BIN,(char *)0);
|
|
Packit |
a69f91 |
for (i=1;i
|
|
Packit |
a69f91 |
Tcl_AppendStringsToObj(cmdObj," ",argv[i],(char *)0);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (devtty) Tcl_AppendStringsToObj(cmdObj,
|
|
Packit |
a69f91 |
#ifdef STTY_READS_STDOUT
|
|
Packit |
a69f91 |
" >/dev/tty",
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
"
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
(char *)0);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_ResetResult(interp);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*
|
|
Packit |
a69f91 |
* normally, I wouldn't set one of Tcl's own variables, but in this
|
|
Packit |
a69f91 |
* case, I only want to see if Tcl resets it to non-NONE, and I don't
|
|
Packit |
a69f91 |
* know any other way of doing it
|
|
Packit |
a69f91 |
*/
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_SetVar(interp,"errorCode","NONE",0);
|
|
Packit |
a69f91 |
rc = Tcl_EvalObjEx(interp,cmdObj,TCL_EVAL_DIRECT);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
Tcl_DecrRefCount(cmdObj);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if stty-reads-stdout, stty will fail since Exec */
|
|
Packit |
a69f91 |
/* will detect the stderr. Only by examining errorCode */
|
|
Packit |
a69f91 |
/* can we tell if a real error occurred. */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#ifdef STTY_READS_STDOUT
|
|
Packit |
a69f91 |
if (rc == TCL_ERROR) {
|
|
Packit |
a69f91 |
char *ec = Tcl_GetVar(interp,"errorCode",TCL_GLOBAL_ONLY);
|
|
Packit |
a69f91 |
if (ec && !streq(ec,"NONE")) return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
static int
|
|
Packit |
a69f91 |
Exp_SttyCmd(
|
|
Packit |
a69f91 |
ClientData clientData,
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
int argc,
|
|
Packit |
a69f91 |
char **argv)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
/* redirection symbol is not counted as a stty arg in terms */
|
|
Packit |
a69f91 |
/* of recognition. */
|
|
Packit |
a69f91 |
int saw_unknown_stty_arg = FALSE;
|
|
Packit |
a69f91 |
int saw_known_stty_arg = FALSE;
|
|
Packit |
a69f91 |
int no_args = TRUE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int rc = TCL_OK;
|
|
Packit |
a69f91 |
int cooked = FALSE;
|
|
Packit |
a69f91 |
int was_raw, was_echo;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
char **redirect; /* location of "<" */
|
|
Packit |
a69f91 |
char *infile = 0;
|
|
Packit |
a69f91 |
int fd; /* (slave) fd of infile */
|
|
Packit |
a69f91 |
int master = -1; /* master fd of infile */
|
|
Packit |
a69f91 |
char **argv0 = argv;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (argv=argv0+1;*argv;argv++) {
|
|
Packit |
a69f91 |
if (argv[0][0] == '<') {
|
|
Packit |
a69f91 |
redirect = argv;
|
|
Packit |
a69f91 |
infile = *(argv+1);
|
|
Packit |
a69f91 |
if (!infile) {
|
|
Packit |
a69f91 |
expErrorLog("usage: < ttyname");
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (streq(infile,"/dev/tty")) {
|
|
Packit |
a69f91 |
infile = 0;
|
|
Packit |
a69f91 |
*argv = 0;
|
|
Packit |
a69f91 |
*(argv+1) = 0;
|
|
Packit |
a69f91 |
argc -= 2;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
master = exp_trap_off(infile);
|
|
Packit |
a69f91 |
if (-1 == (fd = open(infile,2))) {
|
|
Packit |
a69f91 |
expErrorLog("couldn't open %s: %s",
|
|
Packit |
a69f91 |
infile,Tcl_PosixError(interp));
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!infile) { /* work on /dev/tty */
|
|
Packit |
a69f91 |
was_raw = exp_israw();
|
|
Packit |
a69f91 |
was_echo = exp_isecho();
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (argv=argv0+1;*argv;argv++) {
|
|
Packit |
a69f91 |
if (streq(*argv,"raw") ||
|
|
Packit |
a69f91 |
streq(*argv,"-cooked")) {
|
|
Packit |
a69f91 |
exp_tty_raw(1);
|
|
Packit |
a69f91 |
saw_known_stty_arg = TRUE;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else if (streq(*argv,"-raw") ||
|
|
Packit |
a69f91 |
streq(*argv,"cooked")) {
|
|
Packit |
a69f91 |
cooked = TRUE;
|
|
Packit |
a69f91 |
exp_tty_raw(-1);
|
|
Packit |
a69f91 |
saw_known_stty_arg = TRUE;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else if (streq(*argv,"echo")) {
|
|
Packit |
a69f91 |
exp_tty_echo(1);
|
|
Packit |
a69f91 |
saw_known_stty_arg = TRUE;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else if (streq(*argv,"-echo")) {
|
|
Packit |
a69f91 |
exp_tty_echo(-1);
|
|
Packit |
a69f91 |
saw_known_stty_arg = TRUE;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else if (streq(*argv,"rows")) {
|
|
Packit |
a69f91 |
if (*(argv+1)) {
|
|
Packit |
a69f91 |
exp_win_rows_set(*(argv+1));
|
|
Packit |
a69f91 |
argv++;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, exp_win_rows_get(), TCL_VOLATILE);
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else if (streq(*argv,"columns")) {
|
|
Packit |
a69f91 |
if (*(argv+1)) {
|
|
Packit |
a69f91 |
exp_win_columns_set(*(argv+1));
|
|
Packit |
a69f91 |
argv++;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, exp_win_columns_get(), TCL_VOLATILE);
|
|
Packit |
a69f91 |
return TCL_OK;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
saw_unknown_stty_arg = TRUE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
/* if any unknown args, let real stty try */
|
|
Packit |
a69f91 |
if (saw_unknown_stty_arg || no_args) {
|
|
Packit |
a69f91 |
if (saw_unknown_stty_arg) {
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* let real stty try */
|
|
Packit |
a69f91 |
rc = exec_stty(interp,argc,argv0,1);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* find out what weird options user asked for */
|
|
Packit |
a69f91 |
if (exp_tty_get_simple(&tty_current) == -1) {
|
|
Packit |
a69f91 |
exp_error(interp,"stty: ioctl(get): %s\r\n",Tcl_PosixError(interp));
|
|
Packit |
a69f91 |
rc = TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (cooked) {
|
|
Packit |
a69f91 |
/* find out user's new defn of 'cooked' */
|
|
Packit |
a69f91 |
tty_cooked = tty_current;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else if (saw_known_stty_arg) {
|
|
Packit |
a69f91 |
if (exp_tty_set_simple(&tty_current) == -1) {
|
|
Packit |
a69f91 |
if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
|
|
Packit |
a69f91 |
expErrorLog("stty: impossible in this context\n");
|
|
Packit |
a69f91 |
expErrorLog("are you disconnected or in a batch, at, or cron script?");
|
|
Packit |
a69f91 |
/* user could've conceivably closed /dev/tty as well */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
exp_error(interp,"stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
|
|
Packit |
a69f91 |
rc = TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if no result, make a crude one */
|
|
Packit |
a69f91 |
if (0 == strcmp(Tcl_GetString(Tcl_GetObjResult(interp)),"")) {
|
|
Packit |
a69f91 |
char buf [11];
|
|
Packit |
a69f91 |
sprintf(buf,"%sraw %secho",
|
|
Packit |
a69f91 |
(was_raw?"":"-"),
|
|
Packit |
a69f91 |
(was_echo?"":"-"));
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, buf, TCL_VOLATILE);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
/* a different tty */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* temporarily zap redirect */
|
|
Packit |
a69f91 |
char *redirect_save = *redirect;
|
|
Packit |
a69f91 |
*redirect = 0;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (argv=argv0+1;*argv;argv++) {
|
|
Packit |
a69f91 |
if (streq(*argv,"rows")) {
|
|
Packit |
a69f91 |
if (*(argv+1)) {
|
|
Packit |
a69f91 |
exp_win2_rows_set(fd,*(argv+1));
|
|
Packit |
a69f91 |
argv++;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, exp_win2_rows_get(fd), TCL_VOLATILE);
|
|
Packit |
a69f91 |
goto done;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else if (streq(*argv,"columns")) {
|
|
Packit |
a69f91 |
if (*(argv+1)) {
|
|
Packit |
a69f91 |
exp_win2_columns_set(fd,*(argv+1));
|
|
Packit |
a69f91 |
argv++;
|
|
Packit |
a69f91 |
no_args = FALSE;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, exp_win2_columns_get(fd), TCL_VOLATILE);
|
|
Packit |
a69f91 |
goto done;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
} else if (streq(*argv,"<")) {
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
saw_unknown_stty_arg = TRUE;
|
|
Packit |
a69f91 |
break;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* restore redirect */
|
|
Packit |
a69f91 |
*redirect = redirect_save;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
close(fd); /* no more use for this, from now on */
|
|
Packit |
a69f91 |
/* pass by name */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (saw_unknown_stty_arg || no_args) {
|
|
Packit |
a69f91 |
#ifdef STTY_READS_STDOUT
|
|
Packit |
a69f91 |
/* switch "<" to ">" */
|
|
Packit |
a69f91 |
char original_redirect_char = (*redirect)[0];
|
|
Packit |
a69f91 |
(*redirect)[0] = '>';
|
|
Packit |
a69f91 |
/* stderr unredirected so we can get it directly! */
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
rc = exec_stty(interp,argc,argv0,0);
|
|
Packit |
a69f91 |
#ifdef STTY_READS_STDOUT
|
|
Packit |
a69f91 |
/* restore redirect - don't know if necessary */
|
|
Packit |
a69f91 |
(*redirect)[0] = original_redirect_char;
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
done:
|
|
Packit |
a69f91 |
exp_trap_on(master);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
return rc;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/*ARGSUSED*/
|
|
Packit |
a69f91 |
static int
|
|
Packit |
a69f91 |
Exp_SystemCmd(
|
|
Packit |
a69f91 |
ClientData clientData,
|
|
Packit |
a69f91 |
Tcl_Interp *interp,
|
|
Packit |
a69f91 |
int argc,
|
|
Packit |
a69f91 |
char **argv)
|
|
Packit |
a69f91 |
{
|
|
Packit |
a69f91 |
int result = TCL_OK;
|
|
Packit |
a69f91 |
RETSIGTYPE (*old)(); /* save old sigalarm handler */
|
|
Packit |
a69f91 |
#define MAX_ARGLIST 10240
|
|
Packit |
a69f91 |
int i;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
WAIT_STATUS_TYPE waitStatus;
|
|
Packit |
a69f91 |
int systemStatus
|
|
Packit |
a69f91 |
;
|
|
Packit |
a69f91 |
int abnormalExit = FALSE;
|
|
Packit |
a69f91 |
char buf[MAX_ARGLIST];
|
|
Packit |
a69f91 |
char *bufp = buf;
|
|
Packit |
a69f91 |
int total_len = 0, arg_len;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
int stty_args_recognized = TRUE;
|
|
Packit |
a69f91 |
int cmd_is_stty = FALSE;
|
|
Packit |
a69f91 |
int cooked = FALSE;
|
|
Packit |
a69f91 |
int was_raw, was_echo;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (argc == 1) return TCL_OK;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (streq(argv[1],"stty")) {
|
|
Packit |
a69f91 |
expDiagLogU("system stty is deprecated, use stty\r\n");
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
cmd_is_stty = TRUE;
|
|
Packit |
a69f91 |
was_raw = exp_israw();
|
|
Packit |
a69f91 |
was_echo = exp_isecho();
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (argc > 2 && cmd_is_stty) {
|
|
Packit |
a69f91 |
exp_ioctled_devtty = TRUE;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (i=2;i
|
|
Packit |
a69f91 |
if (streq(argv[i],"raw") ||
|
|
Packit |
a69f91 |
streq(argv[i],"-cooked")) {
|
|
Packit |
a69f91 |
exp_tty_raw(1);
|
|
Packit |
a69f91 |
} else if (streq(argv[i],"-raw") ||
|
|
Packit |
a69f91 |
streq(argv[i],"cooked")) {
|
|
Packit |
a69f91 |
cooked = TRUE;
|
|
Packit |
a69f91 |
exp_tty_raw(-1);
|
|
Packit |
a69f91 |
} else if (streq(argv[i],"echo")) {
|
|
Packit |
a69f91 |
exp_tty_echo(1);
|
|
Packit |
a69f91 |
} else if (streq(argv[i],"-echo")) {
|
|
Packit |
a69f91 |
exp_tty_echo(-1);
|
|
Packit |
a69f91 |
} else stty_args_recognized = FALSE;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* if unknown args, fall thru and let real stty have a go */
|
|
Packit |
a69f91 |
if (stty_args_recognized) {
|
|
Packit |
a69f91 |
if (
|
|
Packit |
a69f91 |
#ifdef HAVE_TCSETATTR
|
|
Packit |
a69f91 |
tcsetattr(exp_dev_tty,TCSADRAIN, &tty_current) == -1
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
ioctl(exp_dev_tty, TCSETSW, &tty_current) == -1
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
) {
|
|
Packit |
a69f91 |
if (exp_disconnected || (exp_dev_tty == -1) || !isatty(exp_dev_tty)) {
|
|
Packit |
a69f91 |
expErrorLog("system stty: impossible in this context\n");
|
|
Packit |
a69f91 |
expErrorLog("are you disconnected or in a batch, at, or cron script?");
|
|
Packit |
a69f91 |
/* user could've conceivably closed /dev/tty as well */
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
exp_error(interp,"system stty: ioctl(user): %s\r\n",Tcl_PosixError(interp));
|
|
Packit |
a69f91 |
return(TCL_ERROR);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
if (cmd_is_stty) {
|
|
Packit |
a69f91 |
char buf [11];
|
|
Packit |
a69f91 |
sprintf(buf,"%sraw %secho",
|
|
Packit |
a69f91 |
(was_raw?"":"-"),
|
|
Packit |
a69f91 |
(was_echo?"":"-"));
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, buf, TCL_VOLATILE);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
return(TCL_OK);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
for (i = 1;i
|
|
Packit |
a69f91 |
total_len += (1 + (arg_len = strlen(argv[i])));
|
|
Packit |
a69f91 |
if (total_len > MAX_ARGLIST) {
|
|
Packit |
a69f91 |
exp_error(interp,"args too long (>=%d chars)",
|
|
Packit |
a69f91 |
total_len);
|
|
Packit |
a69f91 |
return(TCL_ERROR);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
memcpy(bufp,argv[i],arg_len);
|
|
Packit |
a69f91 |
bufp += arg_len;
|
|
Packit |
a69f91 |
/* no need to check bounds, we accted for it earlier */
|
|
Packit |
a69f91 |
memcpy(bufp," ",1);
|
|
Packit |
a69f91 |
bufp += 1;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
*(bufp-1) = '\0';
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
old = signal(SIGCHLD, SIG_DFL);
|
|
Packit |
a69f91 |
systemStatus = system(buf);
|
|
Packit |
a69f91 |
signal(SIGCHLD, old); /* restore signal handler */
|
|
Packit |
a69f91 |
expDiagLogU("system(");
|
|
Packit |
a69f91 |
expDiagLogU(buf);
|
|
Packit |
a69f91 |
expDiagLog(") = %d\r\n",i);
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (systemStatus == -1) {
|
|
Packit |
a69f91 |
exp_error(interp,Tcl_PosixError(interp));
|
|
Packit |
a69f91 |
return TCL_ERROR;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
*(int *)&waitStatus = systemStatus;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!stty_args_recognized) {
|
|
Packit |
a69f91 |
/* find out what weird options user asked for */
|
|
Packit |
a69f91 |
if (
|
|
Packit |
a69f91 |
#ifdef HAVE_TCSETATTR
|
|
Packit |
a69f91 |
tcgetattr(exp_dev_tty, &tty_current) == -1
|
|
Packit |
a69f91 |
#else
|
|
Packit |
a69f91 |
ioctl(exp_dev_tty, TCGETS, &tty_current) == -1
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
) {
|
|
Packit |
a69f91 |
expErrorLog("ioctl(get): %s\r\n",Tcl_PosixError(interp));
|
|
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 |
if (cooked) {
|
|
Packit |
a69f91 |
/* find out user's new defn of 'cooked' */
|
|
Packit |
a69f91 |
tty_cooked = tty_current;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (cmd_is_stty) {
|
|
Packit |
a69f91 |
char buf [11];
|
|
Packit |
a69f91 |
sprintf(buf,"%sraw %secho",
|
|
Packit |
a69f91 |
(was_raw?"":"-"),
|
|
Packit |
a69f91 |
(was_echo?"":"-"));
|
|
Packit |
a69f91 |
Tcl_SetResult (interp, buf, TCL_VOLATILE);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* following macros stolen from Tcl's tclUnix.h file */
|
|
Packit |
a69f91 |
/* we can't include the whole thing because it depends on other macros */
|
|
Packit |
a69f91 |
/* that come out of Tcl's Makefile, sigh */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#if 0
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WIFEXITED
|
|
Packit |
a69f91 |
#ifndef WIFEXITED
|
|
Packit |
a69f91 |
# define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0)
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WEXITSTATUS
|
|
Packit |
a69f91 |
#ifndef WEXITSTATUS
|
|
Packit |
a69f91 |
# define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff)
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WIFSIGNALED
|
|
Packit |
a69f91 |
#ifndef WIFSIGNALED
|
|
Packit |
a69f91 |
# define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff)))
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WTERMSIG
|
|
Packit |
a69f91 |
#ifndef WTERMSIG
|
|
Packit |
a69f91 |
# define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f)
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WIFSTOPPED
|
|
Packit |
a69f91 |
#ifndef WIFSTOPPED
|
|
Packit |
a69f91 |
# define WIFSTOPPED(stat) (((*((int *) &(stat))) & 0xff) == 0177)
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#undef WSTOPSIG
|
|
Packit |
a69f91 |
#ifndef WSTOPSIG
|
|
Packit |
a69f91 |
# define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff)
|
|
Packit |
a69f91 |
#endif
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
#endif /* 0 */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
/* stolen from Tcl. Again, this is embedded in another routine */
|
|
Packit |
a69f91 |
/* (CleanupChildren in tclUnixAZ.c) that we can't use directly. */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (!WIFEXITED(waitStatus) || (WEXITSTATUS(waitStatus) != 0)) {
|
|
Packit |
a69f91 |
char msg1[20], msg2[20];
|
|
Packit |
a69f91 |
int pid = 0; /* fake a pid, since system() won't tell us */
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
result = TCL_ERROR;
|
|
Packit |
a69f91 |
sprintf(msg1, "%d", pid);
|
|
Packit |
a69f91 |
if (WIFEXITED(waitStatus)) {
|
|
Packit |
a69f91 |
sprintf(msg2, "%d", WEXITSTATUS(waitStatus));
|
|
Packit |
a69f91 |
Tcl_SetErrorCode(interp, "CHILDSTATUS", msg1, msg2,
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
abnormalExit = TRUE;
|
|
Packit |
a69f91 |
} else if (WIFSIGNALED(waitStatus)) {
|
|
Packit |
a69f91 |
CONST char *p;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
p = Tcl_SignalMsg((int) (WTERMSIG(waitStatus)));
|
|
Packit |
a69f91 |
Tcl_SetErrorCode(interp, "CHILDKILLED", msg1,
|
|
Packit |
a69f91 |
Tcl_SignalId((int) (WTERMSIG(waitStatus))), p,
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
Tcl_AppendResult(interp, "child killed: ", p, "\n",
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
} else if (WIFSTOPPED(waitStatus)) {
|
|
Packit |
a69f91 |
CONST char *p;
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
p = Tcl_SignalMsg((int) (WSTOPSIG(waitStatus)));
|
|
Packit |
a69f91 |
Tcl_SetErrorCode(interp, "CHILDSUSP", msg1,
|
|
Packit |
a69f91 |
Tcl_SignalId((int) (WSTOPSIG(waitStatus))), p, (char *) NULL);
|
|
Packit |
a69f91 |
Tcl_AppendResult(interp, "child suspended: ", p, "\n",
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
} else {
|
|
Packit |
a69f91 |
Tcl_AppendResult(interp,
|
|
Packit |
a69f91 |
"child wait status didn't make sense\n",
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
if (abnormalExit && (Tcl_GetStringResult (interp)[0] == 0)) {
|
|
Packit |
a69f91 |
Tcl_AppendResult(interp, "child process exited abnormally",
|
|
Packit |
a69f91 |
(char *) NULL);
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
return result;
|
|
Packit |
a69f91 |
}
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
static struct exp_cmd_data
|
|
Packit |
a69f91 |
cmd_data[] = {
|
|
Packit |
a69f91 |
{"stty", exp_proc(Exp_SttyCmd), 0, 0},
|
|
Packit |
a69f91 |
{"system", exp_proc(Exp_SystemCmd), 0, 0},
|
|
Packit |
a69f91 |
{0}};
|
|
Packit |
a69f91 |
|
|
Packit |
a69f91 |
void
|
|
Packit |
a69f91 |
exp_init_tty_cmds(struct 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 |
*/
|