ftp.nice.ch/pub/next/unix/communication/pcomm.NIHS.bs.tar.gz#/pcomm/Source/x_extrnl.c

This is x_extrnl.c in view mode; [Download] [Up]

/*
 * Spawn a shell with the stdin and stdout swapped with the remote
 * system, ie:
 *                               +----------+
 *    TTYin ------------> stdin  |          |
 *                               |  shell   |
 *    TTYout <---------- stdout  |          |
 *                               +----------+
 *
 * An undocumented feature:  The external protocol gateway
 * can be used to pipe the output of a normal Unix command to the
 * remote system.
 */

#include <stdio.h>
#include <signal.h>
#include <curses.h>
#include <errno.h>
#include "config.h"

#ifdef BSD
#ifndef SIGCLD
#define SIGCLD SIGCHLD
#endif /* SIGCLD */
#include <sys/file.h>
#else /* BSD */
#include <fcntl.h>
#endif /* BSD */

void
do_extrnl(cmd)
char *cmd;
{
	extern int fd, errno;
	WINDOW *xt_win, *newwin();
	SIG_TYPE (*istat)(), (*qstat)(), (*cstat)();
	int epid, want_out;
	unsigned int sleep();
	void _exit(), input_off();

	input_off();
					/* a full window */
	xt_win = newwin(LINES, COLS, 0, 0);
	nl();
	touchwin(xt_win);
	wrefresh(xt_win);

	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(fd);
					/* swap the stdout */
		close(1);
		dup(fd);
#ifdef SETUGID
		setgid(getgid());
		setuid(getuid());
#endif /* SETUGID */
		execl("/bin/sh", "sh", "-c", cmd, (char *) 0);
		_exit(1);
	}
	istat = signal(SIGINT, SIG_IGN);
	qstat = signal(SIGQUIT, SIG_IGN);
	cstat = signal(SIGCLD, SIG_IGN);

	/*
	 * Check the keyboard while the external program is running.  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);
					/* the tty may have been clobbered */
	sleep(1);
	fixterm();
	nonl();

	clearok(curscr, TRUE);
	werase(xt_win);
	wrefresh(xt_win);
	delwin(xt_win);
	return;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.