|
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; }