This is script.c in view mode; [Download] [Up]
/*
* Spawn a shell with file descriptors that look like this:
*
* +---------+
* TTYin ---> | input | ---> screen (& virtual screen)
* | program |
* +---------+
* | +---------+
* pipe ----------> stdin | |
* | shell |
* TTYout <---------------------- stdout | |
* +---------+
*
* The input program has a routine that duplicates the TTYin and sends it
* down a pipe. The other end of the pipe is the stdin to the shell script.
* This allows the characters to appear on the screen *and* be interpreted
* by the shell script.
*/
#include <stdio.h>
#include <signal.h>
#include <curses.h>
#include <errno.h>
#include "config.h"
#include "dial_dir.h"
#include "status.h"
#ifdef BSD
#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif /* SIGCLD */
#include <sys/file.h>
#else /* BSD */
#include <fcntl.h>
#endif /* BSD */
void
do_script(extra)
char *extra;
{
extern int fd, errno;
SIG_TYPE (*istat)(), (*qstat)(), (*cstat)();
int epid, dup_pipe[2], want_out;
char buf[80], *path, *findfile();
void _exit(), error_win(), input_off(), do_input();
/* if empty */
if (*dir->script[dir->d_cur] == '\0')
return;
/* find the script file */
if ((path = findfile(extra, dir->script[dir->d_cur])) == NULL) {
/*
* Fail quietly, if the script is actually a device.
*/
if (chk_script(dir->script[dir->d_cur]))
return;
sprintf(buf, "Can't locate script \"%s\"", dir->script[dir->d_cur]);
error_win(0, buf, "");
return;
}
/* execute permission ? */
if (access(path, 1)) {
sprintf(buf, "\"%s\"", path);
error_win(0, "No execute permission on script file", buf);
return;
}
/* create a fd for duplicating input */
if (pipe(dup_pipe) < 0)
return;
status->dup_fd = dup_pipe[1];
/* start input duplication */
do_input();
if (!(epid = fork())) {
/* create a new process group ID */
#ifdef BSD
setpgrp(0, getpid());
#else /* BSD */
setpgrp();
#endif /* BSD */
/* swap the stdin */
close(0);
dup(dup_pipe[0]);
/* swap the stdout */
close(1);
dup(fd);
#ifdef SETUGID
setgid(getgid());
setuid(getuid());
#endif /* SETUGID */
execl("/bin/sh", "sh", "-c", path, (char *) 0);
_exit(1);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
cstat = signal(SIGCLD, SIG_IGN);
/*
* Check the keyboard while the script is being "played". If the
* user hits the <ESC> key, then kill the entire process group
* associated with the new shell.
*/
want_out = 0;
while(1) {
switch(wait_key(stdscr, 1)) {
case -1: /* timed out */
break;
case 27: /* a user abort */
#ifdef BSD
killpg(epid, SIGKILL);
#else /* BSD */
kill(-epid, SIGKILL);
#endif /* BSD */
want_out++;
break;
default:
beep();
break;
}
if (want_out)
break;
/* see if the process it still active */
if ((kill(epid, 0) == -1) && errno == ESRCH)
break;
}
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
signal(SIGCLD, cstat);
/* shut down the duplication of input */
status->dup_fd = -1;
#ifndef SHAREDMEM
input_off();
#endif /* SHAREDMEM */
close(dup_pipe[0]);
close(dup_pipe[1]);
beep();
return;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.