DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T s

⟦07dd22c1b⟧ TextFile

    Length: 3616 (0xe20)
    Types: TextFile
    Names: »shell.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/mcp/src/shell.c« 

TextFile

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <signal.h>
#include <strings.h>
#include "sysdep.h"
#include "macros.h"
#include "mem.h"

#ifdef BSD4_3
uid_t	getuid();
gid_t	getgid();
#endif

#define NILRUSAGE	(struct rusage *) 0

char	*getenv();

extern 	addr DEF_SHELL;
extern	int DevTty, kids;

int
shellescape(c, v)
int c;
addr *v;

{
	int kidpid, mypgrp, newpgrp, pid, omask, exitcode = 0;
	union wait status;

	mypgrp = getpgrp(0);

	c--; v++;
	/*
	 * Don't want to be interrupted while forking and leave zombies
	 * and things floating around.  WHo knows what happens when the
	 * parent is interrupted in the midst of a vfork() ?
	 */
	critical();
	kidpid = vfork();
	if (kidpid == -1) {
		perr("vfork failed!");
		return -1;
	}
	non_critical();

	if (kidpid) {
		/*
		 * Do nothing here, because we are the parent; we should go
		 * directly to the wait loop.
		 */
	}
	else if (c == 0) {
		char *shell = getenv("SHELL");
		char *sname;

		if (!shell)
			shell = (char *)DEF_SHELL;
		if (!kidpid) {
			sname = rindex(shell, '/');
			sname = (sname ? sname+1 : shell);
			pid = getpid();
			(void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
			(void) setpgrp(0, pid);
			(void) setuid(getuid());  /* better safe than... */
			(void) setgid(getgid());  /* ... */
			execl(shell, sname, 0);
			perr(shell);
			_exit(1);
		}
	}
	else {
		if (!kidpid) {
			pid = getpid();
			(void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
			(void) setpgrp(0, pid);
			(void) setuid(getuid());
			(void) setgid(getgid());
			execvp((char *)*v, (char **)v);
			perr((char *)*v);
			_exit(1);
		}
	}
	for (;;) {
		/*
		 *	KLUDGE ALERT! BATTLE STATIONS...
		 *
		 * Here we temporarily block possible SIGALRM's that
		 * might be generated when mcp wants to checkpoint itself.
		 * This is due to a bug in wait3() (4.2 BSD).  If the signal
		 * were processed while in wait3(), the wait3() would be
		 * restarted >>without<< the WUNTRACED option, which would
		 * cause a deadlock here if the child were to stop.
		 *
		 * SIGALRM will be released once the child
		 * has terminated.
		 */
		omask = sigblock(mask(SIGALRM));

		pid = wait3(&status, WUNTRACED, NILRUSAGE);
		if (pid == 0)
			continue;
		else if (pid > 0 && pid != kidpid) {
			/*
			 * Apparently this isn't the child we just spawned
			 * (could be an omnichown that terminated), so
			 * we note its passing.
			 */
			kids--;
			continue;
		}
		if (WIFSTOPPED(status)) {
			/*
			 * The child has stopped due to some signal,
			 * so mcp stops itself with the same signal
			 * to achieve transparency.
			 */
			(void) kill(getpid(), (int)status.w_stopsig);
			/*
			 * We've been continued, but the our parent
			 * (the shell) has given us back the tty, so
			 * we must pass it back to the child before
			 * continuing it.
			 */
			(void) setpgrp(kidpid, kidpid);
			(void) ioctl(DevTty, TIOCSPGRP, (char *)&kidpid);
			/*
			 * Now set the child in motion...
			 */
			(void) killpg(kidpid, SIGCONT);
			/*
			 * And keep waiting...
			 */
			continue;
		}
		break;
	}

	/*
	 * Note if anything went amiss.
	 */
	if (status.w_termsig != 0)
		exitcode = status.w_termsig;
	if (status.w_retcode != 0)
		exitcode = status.w_retcode;
	/*
	 * Child has exited, so now we can release any pending
	 * SIGALRM.
	 */
	(void) sigsetmask(omask);

	/*
	 * Take command of the tty again.
	 */
	(void) ioctl(DevTty, TIOCGPGRP, (char *)&newpgrp);
	(void) setpgrp(0, newpgrp);
	(void) ioctl(DevTty, TIOCSPGRP, (char *)&mypgrp);
	(void) setpgrp(0, mypgrp);

	return exitcode;
}