172339Sabial#define Extern extern 272339Sabial#include <sys/types.h> 372339Sabial#include <signal.h> 472339Sabial#define _NSIG NSIG 572339Sabial#include <errno.h> 672339Sabial#include <setjmp.h> 772339Sabial#include <stddef.h> 872339Sabial#include <time.h> 972339Sabial#include <sys/times.h> 1072339Sabial#include <sys/stat.h> 1172339Sabial#include <sys/wait.h> 1272339Sabial#undef NULL 1372339Sabial#include "sh.h" 1472339Sabial 1572339Sabial/* -------- exec.c -------- */ 1672339Sabial/* #include "sh.h" */ 1772339Sabial 1872339Sabial/* 1972339Sabial * execute tree 2072339Sabial */ 2172339Sabial 2272339Sabialstatic char *signame[] = { 2372339Sabial "Signal 0", 2472339Sabial "Hangup", 2572339Sabial (char *)NULL, /* interrupt */ 2672339Sabial "Quit", 2772339Sabial "Illegal instruction", 2872339Sabial "Trace/BPT trap", 2972339Sabial "Abort", 3072339Sabial "EMT trap", 3172339Sabial "Floating exception", 3272339Sabial "Killed", 3372339Sabial "Bus error", 3472339Sabial "Memory fault", 3572339Sabial "Bad system call", 3672339Sabial (char *)NULL, /* broken pipe */ 3772339Sabial "Alarm clock", 3872339Sabial "Terminated", 3972339Sabial}; 4072339Sabial#define NSIGNAL (sizeof(signame)/sizeof(signame[0])) 4172339Sabial 4272339Sabial 4372339Sabial_PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked )); 4472339Sabial_PROTOTYPE(static int parent, (void)); 4572339Sabial_PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout )); 4672339Sabial_PROTOTYPE(static void echo, (char **wp )); 4772339Sabial_PROTOTYPE(static struct op **find1case, (struct op *t, char *w )); 4872339Sabial_PROTOTYPE(static struct op *findcase, (struct op *t, char *w )); 4972339Sabial_PROTOTYPE(static void brkset, (struct brkcon *bc )); 5072339Sabial_PROTOTYPE(int dolabel, (void)); 5172339Sabial_PROTOTYPE(int dochdir, (struct op *t )); 5272339Sabial_PROTOTYPE(int doshift, (struct op *t )); 5372339Sabial_PROTOTYPE(int dologin, (struct op *t )); 5472339Sabial_PROTOTYPE(int doumask, (struct op *t )); 5572339Sabial_PROTOTYPE(int doexec, (struct op *t )); 5672339Sabial_PROTOTYPE(int dodot, (struct op *t )); 5772339Sabial_PROTOTYPE(int dowait, (struct op *t )); 5872339Sabial_PROTOTYPE(int doread, (struct op *t )); 5972339Sabial_PROTOTYPE(int doeval, (struct op *t )); 6072339Sabial_PROTOTYPE(int dotrap, (struct op *t )); 6172339Sabial_PROTOTYPE(int getsig, (char *s )); 6272339Sabial_PROTOTYPE(void setsig, (int n, void (*f)())); 6372339Sabial_PROTOTYPE(int getn, (char *as )); 6472339Sabial_PROTOTYPE(int dobreak, (struct op *t )); 6572339Sabial_PROTOTYPE(int docontinue, (struct op *t )); 6672339Sabial_PROTOTYPE(static int brkcontin, (char *cp, int val )); 6772339Sabial_PROTOTYPE(int doexit, (struct op *t )); 6872339Sabial_PROTOTYPE(int doexport, (struct op *t )); 6972339Sabial_PROTOTYPE(int doreadonly, (struct op *t )); 7072339Sabial_PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key)); 7172339Sabial_PROTOTYPE(static void badid, (char *s )); 7272339Sabial_PROTOTYPE(int doset, (struct op *t )); 7372339Sabial_PROTOTYPE(void varput, (char *s, int out )); 7472339Sabial_PROTOTYPE(int dotimes, (void)); 7572339Sabial 7672339Sabialint 7772339Sabialexecute(t, pin, pout, act) 7872339Sabialregister struct op *t; 7972339Sabialint *pin, *pout; 8072339Sabialint act; 8172339Sabial{ 8272339Sabial register struct op *t1; 8372339Sabial int i, pv[2], rv, child, a; 8472339Sabial char *cp, **wp, **wp2; 8572339Sabial struct var *vp; 8672339Sabial struct brkcon bc; 8772339Sabial 8872339Sabial if (t == NULL) 8972339Sabial return(0); 9072339Sabial rv = 0; 9172339Sabial a = areanum++; 9272339Sabial wp = (wp2 = t->words) != NULL 9372339Sabial ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY) 9472339Sabial : NULL; 9572339Sabial 9672339Sabial switch(t->type) { 9772339Sabial case TPAREN: 9872339Sabial case TCOM: 9972339Sabial rv = forkexec(t, pin, pout, act, wp, &child); 10072339Sabial if (child) { 10172339Sabial exstat = rv; 10272339Sabial leave(); 10372339Sabial } 10472339Sabial break; 10572339Sabial 10672339Sabial case TPIPE: 10772339Sabial if ((rv = openpipe(pv)) < 0) 10872339Sabial break; 10972339Sabial pv[0] = remap(pv[0]); 11072339Sabial pv[1] = remap(pv[1]); 11172339Sabial (void) execute(t->left, pin, pv, 0); 11272339Sabial rv = execute(t->right, pv, pout, 0); 11372339Sabial break; 11472339Sabial 11572339Sabial case TLIST: 11672339Sabial (void) execute(t->left, pin, pout, 0); 11772339Sabial rv = execute(t->right, pin, pout, 0); 11872339Sabial break; 11972339Sabial 12072339Sabial case TASYNC: 12172339Sabial i = parent(); 12272339Sabial if (i != 0) { 12372339Sabial if (i != -1) { 12472339Sabial setval(lookup("!"), putn(i)); 12572339Sabial if (pin != NULL) 12672339Sabial closepipe(pin); 12772339Sabial if (talking) { 12872339Sabial prs(putn(i)); 12972339Sabial prs("\n"); 13072339Sabial } 13172339Sabial } else 13272339Sabial rv = -1; 13372339Sabial setstatus(rv); 13472339Sabial } else { 13572339Sabial signal(SIGINT, SIG_IGN); 13672339Sabial signal(SIGQUIT, SIG_IGN); 13772339Sabial if (talking) 13872339Sabial signal(SIGTERM, SIG_DFL); 13972339Sabial talking = 0; 14072339Sabial if (pin == NULL) { 14172339Sabial close(0); 14272339Sabial open("/dev/null", 0); 14372339Sabial } 14472339Sabial exit(execute(t->left, pin, pout, FEXEC)); 14572339Sabial } 14672339Sabial break; 14772339Sabial 14872339Sabial case TOR: 14972339Sabial case TAND: 15072339Sabial rv = execute(t->left, pin, pout, 0); 15172339Sabial if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND)) 15272339Sabial rv = execute(t1, pin, pout, 0); 15372339Sabial break; 15472339Sabial 15572339Sabial case TFOR: 15672339Sabial if (wp == NULL) { 15772339Sabial wp = dolv+1; 15872339Sabial if ((i = dolc) < 0) 15972339Sabial i = 0; 16072339Sabial } else { 16172339Sabial i = -1; 16272339Sabial while (*wp++ != NULL) 16372339Sabial ; 16472339Sabial } 16572339Sabial vp = lookup(t->str); 16672339Sabial while (setjmp(bc.brkpt)) 16772339Sabial if (isbreak) 16872339Sabial goto broken; 16972339Sabial brkset(&bc); 17072339Sabial for (t1 = t->left; i-- && *wp != NULL;) { 17172339Sabial setval(vp, *wp++); 17272339Sabial rv = execute(t1, pin, pout, 0); 17372339Sabial } 17472339Sabial brklist = brklist->nextlev; 17572339Sabial break; 17672339Sabial 17772339Sabial case TWHILE: 17872339Sabial case TUNTIL: 17972339Sabial while (setjmp(bc.brkpt)) 18072339Sabial if (isbreak) 18172339Sabial goto broken; 18272339Sabial brkset(&bc); 18372339Sabial t1 = t->left; 18472339Sabial while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE)) 18572339Sabial rv = execute(t->right, pin, pout, 0); 18672339Sabial brklist = brklist->nextlev; 18772339Sabial break; 18872339Sabial 18972339Sabial case TIF: 19072339Sabial case TELIF: 19172339Sabial if (t->right != NULL) { 19272339Sabial rv = !execute(t->left, pin, pout, 0) ? 19372339Sabial execute(t->right->left, pin, pout, 0): 19472339Sabial execute(t->right->right, pin, pout, 0); 19572339Sabial } 19672339Sabial break; 19772339Sabial 19872339Sabial case TCASE: 19972339Sabial if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0) 20072339Sabial cp = ""; 20172339Sabial if ((t1 = findcase(t->left, cp)) != NULL) 20272339Sabial rv = execute(t1, pin, pout, 0); 20372339Sabial break; 20472339Sabial 20572339Sabial case TBRACE: 20672339Sabial/* 20772339Sabial if (iopp = t->ioact) 20872339Sabial while (*iopp) 20972339Sabial if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) { 21072339Sabial rv = -1; 21172339Sabial break; 21272339Sabial } 21372339Sabial*/ 21472339Sabial if (rv >= 0 && (t1 = t->left)) 21572339Sabial rv = execute(t1, pin, pout, 0); 21672339Sabial break; 21772339Sabial } 21872339Sabial 21972339Sabialbroken: 22072339Sabial t->words = wp2; 22172339Sabial isbreak = 0; 22272339Sabial freehere(areanum); 22372339Sabial freearea(areanum); 22472339Sabial areanum = a; 22572339Sabial if (talking && intr) { 22672339Sabial closeall(); 22772339Sabial fail(); 22872339Sabial } 22972339Sabial if ((i = trapset) != 0) { 23072339Sabial trapset = 0; 23172339Sabial runtrap(i); 23272339Sabial } 23372339Sabial return(rv); 23472339Sabial} 23572339Sabial 23672339Sabialstatic int 23772339Sabialforkexec(t, pin, pout, act, wp, pforked) 23872339Sabialregister struct op *t; 23972339Sabialint *pin, *pout; 24072339Sabialint act; 24172339Sabialchar **wp; 24272339Sabialint *pforked; 24372339Sabial{ 24472339Sabial int i, rv, (*shcom)(); 24572339Sabial register int f; 24672339Sabial char *cp; 24772339Sabial struct ioword **iopp; 24872339Sabial int resetsig; 24972339Sabial char **owp; 25072339Sabial 25172339Sabial owp = wp; 25272339Sabial resetsig = 0; 25372339Sabial *pforked = 0; 25472339Sabial shcom = NULL; 25572339Sabial rv = -1; /* system-detected error */ 25672339Sabial if (t->type == TCOM) { 25772339Sabial while ((cp = *wp++) != NULL) 25872339Sabial ; 25972339Sabial cp = *wp; 26072339Sabial 26172339Sabial /* strip all initial assignments */ 26272339Sabial /* not correct wrt PATH=yyy command etc */ 26372339Sabial if (flag['x']) 26472339Sabial echo (cp ? wp: owp); 26572339Sabial if (cp == NULL && t->ioact == NULL) { 26672339Sabial while ((cp = *owp++) != NULL && assign(cp, COPYV)) 26772339Sabial ; 26872339Sabial return(setstatus(0)); 26972339Sabial } 27072339Sabial else if (cp != NULL) 27172339Sabial shcom = inbuilt(cp); 27272339Sabial } 27372339Sabial t->words = wp; 27472339Sabial f = act; 27572339Sabial if (shcom == NULL && (f & FEXEC) == 0) { 27672339Sabial i = parent(); 27772339Sabial if (i != 0) { 27872339Sabial if (i == -1) 27972339Sabial return(rv); 28072339Sabial if (pin != NULL) 28172339Sabial closepipe(pin); 28272339Sabial return(pout==NULL? setstatus(waitfor(i,0)): 0); 28372339Sabial } 28472339Sabial if (talking) { 28572339Sabial signal(SIGINT, SIG_IGN); 28672339Sabial signal(SIGQUIT, SIG_IGN); 28772339Sabial resetsig = 1; 28872339Sabial } 28972339Sabial talking = 0; 29072339Sabial intr = 0; 29172339Sabial (*pforked)++; 29272339Sabial brklist = 0; 29372339Sabial execflg = 0; 29472339Sabial } 29572339Sabial if (owp != NULL) 29672339Sabial while ((cp = *owp++) != NULL && assign(cp, COPYV)) 29772339Sabial if (shcom == NULL) 29872339Sabial export(lookup(cp)); 29972339Sabial#ifdef COMPIPE 30072339Sabial if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) { 30172339Sabial err("piping to/from shell builtins not yet done"); 30272339Sabial return(-1); 30372339Sabial } 30472339Sabial#endif 30572339Sabial if (pin != NULL) { 30672339Sabial dup2(pin[0], 0); 30772339Sabial closepipe(pin); 30872339Sabial } 30972339Sabial if (pout != NULL) { 31072339Sabial dup2(pout[1], 1); 31172339Sabial closepipe(pout); 31272339Sabial } 31372339Sabial if ((iopp = t->ioact) != NULL) { 31472339Sabial if (shcom != NULL && shcom != doexec) { 31572339Sabial prs(cp); 31672339Sabial err(": cannot redirect shell command"); 31772339Sabial return(-1); 31872339Sabial } 31972339Sabial while (*iopp) 32072339Sabial if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) 32172339Sabial return(rv); 32272339Sabial } 32372339Sabial if (shcom) 32472339Sabial return(setstatus((*shcom)(t))); 32572339Sabial /* should use FIOCEXCL */ 32672339Sabial for (i=FDBASE; i<NOFILE; i++) 32772339Sabial close(i); 32872339Sabial if (resetsig) { 32972339Sabial signal(SIGINT, SIG_DFL); 33072339Sabial signal(SIGQUIT, SIG_DFL); 33172339Sabial } 33272339Sabial if (t->type == TPAREN) 33372339Sabial exit(execute(t->left, NOPIPE, NOPIPE, FEXEC)); 33472339Sabial if (wp[0] == NULL) 33572339Sabial exit(0); 33672339Sabial cp = rexecve(wp[0], wp, makenv()); 33772339Sabial prs(wp[0]); prs(": "); warn(cp); 33872339Sabial if (!execflg) 33972339Sabial trap[0] = NULL; 34072339Sabial leave(); 34172339Sabial /* NOTREACHED */ 34272339Sabial} 34372339Sabial 34472339Sabial/* 34572339Sabial * common actions when creating a new child 34672339Sabial */ 34772339Sabialstatic int 34872339Sabialparent() 34972339Sabial{ 35072339Sabial register int i; 35172339Sabial 35272339Sabial i = fork(); 35372339Sabial if (i != 0) { 35472339Sabial if (i == -1) 35572339Sabial warn("try again"); 35672339Sabial } 35772339Sabial return(i); 35872339Sabial} 35972339Sabial 36072339Sabial/* 36172339Sabial * 0< 1> are ignored as required 36272339Sabial * within pipelines. 36372339Sabial */ 36472339Sabialint 36572339Sabialiosetup(iop, pipein, pipeout) 36672339Sabialregister struct ioword *iop; 36772339Sabialint pipein, pipeout; 36872339Sabial{ 36972339Sabial register u; 37072339Sabial char *cp, *msg; 37172339Sabial 37272339Sabial if (iop->io_unit == IODEFAULT) /* take default */ 37372339Sabial iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1; 37472339Sabial if (pipein && iop->io_unit == 0) 37572339Sabial return(0); 37672339Sabial if (pipeout && iop->io_unit == 1) 37772339Sabial return(0); 37872339Sabial msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create"; 37972339Sabial if ((iop->io_flag & IOHERE) == 0) { 38072339Sabial cp = iop->io_name; 38172339Sabial if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL) 38272339Sabial return(1); 38372339Sabial } 38472339Sabial if (iop->io_flag & IODUP) { 38572339Sabial if (cp[1] || (!digit(*cp) && *cp != '-')) { 38672339Sabial prs(cp); 38772339Sabial err(": illegal >& argument"); 38872339Sabial return(1); 38972339Sabial } 39072339Sabial if (*cp == '-') 39172339Sabial iop->io_flag = IOCLOSE; 39272339Sabial iop->io_flag &= ~(IOREAD|IOWRITE); 39372339Sabial } 39472339Sabial switch (iop->io_flag) { 39572339Sabial case IOREAD: 39672339Sabial u = open(cp, 0); 39772339Sabial break; 39872339Sabial 39972339Sabial case IOHERE: 40072339Sabial case IOHERE|IOXHERE: 40172339Sabial u = herein(iop->io_name, iop->io_flag&IOXHERE); 40272339Sabial cp = "here file"; 40372339Sabial break; 40472339Sabial 40572339Sabial case IOWRITE|IOCAT: 40672339Sabial if ((u = open(cp, 1)) >= 0) { 40772339Sabial lseek(u, (long)0, 2); 40872339Sabial break; 40972339Sabial } 41072339Sabial case IOWRITE: 41172339Sabial u = creat(cp, 0666); 41272339Sabial break; 41372339Sabial 41472339Sabial case IODUP: 41572339Sabial u = dup2(*cp-'0', iop->io_unit); 41672339Sabial break; 41772339Sabial 41872339Sabial case IOCLOSE: 41972339Sabial close(iop->io_unit); 42072339Sabial return(0); 42172339Sabial } 42272339Sabial if (u < 0) { 42372339Sabial prs(cp); 42472339Sabial prs(": cannot "); 42572339Sabial warn(msg); 42672339Sabial return(1); 42772339Sabial } else { 42872339Sabial if (u != iop->io_unit) { 42972339Sabial dup2(u, iop->io_unit); 43072339Sabial close(u); 43172339Sabial } 43272339Sabial } 43372339Sabial return(0); 43472339Sabial} 43572339Sabial 43672339Sabialstatic void 43772339Sabialecho(wp) 43872339Sabialregister char **wp; 43972339Sabial{ 44072339Sabial register i; 44172339Sabial 44272339Sabial prs("+"); 44372339Sabial for (i=0; wp[i]; i++) { 44472339Sabial if (i) 44572339Sabial prs(" "); 44672339Sabial prs(wp[i]); 44772339Sabial } 44872339Sabial prs("\n"); 44972339Sabial} 45072339Sabial 45172339Sabialstatic struct op ** 45272339Sabialfind1case(t, w) 45372339Sabialstruct op *t; 45472339Sabialchar *w; 45572339Sabial{ 45672339Sabial register struct op *t1; 45772339Sabial struct op **tp; 45872339Sabial register char **wp, *cp; 45972339Sabial 46072339Sabial if (t == NULL) 46172339Sabial return((struct op **)NULL); 46272339Sabial if (t->type == TLIST) { 46372339Sabial if ((tp = find1case(t->left, w)) != NULL) 46472339Sabial return(tp); 46572339Sabial t1 = t->right; /* TPAT */ 46672339Sabial } else 46772339Sabial t1 = t; 46872339Sabial for (wp = t1->words; *wp;) 46972339Sabial if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) 47072339Sabial return(&t1->left); 47172339Sabial return((struct op **)NULL); 47272339Sabial} 47372339Sabial 47472339Sabialstatic struct op * 47572339Sabialfindcase(t, w) 47672339Sabialstruct op *t; 47772339Sabialchar *w; 47872339Sabial{ 47972339Sabial register struct op **tp; 48072339Sabial 48172339Sabial return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL); 48272339Sabial} 48372339Sabial 48472339Sabial/* 48572339Sabial * Enter a new loop level (marked for break/continue). 48672339Sabial */ 48772339Sabialstatic void 48872339Sabialbrkset(bc) 48972339Sabialstruct brkcon *bc; 49072339Sabial{ 49172339Sabial bc->nextlev = brklist; 49272339Sabial brklist = bc; 49372339Sabial} 49472339Sabial 49572339Sabial/* 49672339Sabial * Wait for the last process created. 49772339Sabial * Print a message for each process found 49872339Sabial * that was killed by a signal. 49972339Sabial * Ignore interrupt signals while waiting 50072339Sabial * unless `canintr' is true. 50172339Sabial */ 50272339Sabialint 50372339Sabialwaitfor(lastpid, canintr) 50472339Sabialregister int lastpid; 50572339Sabialint canintr; 50672339Sabial{ 50772339Sabial register int pid, rv; 50872339Sabial int s; 50972339Sabial int oheedint = heedint; 51072339Sabial 51172339Sabial heedint = 0; 51272339Sabial rv = 0; 51372339Sabial do { 51472339Sabial pid = wait(&s); 51572339Sabial if (pid == -1) { 51672339Sabial if (errno != EINTR || canintr) 51772339Sabial break; 51872339Sabial } else { 51972339Sabial if ((rv = WAITSIG(s)) != 0) { 52072339Sabial if (rv < NSIGNAL) { 52172339Sabial if (signame[rv] != NULL) { 52272339Sabial if (pid != lastpid) { 52372339Sabial prn(pid); 52472339Sabial prs(": "); 52572339Sabial } 52672339Sabial prs(signame[rv]); 52772339Sabial } 52872339Sabial } else { 52972339Sabial if (pid != lastpid) { 53072339Sabial prn(pid); 53172339Sabial prs(": "); 53272339Sabial } 53372339Sabial prs("Signal "); prn(rv); prs(" "); 53472339Sabial } 53572339Sabial if (WAITCORE(s)) 53672339Sabial prs(" - core dumped"); 53772339Sabial if (rv >= NSIGNAL || signame[rv]) 53872339Sabial prs("\n"); 53972339Sabial rv = -1; 54072339Sabial } else 54172339Sabial rv = WAITVAL(s); 54272339Sabial } 54372339Sabial } while (pid != lastpid); 54472339Sabial heedint = oheedint; 54572339Sabial if (intr) 54672339Sabial if (talking) { 54772339Sabial if (canintr) 54872339Sabial intr = 0; 54972339Sabial } else { 55072339Sabial if (exstat == 0) exstat = rv; 55172339Sabial onintr(0); 55272339Sabial } 55372339Sabial return(rv); 55472339Sabial} 55572339Sabial 55672339Sabialint 55772339Sabialsetstatus(s) 55872339Sabialregister int s; 55972339Sabial{ 56072339Sabial exstat = s; 56172339Sabial setval(lookup("?"), putn(s)); 56272339Sabial return(s); 56372339Sabial} 56472339Sabial 56572339Sabial/* 56672339Sabial * PATH-searching interface to execve. 56772339Sabial * If getenv("PATH") were kept up-to-date, 56872339Sabial * execvp might be used. 56972339Sabial */ 57072339Sabialchar * 57172339Sabialrexecve(c, v, envp) 57272339Sabialchar *c, **v, **envp; 57372339Sabial{ 57472339Sabial register int i; 57572339Sabial register char *sp, *tp; 57672339Sabial int eacces = 0, asis = 0; 57772339Sabial 57872339Sabial sp = any('/', c)? "": path->value; 57972339Sabial asis = *sp == '\0'; 58072339Sabial while (asis || *sp != '\0') { 58172339Sabial asis = 0; 58272339Sabial tp = e.linep; 58372339Sabial for (; *sp != '\0'; tp++) 58472339Sabial if ((*tp = *sp++) == ':') { 58572339Sabial asis = *sp == '\0'; 58672339Sabial break; 58772339Sabial } 58872339Sabial if (tp != e.linep) 58972339Sabial *tp++ = '/'; 59072339Sabial for (i = 0; (*tp++ = c[i++]) != '\0';) 59172339Sabial ; 59272339Sabial execve(e.linep, v, envp); 59372339Sabial switch (errno) { 59472339Sabial case ENOEXEC: 59572339Sabial *v = e.linep; 59672339Sabial tp = *--v; 59772339Sabial *v = e.linep; 59872339Sabial execve("/bin/sh", v, envp); 59972339Sabial *v = tp; 60072339Sabial return("no Shell"); 60172339Sabial 60272339Sabial case ENOMEM: 60372339Sabial return("program too big"); 60472339Sabial 60572339Sabial case E2BIG: 60672339Sabial return("argument list too long"); 60772339Sabial 60872339Sabial case EACCES: 60972339Sabial eacces++; 61072339Sabial break; 61172339Sabial } 61272339Sabial } 61372339Sabial return(errno==ENOENT ? "not found" : "cannot execute"); 61472339Sabial} 61572339Sabial 61672339Sabial/* 61772339Sabial * Run the command produced by generator `f' 61872339Sabial * applied to stream `arg'. 61972339Sabial */ 62072339Sabialint 62172339Sabialrun(argp, f) 62272339Sabialstruct ioarg *argp; 62372339Sabialint (*f)(); 62472339Sabial{ 62572339Sabial struct op *otree; 62672339Sabial struct wdblock *swdlist; 62772339Sabial struct wdblock *siolist; 62872339Sabial jmp_buf ev, rt; 62972339Sabial xint *ofail; 63072339Sabial int rv; 63172339Sabial 63272339Sabial areanum++; 63372339Sabial swdlist = wdlist; 63472339Sabial siolist = iolist; 63572339Sabial otree = outtree; 63672339Sabial ofail = failpt; 63772339Sabial rv = -1; 63872339Sabial if (newenv(setjmp(errpt = ev)) == 0) { 63972339Sabial wdlist = 0; 64072339Sabial iolist = 0; 64172339Sabial pushio(argp, f); 64272339Sabial e.iobase = e.iop; 64372339Sabial yynerrs = 0; 64472339Sabial if (setjmp(failpt = rt) == 0 && yyparse() == 0) 64572339Sabial rv = execute(outtree, NOPIPE, NOPIPE, 0); 64672339Sabial quitenv(); 64772339Sabial } 64872339Sabial wdlist = swdlist; 64972339Sabial iolist = siolist; 65072339Sabial failpt = ofail; 65172339Sabial outtree = otree; 65272339Sabial freearea(areanum--); 65372339Sabial return(rv); 65472339Sabial} 65572339Sabial 65672339Sabial/* -------- do.c -------- */ 65772339Sabial/* #include "sh.h" */ 65872339Sabial 65972339Sabial/* 66072339Sabial * built-in commands: doX 66172339Sabial */ 66272339Sabial 66372339Sabialint 66472339Sabialdolabel() 66572339Sabial{ 66672339Sabial return(0); 66772339Sabial} 66872339Sabial 66972339Sabialint 67072339Sabialdochdir(t) 67172339Sabialregister struct op *t; 67272339Sabial{ 67372339Sabial register char *cp, *er; 67472339Sabial 67572339Sabial if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL) 67672339Sabial er = ": no home directory"; 67772339Sabial else if(chdir(cp) < 0) 67872339Sabial er = ": bad directory"; 67972339Sabial else 68072339Sabial return(0); 68172339Sabial prs(cp != NULL? cp: "cd"); 68272339Sabial err(er); 68372339Sabial return(1); 68472339Sabial} 68572339Sabial 68672339Sabialint 68772339Sabialdoshift(t) 68872339Sabialregister struct op *t; 68972339Sabial{ 69072339Sabial register n; 69172339Sabial 69272339Sabial n = t->words[1]? getn(t->words[1]): 1; 69372339Sabial if(dolc < n) { 69472339Sabial err("nothing to shift"); 69572339Sabial return(1); 69672339Sabial } 69772339Sabial dolv[n] = dolv[0]; 69872339Sabial dolv += n; 69972339Sabial dolc -= n; 70072339Sabial setval(lookup("#"), putn(dolc)); 70172339Sabial return(0); 70272339Sabial} 70372339Sabial 70472339Sabial/* 70572339Sabial * execute login and newgrp directly 70672339Sabial */ 70772339Sabialint 70872339Sabialdologin(t) 70972339Sabialstruct op *t; 71072339Sabial{ 71172339Sabial register char *cp; 71272339Sabial 71372339Sabial if (talking) { 71472339Sabial signal(SIGINT, SIG_DFL); 71572339Sabial signal(SIGQUIT, SIG_DFL); 71672339Sabial } 71772339Sabial cp = rexecve(t->words[0], t->words, makenv()); 71872339Sabial prs(t->words[0]); prs(": "); err(cp); 71972339Sabial return(1); 72072339Sabial} 72172339Sabial 72272339Sabialint 72372339Sabialdoumask(t) 72472339Sabialregister struct op *t; 72572339Sabial{ 72672339Sabial register int i, n; 72772339Sabial register char *cp; 72872339Sabial 72972339Sabial if ((cp = t->words[1]) == NULL) { 73072339Sabial i = umask(0); 73172339Sabial umask(i); 73272339Sabial for (n=3*4; (n-=3) >= 0;) 73372339Sabial putc('0'+((i>>n)&07)); 73472339Sabial putc('\n'); 73572339Sabial } else { 73672339Sabial for (n=0; *cp>='0' && *cp<='9'; cp++) 73772339Sabial n = n*8 + (*cp-'0'); 73872339Sabial umask(n); 73972339Sabial } 74072339Sabial return(0); 74172339Sabial} 74272339Sabial 74372339Sabialint 74472339Sabialdoexec(t) 74572339Sabialregister struct op *t; 74672339Sabial{ 74772339Sabial register i; 74872339Sabial jmp_buf ex; 74972339Sabial xint *ofail; 75072339Sabial 75172339Sabial t->ioact = NULL; 75272339Sabial for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++) 75372339Sabial ; 75472339Sabial if (i == 0) 75572339Sabial return(1); 75672339Sabial execflg = 1; 75772339Sabial ofail = failpt; 75872339Sabial if (setjmp(failpt = ex) == 0) 75972339Sabial execute(t, NOPIPE, NOPIPE, FEXEC); 76072339Sabial failpt = ofail; 76172339Sabial execflg = 0; 76272339Sabial return(1); 76372339Sabial} 76472339Sabial 76572339Sabialint 76672339Sabialdodot(t) 76772339Sabialstruct op *t; 76872339Sabial{ 76972339Sabial register i; 77072339Sabial register char *sp, *tp; 77172339Sabial char *cp; 77272339Sabial 77372339Sabial if ((cp = t->words[1]) == NULL) 77472339Sabial return(0); 77572339Sabial sp = any('/', cp)? ":": path->value; 77672339Sabial while (*sp) { 77772339Sabial tp = e.linep; 77872339Sabial while (*sp && (*tp = *sp++) != ':') 77972339Sabial tp++; 78072339Sabial if (tp != e.linep) 78172339Sabial *tp++ = '/'; 78272339Sabial for (i = 0; (*tp++ = cp[i++]) != '\0';) 78372339Sabial ; 78472339Sabial if ((i = open(e.linep, 0)) >= 0) { 78572339Sabial exstat = 0; 78672339Sabial next(remap(i)); 78772339Sabial return(exstat); 78872339Sabial } 78972339Sabial } 79072339Sabial prs(cp); 79172339Sabial err(": not found"); 79272339Sabial return(-1); 79372339Sabial} 79472339Sabial 79572339Sabialint 79672339Sabialdowait(t) 79772339Sabialstruct op *t; 79872339Sabial{ 79972339Sabial register i; 80072339Sabial register char *cp; 80172339Sabial 80272339Sabial if ((cp = t->words[1]) != NULL) { 80372339Sabial i = getn(cp); 80472339Sabial if (i == 0) 80572339Sabial return(0); 80672339Sabial } else 80772339Sabial i = -1; 80872339Sabial setstatus(waitfor(i, 1)); 80972339Sabial return(0); 81072339Sabial} 81172339Sabial 81272339Sabialint 81372339Sabialdoread(t) 81472339Sabialstruct op *t; 81572339Sabial{ 81672339Sabial register char *cp, **wp; 81772339Sabial register nb; 81872339Sabial register int nl = 0; 81972339Sabial 82072339Sabial if (t->words[1] == NULL) { 82195258Sdes err("usage: read name ..."); 82272339Sabial return(1); 82372339Sabial } 82472339Sabial for (wp = t->words+1; *wp; wp++) { 82572339Sabial for (cp = e.linep; !nl && cp < elinep-1; cp++) 82672339Sabial if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) || 82772339Sabial (nl = (*cp == '\n')) || 82872339Sabial (wp[1] && any(*cp, ifs->value))) 82972339Sabial break; 83072339Sabial *cp = 0; 83172339Sabial if (nb <= 0) 83272339Sabial break; 83372339Sabial setval(lookup(*wp), e.linep); 83472339Sabial } 83572339Sabial return(nb <= 0); 83672339Sabial} 83772339Sabial 83872339Sabialint 83972339Sabialdoeval(t) 84072339Sabialregister struct op *t; 84172339Sabial{ 84272339Sabial return(RUN(awordlist, t->words+1, wdchar)); 84372339Sabial} 84472339Sabial 84572339Sabialint 84672339Sabialdotrap(t) 84772339Sabialregister struct op *t; 84872339Sabial{ 84972339Sabial register int n, i; 85072339Sabial register int resetsig; 85172339Sabial 85272339Sabial if (t->words[1] == NULL) { 85372339Sabial for (i=0; i<=_NSIG; i++) 85472339Sabial if (trap[i]) { 85572339Sabial prn(i); 85672339Sabial prs(": "); 85772339Sabial prs(trap[i]); 85872339Sabial prs("\n"); 85972339Sabial } 86072339Sabial return(0); 86172339Sabial } 86272339Sabial resetsig = digit(*t->words[1]); 86372339Sabial for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) { 86472339Sabial n = getsig(t->words[i]); 86572339Sabial xfree(trap[n]); 86672339Sabial trap[n] = 0; 86772339Sabial if (!resetsig) { 86872339Sabial if (*t->words[1] != '\0') { 86972339Sabial trap[n] = strsave(t->words[1], 0); 87072339Sabial setsig(n, sig); 87172339Sabial } else 87272339Sabial setsig(n, SIG_IGN); 87372339Sabial } else { 87472339Sabial if (talking) 87572339Sabial if (n == SIGINT) 87672339Sabial setsig(n, onintr); 87772339Sabial else 87872339Sabial setsig(n, n == SIGQUIT ? SIG_IGN 87972339Sabial : SIG_DFL); 88072339Sabial else 88172339Sabial setsig(n, SIG_DFL); 88272339Sabial } 88372339Sabial } 88472339Sabial return(0); 88572339Sabial} 88672339Sabial 88772339Sabialint 88872339Sabialgetsig(s) 88972339Sabialchar *s; 89072339Sabial{ 89172339Sabial register int n; 89272339Sabial 89372339Sabial if ((n = getn(s)) < 0 || n > _NSIG) { 89472339Sabial err("trap: bad signal number"); 89572339Sabial n = 0; 89672339Sabial } 89772339Sabial return(n); 89872339Sabial} 89972339Sabial 90072339Sabialvoid 90172339Sabialsetsig(n, f) 90272339Sabialregister n; 90372339Sabial_PROTOTYPE(void (*f), (int)); 90472339Sabial{ 90572339Sabial if (n == 0) 90672339Sabial return; 90772339Sabial if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) { 90872339Sabial ourtrap[n] = 1; 90972339Sabial signal(n, f); 91072339Sabial } 91172339Sabial} 91272339Sabial 91372339Sabialint 91472339Sabialgetn(as) 91572339Sabialchar *as; 91672339Sabial{ 91772339Sabial register char *s; 91872339Sabial register n, m; 91972339Sabial 92072339Sabial s = as; 92172339Sabial m = 1; 92272339Sabial if (*s == '-') { 92372339Sabial m = -1; 92472339Sabial s++; 92572339Sabial } 92672339Sabial for (n = 0; digit(*s); s++) 92772339Sabial n = (n*10) + (*s-'0'); 92872339Sabial if (*s) { 92972339Sabial prs(as); 93072339Sabial err(": bad number"); 93172339Sabial } 93272339Sabial return(n*m); 93372339Sabial} 93472339Sabial 93572339Sabialint 93672339Sabialdobreak(t) 93772339Sabialstruct op *t; 93872339Sabial{ 93972339Sabial return(brkcontin(t->words[1], 1)); 94072339Sabial} 94172339Sabial 94272339Sabialint 94372339Sabialdocontinue(t) 94472339Sabialstruct op *t; 94572339Sabial{ 94672339Sabial return(brkcontin(t->words[1], 0)); 94772339Sabial} 94872339Sabial 94972339Sabialstatic int 95072339Sabialbrkcontin(cp, val) 95172339Sabialregister char *cp; 95272339Sabialint val; 95372339Sabial{ 95472339Sabial register struct brkcon *bc; 95572339Sabial register nl; 95672339Sabial 95772339Sabial nl = cp == NULL? 1: getn(cp); 95872339Sabial if (nl <= 0) 95972339Sabial nl = 999; 96072339Sabial do { 96172339Sabial if ((bc = brklist) == NULL) 96272339Sabial break; 96372339Sabial brklist = bc->nextlev; 96472339Sabial } while (--nl); 96572339Sabial if (nl) { 96672339Sabial err("bad break/continue level"); 96772339Sabial return(1); 96872339Sabial } 96972339Sabial isbreak = val; 97072339Sabial longjmp(bc->brkpt, 1); 97172339Sabial /* NOTREACHED */ 97272339Sabial} 97372339Sabial 97472339Sabialint 97572339Sabialdoexit(t) 97672339Sabialstruct op *t; 97772339Sabial{ 97872339Sabial register char *cp; 97972339Sabial 98072339Sabial execflg = 0; 98172339Sabial if ((cp = t->words[1]) != NULL) 98272339Sabial setstatus(getn(cp)); 98372339Sabial leave(); 98472339Sabial /* NOTREACHED */ 98572339Sabial} 98672339Sabial 98772339Sabialint 98872339Sabialdoexport(t) 98972339Sabialstruct op *t; 99072339Sabial{ 99172339Sabial rdexp(t->words+1, export, EXPORT); 99272339Sabial return(0); 99372339Sabial} 99472339Sabial 99572339Sabialint 99672339Sabialdoreadonly(t) 99772339Sabialstruct op *t; 99872339Sabial{ 99972339Sabial rdexp(t->words+1, ronly, RONLY); 100072339Sabial return(0); 100172339Sabial} 100272339Sabial 100372339Sabialstatic void 100472339Sabialrdexp(wp, f, key) 100572339Sabialregister char **wp; 100672339Sabialvoid (*f)(); 100772339Sabialint key; 100872339Sabial{ 100972339Sabial if (*wp != NULL) { 101072339Sabial for (; *wp != NULL; wp++) 101172339Sabial if (checkname(*wp)) 101272339Sabial (*f)(lookup(*wp)); 101372339Sabial else 101472339Sabial badid(*wp); 101572339Sabial } else 101672339Sabial putvlist(key, 1); 101772339Sabial} 101872339Sabial 101972339Sabialstatic void 102072339Sabialbadid(s) 102172339Sabialregister char *s; 102272339Sabial{ 102372339Sabial prs(s); 102472339Sabial err(": bad identifier"); 102572339Sabial} 102672339Sabial 102772339Sabialint 102872339Sabialdoset(t) 102972339Sabialregister struct op *t; 103072339Sabial{ 103172339Sabial register struct var *vp; 103272339Sabial register char *cp; 103372339Sabial register n; 103472339Sabial 103572339Sabial if ((cp = t->words[1]) == NULL) { 103672339Sabial for (vp = vlist; vp; vp = vp->next) 103772339Sabial varput(vp->name, 1); 103872339Sabial return(0); 103972339Sabial } 104072339Sabial if (*cp == '-') { 104172339Sabial /* bad: t->words++; */ 104272339Sabial for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++) 104372339Sabial ; 104472339Sabial if (*++cp == 0) 104572339Sabial flag['x'] = flag['v'] = 0; 104672339Sabial else 104772339Sabial for (; *cp; cp++) 104872339Sabial switch (*cp) { 104972339Sabial case 'e': 105072339Sabial if (!talking) 105172339Sabial flag['e']++; 105272339Sabial break; 105372339Sabial 105472339Sabial default: 105572339Sabial if (*cp>='a' && *cp<='z') 105672339Sabial flag[*cp]++; 105772339Sabial break; 105872339Sabial } 105972339Sabial setdash(); 106072339Sabial } 106172339Sabial if (t->words[1]) { 106272339Sabial t->words[0] = dolv[0]; 106372339Sabial for (n=1; t->words[n]; n++) 106472339Sabial setarea((char *)t->words[n], 0); 106572339Sabial dolc = n-1; 106672339Sabial dolv = t->words; 106772339Sabial setval(lookup("#"), putn(dolc)); 106872339Sabial setarea((char *)(dolv-1), 0); 106972339Sabial } 107072339Sabial return(0); 107172339Sabial} 107272339Sabial 107372339Sabialvoid 107472339Sabialvarput(s, out) 107572339Sabialregister char *s; 107672339Sabialint out; 107772339Sabial{ 107872339Sabial if (letnum(*s)) { 107972339Sabial write(out, s, strlen(s)); 108072339Sabial write(out, "\n", 1); 108172339Sabial } 108272339Sabial} 108372339Sabial 108472339Sabial 108572339Sabial#define SECS 60L 108672339Sabial#define MINS 3600L 108772339Sabial 108872339Sabialint 108972339Sabialdotimes() 109072339Sabial{ 109172339Sabial struct tms tbuf; 109272339Sabial 109372339Sabial times(&tbuf); 109472339Sabial 109572339Sabial prn((int)(tbuf.tms_cutime / MINS)); 109672339Sabial prs("m"); 109772339Sabial prn((int)((tbuf.tms_cutime % MINS) / SECS)); 109872339Sabial prs("s "); 109972339Sabial prn((int)(tbuf.tms_cstime / MINS)); 110072339Sabial prs("m"); 110172339Sabial prn((int)((tbuf.tms_cstime % MINS) / SECS)); 110272339Sabial prs("s\n"); 110372339Sabial return(0); 110472339Sabial} 110572339Sabial 110672339Sabialstruct builtin { 110772339Sabial char *command; 110872339Sabial int (*fn)(); 110972339Sabial}; 111072339Sabialstatic struct builtin builtin[] = { 111172339Sabial ":", dolabel, 111272339Sabial "cd", dochdir, 111372339Sabial "shift", doshift, 111472339Sabial "exec", doexec, 111572339Sabial "wait", dowait, 111672339Sabial "read", doread, 111772339Sabial "eval", doeval, 111872339Sabial "trap", dotrap, 111972339Sabial "break", dobreak, 112072339Sabial "continue", docontinue, 112172339Sabial "exit", doexit, 112272339Sabial "export", doexport, 112372339Sabial "readonly", doreadonly, 112472339Sabial "set", doset, 112572339Sabial ".", dodot, 112672339Sabial "umask", doumask, 112772339Sabial "login", dologin, 112872339Sabial "newgrp", dologin, 112972339Sabial "times", dotimes, 113072339Sabial 0, 113172339Sabial}; 113272339Sabial 113372339Sabialint (*inbuilt(s))() 113472339Sabialregister char *s; 113572339Sabial{ 113672339Sabial register struct builtin *bp; 113772339Sabial 113872339Sabial for (bp = builtin; bp->command != NULL; bp++) 113972339Sabial if (strcmp(bp->command, s) == 0) 114072339Sabial return(bp->fn); 114172339Sabial return((int(*)())NULL); 114272339Sabial} 114372339Sabial 1144