|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 3616 (0xe20)
Types: TextFile
Names: »shell.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec8/mcp/src/shell.c«
#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;
}