1*47112Sbostic /*- 2*47112Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*47112Sbostic * All rights reserved. 4*47112Sbostic * 5*47112Sbostic * This code is derived from software contributed to Berkeley by 6*47112Sbostic * Kenneth Almquist. 7*47112Sbostic * 8*47112Sbostic * %sccs.include.redist.c% 9*47112Sbostic */ 10*47112Sbostic 11*47112Sbostic #ifndef lint 12*47112Sbostic static char sccsid[] = "@(#)eval.c 5.1 (Berkeley) 03/07/91"; 13*47112Sbostic #endif /* not lint */ 14*47112Sbostic 15*47112Sbostic /* 16*47112Sbostic * Evaluate a command. 17*47112Sbostic */ 18*47112Sbostic 19*47112Sbostic #include "shell.h" 20*47112Sbostic #include "nodes.h" 21*47112Sbostic #include "syntax.h" 22*47112Sbostic #include "expand.h" 23*47112Sbostic #include "parser.h" 24*47112Sbostic #include "jobs.h" 25*47112Sbostic #include "eval.h" 26*47112Sbostic #include "builtins.h" 27*47112Sbostic #include "options.h" 28*47112Sbostic #include "exec.h" 29*47112Sbostic #include "redir.h" 30*47112Sbostic #include "input.h" 31*47112Sbostic #include "output.h" 32*47112Sbostic #include "trap.h" 33*47112Sbostic #include "var.h" 34*47112Sbostic #include "memalloc.h" 35*47112Sbostic #include "error.h" 36*47112Sbostic #include "mystring.h" 37*47112Sbostic #include <signal.h> 38*47112Sbostic 39*47112Sbostic 40*47112Sbostic /* flags in argument to evaltree */ 41*47112Sbostic #define EV_EXIT 01 /* exit after evaluating tree */ 42*47112Sbostic #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 43*47112Sbostic #define EV_BACKCMD 04 /* command executing within back quotes */ 44*47112Sbostic 45*47112Sbostic 46*47112Sbostic /* reasons for skipping commands (see comment on breakcmd routine) */ 47*47112Sbostic #define SKIPBREAK 1 48*47112Sbostic #define SKIPCONT 2 49*47112Sbostic #define SKIPFUNC 3 50*47112Sbostic 51*47112Sbostic MKINIT int evalskip; /* set if we are skipping commands */ 52*47112Sbostic STATIC int skipcount; /* number of levels to skip */ 53*47112Sbostic MKINIT int loopnest; /* current loop nesting level */ 54*47112Sbostic int funcnest; /* depth of function calls */ 55*47112Sbostic 56*47112Sbostic 57*47112Sbostic char *commandname; 58*47112Sbostic struct strlist *cmdenviron; 59*47112Sbostic int exitstatus; /* exit status of last command */ 60*47112Sbostic 61*47112Sbostic 62*47112Sbostic #ifdef __STDC__ 63*47112Sbostic STATIC void evalloop(union node *); 64*47112Sbostic STATIC void evalfor(union node *); 65*47112Sbostic STATIC void evalcase(union node *, int); 66*47112Sbostic STATIC void evalsubshell(union node *, int); 67*47112Sbostic STATIC void expredir(union node *); 68*47112Sbostic STATIC void evalpipe(union node *); 69*47112Sbostic STATIC void evalcommand(union node *, int, struct backcmd *); 70*47112Sbostic STATIC void prehash(union node *); 71*47112Sbostic #else 72*47112Sbostic STATIC void evalloop(); 73*47112Sbostic STATIC void evalfor(); 74*47112Sbostic STATIC void evalcase(); 75*47112Sbostic STATIC void evalsubshell(); 76*47112Sbostic STATIC void expredir(); 77*47112Sbostic STATIC void evalpipe(); 78*47112Sbostic STATIC void evalcommand(); 79*47112Sbostic STATIC void prehash(); 80*47112Sbostic #endif 81*47112Sbostic 82*47112Sbostic 83*47112Sbostic 84*47112Sbostic /* 85*47112Sbostic * Called to reset things after an exception. 86*47112Sbostic */ 87*47112Sbostic 88*47112Sbostic #ifdef mkinit 89*47112Sbostic INCLUDE "eval.h" 90*47112Sbostic 91*47112Sbostic RESET { 92*47112Sbostic evalskip = 0; 93*47112Sbostic loopnest = 0; 94*47112Sbostic funcnest = 0; 95*47112Sbostic } 96*47112Sbostic 97*47112Sbostic SHELLPROC { 98*47112Sbostic exitstatus = 0; 99*47112Sbostic } 100*47112Sbostic #endif 101*47112Sbostic 102*47112Sbostic 103*47112Sbostic 104*47112Sbostic /* 105*47112Sbostic * The eval builtin. Do you want clean, straight-forward semantics for 106*47112Sbostic * your eval command? If so, read on.... 107*47112Sbostic */ 108*47112Sbostic 109*47112Sbostic #ifdef ELIGANT 110*47112Sbostic evalcmd(argc, argv) char **argv; { 111*47112Sbostic char **ap; 112*47112Sbostic 113*47112Sbostic for (ap = argv + 1 ; *ap ; ap++) { 114*47112Sbostic evalstring(*ap); 115*47112Sbostic } 116*47112Sbostic return exitstatus; 117*47112Sbostic } 118*47112Sbostic #else 119*47112Sbostic 120*47112Sbostic /* 121*47112Sbostic * If, on the other hand, you prefer downright bogus semantics in the 122*47112Sbostic * name of compatibility, here it is... 123*47112Sbostic */ 124*47112Sbostic 125*47112Sbostic evalcmd(argc, argv) char **argv; { 126*47112Sbostic char **ap; 127*47112Sbostic char *p, *q; 128*47112Sbostic 129*47112Sbostic if (argc <= 1) { 130*47112Sbostic p = nullstr; 131*47112Sbostic } else if (argc == 2) { 132*47112Sbostic p = argv[1]; 133*47112Sbostic } else { 134*47112Sbostic STARTSTACKSTR(p); 135*47112Sbostic ap = argv + 1; 136*47112Sbostic for (;;) { 137*47112Sbostic q = *ap++; 138*47112Sbostic while (*q) { 139*47112Sbostic STPUTC(*q++, p); 140*47112Sbostic } 141*47112Sbostic if (*ap == NULL) 142*47112Sbostic break; 143*47112Sbostic STPUTC(' ', p); 144*47112Sbostic } 145*47112Sbostic STPUTC('\0', p); 146*47112Sbostic p = grabstackstr(p); 147*47112Sbostic } 148*47112Sbostic evalstring(p); 149*47112Sbostic return exitstatus; 150*47112Sbostic } 151*47112Sbostic #endif 152*47112Sbostic 153*47112Sbostic 154*47112Sbostic 155*47112Sbostic /* 156*47112Sbostic * Execute a command or commands contained in a string. 157*47112Sbostic */ 158*47112Sbostic 159*47112Sbostic void 160*47112Sbostic evalstring(s) 161*47112Sbostic char *s; 162*47112Sbostic { 163*47112Sbostic union node *n; 164*47112Sbostic struct stackmark smark; 165*47112Sbostic 166*47112Sbostic setstackmark(&smark); 167*47112Sbostic setinputstring(s, 1); 168*47112Sbostic while ((n = parsecmd(0)) != NEOF) { 169*47112Sbostic evaltree(n, 0); 170*47112Sbostic popstackmark(&smark); 171*47112Sbostic } 172*47112Sbostic popfile(); 173*47112Sbostic popstackmark(&smark); 174*47112Sbostic } 175*47112Sbostic 176*47112Sbostic 177*47112Sbostic 178*47112Sbostic /* 179*47112Sbostic * Evaluate a parse tree. The value is left in the global variable 180*47112Sbostic * exitstatus. 181*47112Sbostic */ 182*47112Sbostic 183*47112Sbostic void 184*47112Sbostic evaltree(n, flags) 185*47112Sbostic union node *n; 186*47112Sbostic { 187*47112Sbostic if (n == NULL) { 188*47112Sbostic TRACE(("evaltree(NULL) called\n")); 189*47112Sbostic return; 190*47112Sbostic } 191*47112Sbostic TRACE(("evaltree(0x%x: %d) called\n", (int)n, n->type)); 192*47112Sbostic switch (n->type) { 193*47112Sbostic case NSEMI: 194*47112Sbostic evaltree(n->nbinary.ch1, 0); 195*47112Sbostic if (evalskip) 196*47112Sbostic goto out; 197*47112Sbostic evaltree(n->nbinary.ch2, flags); 198*47112Sbostic break; 199*47112Sbostic case NAND: 200*47112Sbostic evaltree(n->nbinary.ch1, EV_TESTED); 201*47112Sbostic if (evalskip || exitstatus != 0) 202*47112Sbostic goto out; 203*47112Sbostic evaltree(n->nbinary.ch2, flags); 204*47112Sbostic break; 205*47112Sbostic case NOR: 206*47112Sbostic evaltree(n->nbinary.ch1, EV_TESTED); 207*47112Sbostic if (evalskip || exitstatus == 0) 208*47112Sbostic goto out; 209*47112Sbostic evaltree(n->nbinary.ch2, flags); 210*47112Sbostic break; 211*47112Sbostic case NREDIR: 212*47112Sbostic expredir(n->nredir.redirect); 213*47112Sbostic redirect(n->nredir.redirect, REDIR_PUSH); 214*47112Sbostic evaltree(n->nredir.n, flags); 215*47112Sbostic popredir(); 216*47112Sbostic break; 217*47112Sbostic case NSUBSHELL: 218*47112Sbostic evalsubshell(n, flags); 219*47112Sbostic break; 220*47112Sbostic case NBACKGND: 221*47112Sbostic evalsubshell(n, flags); 222*47112Sbostic break; 223*47112Sbostic case NIF: 224*47112Sbostic evaltree(n->nif.test, EV_TESTED); 225*47112Sbostic if (evalskip) 226*47112Sbostic goto out; 227*47112Sbostic if (exitstatus == 0) { 228*47112Sbostic evaltree(n->nif.ifpart, flags); 229*47112Sbostic } else if (n->nif.elsepart) { 230*47112Sbostic evaltree(n->nif.elsepart, flags); 231*47112Sbostic } 232*47112Sbostic break; 233*47112Sbostic case NWHILE: 234*47112Sbostic case NUNTIL: 235*47112Sbostic evalloop(n); 236*47112Sbostic break; 237*47112Sbostic case NFOR: 238*47112Sbostic evalfor(n); 239*47112Sbostic break; 240*47112Sbostic case NCASE: 241*47112Sbostic evalcase(n, flags); 242*47112Sbostic break; 243*47112Sbostic case NDEFUN: 244*47112Sbostic defun(n->narg.text, n->narg.next); 245*47112Sbostic exitstatus = 0; 246*47112Sbostic break; 247*47112Sbostic case NPIPE: 248*47112Sbostic evalpipe(n); 249*47112Sbostic break; 250*47112Sbostic case NCMD: 251*47112Sbostic evalcommand(n, flags, (struct backcmd *)NULL); 252*47112Sbostic break; 253*47112Sbostic default: 254*47112Sbostic out1fmt("Node type = %d\n", n->type); 255*47112Sbostic flushout(&output); 256*47112Sbostic break; 257*47112Sbostic } 258*47112Sbostic out: 259*47112Sbostic if (pendingsigs) 260*47112Sbostic dotrap(); 261*47112Sbostic if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED))) 262*47112Sbostic exitshell(exitstatus); 263*47112Sbostic } 264*47112Sbostic 265*47112Sbostic 266*47112Sbostic STATIC void 267*47112Sbostic evalloop(n) 268*47112Sbostic union node *n; 269*47112Sbostic { 270*47112Sbostic int status; 271*47112Sbostic 272*47112Sbostic loopnest++; 273*47112Sbostic status = 0; 274*47112Sbostic for (;;) { 275*47112Sbostic evaltree(n->nbinary.ch1, EV_TESTED); 276*47112Sbostic if (evalskip) { 277*47112Sbostic skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 278*47112Sbostic evalskip = 0; 279*47112Sbostic continue; 280*47112Sbostic } 281*47112Sbostic if (evalskip == SKIPBREAK && --skipcount <= 0) 282*47112Sbostic evalskip = 0; 283*47112Sbostic break; 284*47112Sbostic } 285*47112Sbostic if (n->type == NWHILE) { 286*47112Sbostic if (exitstatus != 0) 287*47112Sbostic break; 288*47112Sbostic } else { 289*47112Sbostic if (exitstatus == 0) 290*47112Sbostic break; 291*47112Sbostic } 292*47112Sbostic evaltree(n->nbinary.ch2, 0); 293*47112Sbostic status = exitstatus; 294*47112Sbostic if (evalskip) 295*47112Sbostic goto skipping; 296*47112Sbostic } 297*47112Sbostic loopnest--; 298*47112Sbostic exitstatus = status; 299*47112Sbostic } 300*47112Sbostic 301*47112Sbostic 302*47112Sbostic 303*47112Sbostic STATIC void 304*47112Sbostic evalfor(n) 305*47112Sbostic union node *n; 306*47112Sbostic { 307*47112Sbostic struct arglist arglist; 308*47112Sbostic union node *argp; 309*47112Sbostic struct strlist *sp; 310*47112Sbostic struct stackmark smark; 311*47112Sbostic 312*47112Sbostic setstackmark(&smark); 313*47112Sbostic arglist.lastp = &arglist.list; 314*47112Sbostic for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { 315*47112Sbostic expandarg(argp, &arglist, 1); 316*47112Sbostic if (evalskip) 317*47112Sbostic goto out; 318*47112Sbostic } 319*47112Sbostic *arglist.lastp = NULL; 320*47112Sbostic 321*47112Sbostic exitstatus = 0; 322*47112Sbostic loopnest++; 323*47112Sbostic for (sp = arglist.list ; sp ; sp = sp->next) { 324*47112Sbostic setvar(n->nfor.var, sp->text, 0); 325*47112Sbostic evaltree(n->nfor.body, 0); 326*47112Sbostic if (evalskip) { 327*47112Sbostic if (evalskip == SKIPCONT && --skipcount <= 0) { 328*47112Sbostic evalskip = 0; 329*47112Sbostic continue; 330*47112Sbostic } 331*47112Sbostic if (evalskip == SKIPBREAK && --skipcount <= 0) 332*47112Sbostic evalskip = 0; 333*47112Sbostic break; 334*47112Sbostic } 335*47112Sbostic } 336*47112Sbostic loopnest--; 337*47112Sbostic out: 338*47112Sbostic popstackmark(&smark); 339*47112Sbostic } 340*47112Sbostic 341*47112Sbostic 342*47112Sbostic 343*47112Sbostic STATIC void 344*47112Sbostic evalcase(n, flags) 345*47112Sbostic union node *n; 346*47112Sbostic { 347*47112Sbostic union node *cp; 348*47112Sbostic union node *patp; 349*47112Sbostic struct arglist arglist; 350*47112Sbostic struct stackmark smark; 351*47112Sbostic 352*47112Sbostic setstackmark(&smark); 353*47112Sbostic arglist.lastp = &arglist.list; 354*47112Sbostic expandarg(n->ncase.expr, &arglist, 0); 355*47112Sbostic for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { 356*47112Sbostic for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { 357*47112Sbostic if (casematch(patp, arglist.list->text)) { 358*47112Sbostic if (evalskip == 0) { 359*47112Sbostic evaltree(cp->nclist.body, flags); 360*47112Sbostic } 361*47112Sbostic goto out; 362*47112Sbostic } 363*47112Sbostic } 364*47112Sbostic } 365*47112Sbostic out: 366*47112Sbostic popstackmark(&smark); 367*47112Sbostic } 368*47112Sbostic 369*47112Sbostic 370*47112Sbostic 371*47112Sbostic /* 372*47112Sbostic * Kick off a subshell to evaluate a tree. 373*47112Sbostic */ 374*47112Sbostic 375*47112Sbostic STATIC void 376*47112Sbostic evalsubshell(n, flags) 377*47112Sbostic union node *n; 378*47112Sbostic { 379*47112Sbostic struct job *jp; 380*47112Sbostic int backgnd = (n->type == NBACKGND); 381*47112Sbostic 382*47112Sbostic expredir(n->nredir.redirect); 383*47112Sbostic jp = makejob(n, 1); 384*47112Sbostic if (forkshell(jp, n, backgnd) == 0) { 385*47112Sbostic if (backgnd) 386*47112Sbostic flags &=~ EV_TESTED; 387*47112Sbostic redirect(n->nredir.redirect, 0); 388*47112Sbostic evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 389*47112Sbostic } 390*47112Sbostic if (! backgnd) { 391*47112Sbostic INTOFF; 392*47112Sbostic exitstatus = waitforjob(jp); 393*47112Sbostic INTON; 394*47112Sbostic } 395*47112Sbostic } 396*47112Sbostic 397*47112Sbostic 398*47112Sbostic 399*47112Sbostic /* 400*47112Sbostic * Compute the names of the files in a redirection list. 401*47112Sbostic */ 402*47112Sbostic 403*47112Sbostic STATIC void 404*47112Sbostic expredir(n) 405*47112Sbostic union node *n; 406*47112Sbostic { 407*47112Sbostic register union node *redir; 408*47112Sbostic 409*47112Sbostic for (redir = n ; redir ; redir = redir->nfile.next) { 410*47112Sbostic if (redir->type == NFROM 411*47112Sbostic || redir->type == NTO 412*47112Sbostic || redir->type == NAPPEND) { 413*47112Sbostic struct arglist fn; 414*47112Sbostic fn.lastp = &fn.list; 415*47112Sbostic expandarg(redir->nfile.fname, &fn, 0); 416*47112Sbostic redir->nfile.expfname = fn.list->text; 417*47112Sbostic } 418*47112Sbostic } 419*47112Sbostic } 420*47112Sbostic 421*47112Sbostic 422*47112Sbostic 423*47112Sbostic /* 424*47112Sbostic * Evaluate a pipeline. All the processes in the pipeline are children 425*47112Sbostic * of the process creating the pipeline. (This differs from some versions 426*47112Sbostic * of the shell, which make the last process in a pipeline the parent 427*47112Sbostic * of all the rest.) 428*47112Sbostic */ 429*47112Sbostic 430*47112Sbostic STATIC void 431*47112Sbostic evalpipe(n) 432*47112Sbostic union node *n; 433*47112Sbostic { 434*47112Sbostic struct job *jp; 435*47112Sbostic struct nodelist *lp; 436*47112Sbostic int pipelen; 437*47112Sbostic int prevfd; 438*47112Sbostic int pip[2]; 439*47112Sbostic 440*47112Sbostic TRACE(("evalpipe(0x%x) called\n", (int)n)); 441*47112Sbostic pipelen = 0; 442*47112Sbostic for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) 443*47112Sbostic pipelen++; 444*47112Sbostic INTOFF; 445*47112Sbostic jp = makejob(n, pipelen); 446*47112Sbostic prevfd = -1; 447*47112Sbostic for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 448*47112Sbostic prehash(lp->n); 449*47112Sbostic pip[1] = -1; 450*47112Sbostic if (lp->next) { 451*47112Sbostic if (pipe(pip) < 0) { 452*47112Sbostic close(prevfd); 453*47112Sbostic error("Pipe call failed"); 454*47112Sbostic } 455*47112Sbostic } 456*47112Sbostic if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { 457*47112Sbostic INTON; 458*47112Sbostic if (prevfd > 0) { 459*47112Sbostic close(0); 460*47112Sbostic copyfd(prevfd, 0); 461*47112Sbostic close(prevfd); 462*47112Sbostic } 463*47112Sbostic if (pip[1] >= 0) { 464*47112Sbostic close(pip[0]); 465*47112Sbostic if (pip[1] != 1) { 466*47112Sbostic close(1); 467*47112Sbostic copyfd(pip[1], 1); 468*47112Sbostic close(pip[1]); 469*47112Sbostic } 470*47112Sbostic } 471*47112Sbostic evaltree(lp->n, EV_EXIT); 472*47112Sbostic } 473*47112Sbostic if (prevfd >= 0) 474*47112Sbostic close(prevfd); 475*47112Sbostic prevfd = pip[0]; 476*47112Sbostic close(pip[1]); 477*47112Sbostic } 478*47112Sbostic INTON; 479*47112Sbostic if (n->npipe.backgnd == 0) { 480*47112Sbostic INTOFF; 481*47112Sbostic exitstatus = waitforjob(jp); 482*47112Sbostic TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 483*47112Sbostic INTON; 484*47112Sbostic } 485*47112Sbostic } 486*47112Sbostic 487*47112Sbostic 488*47112Sbostic 489*47112Sbostic /* 490*47112Sbostic * Execute a command inside back quotes. If it's a builtin command, we 491*47112Sbostic * want to save its output in a block obtained from malloc. Otherwise 492*47112Sbostic * we fork off a subprocess and get the output of the command via a pipe. 493*47112Sbostic * Should be called with interrupts off. 494*47112Sbostic */ 495*47112Sbostic 496*47112Sbostic void 497*47112Sbostic evalbackcmd(n, result) 498*47112Sbostic union node *n; 499*47112Sbostic struct backcmd *result; 500*47112Sbostic { 501*47112Sbostic int pip[2]; 502*47112Sbostic struct job *jp; 503*47112Sbostic struct stackmark smark; /* unnecessary */ 504*47112Sbostic 505*47112Sbostic setstackmark(&smark); 506*47112Sbostic result->fd = -1; 507*47112Sbostic result->buf = NULL; 508*47112Sbostic result->nleft = 0; 509*47112Sbostic result->jp = NULL; 510*47112Sbostic if (n->type == NCMD) { 511*47112Sbostic evalcommand(n, EV_BACKCMD, result); 512*47112Sbostic } else { 513*47112Sbostic if (pipe(pip) < 0) 514*47112Sbostic error("Pipe call failed"); 515*47112Sbostic jp = makejob(n, 1); 516*47112Sbostic if (forkshell(jp, n, FORK_NOJOB) == 0) { 517*47112Sbostic FORCEINTON; 518*47112Sbostic close(pip[0]); 519*47112Sbostic if (pip[1] != 1) { 520*47112Sbostic close(1); 521*47112Sbostic copyfd(pip[1], 1); 522*47112Sbostic close(pip[1]); 523*47112Sbostic } 524*47112Sbostic evaltree(n, EV_EXIT); 525*47112Sbostic } 526*47112Sbostic close(pip[1]); 527*47112Sbostic result->fd = pip[0]; 528*47112Sbostic result->jp = jp; 529*47112Sbostic } 530*47112Sbostic popstackmark(&smark); 531*47112Sbostic TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", 532*47112Sbostic result->fd, result->buf, result->nleft, result->jp)); 533*47112Sbostic } 534*47112Sbostic 535*47112Sbostic 536*47112Sbostic 537*47112Sbostic /* 538*47112Sbostic * Execute a simple command. 539*47112Sbostic */ 540*47112Sbostic 541*47112Sbostic STATIC void 542*47112Sbostic evalcommand(cmd, flags, backcmd) 543*47112Sbostic union node *cmd; 544*47112Sbostic struct backcmd *backcmd; 545*47112Sbostic { 546*47112Sbostic struct stackmark smark; 547*47112Sbostic union node *argp; 548*47112Sbostic struct arglist arglist; 549*47112Sbostic struct arglist varlist; 550*47112Sbostic char **argv; 551*47112Sbostic int argc; 552*47112Sbostic char **envp; 553*47112Sbostic int varflag; 554*47112Sbostic struct strlist *sp; 555*47112Sbostic register char *p; 556*47112Sbostic int mode; 557*47112Sbostic int pip[2]; 558*47112Sbostic struct cmdentry cmdentry; 559*47112Sbostic struct job *jp; 560*47112Sbostic struct jmploc jmploc; 561*47112Sbostic struct jmploc *volatile savehandler; 562*47112Sbostic char *volatile savecmdname; 563*47112Sbostic volatile struct shparam saveparam; 564*47112Sbostic struct localvar *volatile savelocalvars; 565*47112Sbostic volatile int e; 566*47112Sbostic char *lastarg; 567*47112Sbostic 568*47112Sbostic /* First expand the arguments. */ 569*47112Sbostic TRACE(("evalcommand(0x%x, %d) called\n", (int)cmd, flags)); 570*47112Sbostic setstackmark(&smark); 571*47112Sbostic arglist.lastp = &arglist.list; 572*47112Sbostic varlist.lastp = &varlist.list; 573*47112Sbostic varflag = 1; 574*47112Sbostic for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 575*47112Sbostic p = argp->narg.text; 576*47112Sbostic if (varflag && is_name(*p)) { 577*47112Sbostic do { 578*47112Sbostic p++; 579*47112Sbostic } while (is_in_name(*p)); 580*47112Sbostic if (*p == '=') { 581*47112Sbostic expandarg(argp, &varlist, 0); 582*47112Sbostic continue; 583*47112Sbostic } 584*47112Sbostic } 585*47112Sbostic expandarg(argp, &arglist, 1); 586*47112Sbostic varflag = 0; 587*47112Sbostic } 588*47112Sbostic *arglist.lastp = NULL; 589*47112Sbostic *varlist.lastp = NULL; 590*47112Sbostic expredir(cmd->ncmd.redirect); 591*47112Sbostic argc = 0; 592*47112Sbostic for (sp = arglist.list ; sp ; sp = sp->next) 593*47112Sbostic argc++; 594*47112Sbostic argv = stalloc(sizeof (char *) * (argc + 1)); 595*47112Sbostic for (sp = arglist.list ; sp ; sp = sp->next) 596*47112Sbostic *argv++ = sp->text; 597*47112Sbostic *argv = NULL; 598*47112Sbostic lastarg = NULL; 599*47112Sbostic if (iflag && funcnest == 0 && argc > 0) 600*47112Sbostic lastarg = argv[-1]; 601*47112Sbostic argv -= argc; 602*47112Sbostic 603*47112Sbostic /* Print the command if xflag is set. */ 604*47112Sbostic if (xflag) { 605*47112Sbostic outc('+', &errout); 606*47112Sbostic for (sp = varlist.list ; sp ; sp = sp->next) { 607*47112Sbostic outc(' ', &errout); 608*47112Sbostic out2str(sp->text); 609*47112Sbostic } 610*47112Sbostic for (sp = arglist.list ; sp ; sp = sp->next) { 611*47112Sbostic outc(' ', &errout); 612*47112Sbostic out2str(sp->text); 613*47112Sbostic } 614*47112Sbostic outc('\n', &errout); 615*47112Sbostic flushout(&errout); 616*47112Sbostic } 617*47112Sbostic 618*47112Sbostic /* Now locate the command. */ 619*47112Sbostic if (argc == 0) { 620*47112Sbostic cmdentry.cmdtype = CMDBUILTIN; 621*47112Sbostic cmdentry.u.index = BLTINCMD; 622*47112Sbostic } else { 623*47112Sbostic find_command(argv[0], &cmdentry, 1); 624*47112Sbostic if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ 625*47112Sbostic exitstatus = 2; 626*47112Sbostic flushout(&errout); 627*47112Sbostic return; 628*47112Sbostic } 629*47112Sbostic /* implement the bltin builtin here */ 630*47112Sbostic if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { 631*47112Sbostic for (;;) { 632*47112Sbostic argv++; 633*47112Sbostic if (--argc == 0) 634*47112Sbostic break; 635*47112Sbostic if ((cmdentry.u.index = find_builtin(*argv)) < 0) { 636*47112Sbostic outfmt(&errout, "%s: not found\n", *argv); 637*47112Sbostic exitstatus = 2; 638*47112Sbostic flushout(&errout); 639*47112Sbostic return; 640*47112Sbostic } 641*47112Sbostic if (cmdentry.u.index != BLTINCMD) 642*47112Sbostic break; 643*47112Sbostic } 644*47112Sbostic } 645*47112Sbostic } 646*47112Sbostic 647*47112Sbostic /* Fork off a child process if necessary. */ 648*47112Sbostic if (cmd->ncmd.backgnd 649*47112Sbostic || cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0 650*47112Sbostic || (flags & EV_BACKCMD) != 0 651*47112Sbostic && (cmdentry.cmdtype != CMDBUILTIN 652*47112Sbostic || cmdentry.u.index == DOTCMD 653*47112Sbostic || cmdentry.u.index == EVALCMD)) { 654*47112Sbostic jp = makejob(cmd, 1); 655*47112Sbostic mode = cmd->ncmd.backgnd; 656*47112Sbostic if (flags & EV_BACKCMD) { 657*47112Sbostic mode = FORK_NOJOB; 658*47112Sbostic if (pipe(pip) < 0) 659*47112Sbostic error("Pipe call failed"); 660*47112Sbostic } 661*47112Sbostic if (forkshell(jp, cmd, mode) != 0) 662*47112Sbostic goto parent; /* at end of routine */ 663*47112Sbostic if (flags & EV_BACKCMD) { 664*47112Sbostic FORCEINTON; 665*47112Sbostic close(pip[0]); 666*47112Sbostic if (pip[1] != 1) { 667*47112Sbostic close(1); 668*47112Sbostic copyfd(pip[1], 1); 669*47112Sbostic close(pip[1]); 670*47112Sbostic } 671*47112Sbostic } 672*47112Sbostic flags |= EV_EXIT; 673*47112Sbostic } 674*47112Sbostic 675*47112Sbostic /* This is the child process if a fork occurred. */ 676*47112Sbostic /* Execute the command. */ 677*47112Sbostic if (cmdentry.cmdtype == CMDFUNCTION) { 678*47112Sbostic trputs("Shell function: "); trargs(argv); 679*47112Sbostic redirect(cmd->ncmd.redirect, REDIR_PUSH); 680*47112Sbostic saveparam = shellparam; 681*47112Sbostic shellparam.malloc = 0; 682*47112Sbostic shellparam.nparam = argc - 1; 683*47112Sbostic shellparam.p = argv + 1; 684*47112Sbostic shellparam.optnext = NULL; 685*47112Sbostic INTOFF; 686*47112Sbostic savelocalvars = localvars; 687*47112Sbostic localvars = NULL; 688*47112Sbostic INTON; 689*47112Sbostic if (setjmp(jmploc.loc)) { 690*47112Sbostic if (exception == EXSHELLPROC) 691*47112Sbostic freeparam((struct shparam *)&saveparam); 692*47112Sbostic else { 693*47112Sbostic freeparam(&shellparam); 694*47112Sbostic shellparam = saveparam; 695*47112Sbostic } 696*47112Sbostic poplocalvars(); 697*47112Sbostic localvars = savelocalvars; 698*47112Sbostic handler = savehandler; 699*47112Sbostic longjmp(handler->loc, 1); 700*47112Sbostic } 701*47112Sbostic savehandler = handler; 702*47112Sbostic handler = &jmploc; 703*47112Sbostic for (sp = varlist.list ; sp ; sp = sp->next) 704*47112Sbostic mklocal(sp->text); 705*47112Sbostic funcnest++; 706*47112Sbostic evaltree(cmdentry.u.func, 0); 707*47112Sbostic funcnest--; 708*47112Sbostic INTOFF; 709*47112Sbostic poplocalvars(); 710*47112Sbostic localvars = savelocalvars; 711*47112Sbostic freeparam(&shellparam); 712*47112Sbostic shellparam = saveparam; 713*47112Sbostic handler = savehandler; 714*47112Sbostic popredir(); 715*47112Sbostic INTON; 716*47112Sbostic if (evalskip == SKIPFUNC) { 717*47112Sbostic evalskip = 0; 718*47112Sbostic skipcount = 0; 719*47112Sbostic } 720*47112Sbostic if (flags & EV_EXIT) 721*47112Sbostic exitshell(exitstatus); 722*47112Sbostic } else if (cmdentry.cmdtype == CMDBUILTIN) { 723*47112Sbostic trputs("builtin command: "); trargs(argv); 724*47112Sbostic mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; 725*47112Sbostic if (flags == EV_BACKCMD) { 726*47112Sbostic memout.nleft = 0; 727*47112Sbostic memout.nextc = memout.buf; 728*47112Sbostic memout.bufsize = 64; 729*47112Sbostic mode |= REDIR_BACKQ; 730*47112Sbostic } 731*47112Sbostic redirect(cmd->ncmd.redirect, mode); 732*47112Sbostic savecmdname = commandname; 733*47112Sbostic cmdenviron = varlist.list; 734*47112Sbostic e = -1; 735*47112Sbostic if (setjmp(jmploc.loc)) { 736*47112Sbostic e = exception; 737*47112Sbostic exitstatus = (e == EXINT)? SIGINT+128 : 2; 738*47112Sbostic goto cmddone; 739*47112Sbostic } 740*47112Sbostic savehandler = handler; 741*47112Sbostic handler = &jmploc; 742*47112Sbostic commandname = argv[0]; 743*47112Sbostic argptr = argv + 1; 744*47112Sbostic optptr = NULL; /* initialize nextopt */ 745*47112Sbostic exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); 746*47112Sbostic flushall(); 747*47112Sbostic cmddone: 748*47112Sbostic out1 = &output; 749*47112Sbostic out2 = &errout; 750*47112Sbostic freestdout(); 751*47112Sbostic if (e != EXSHELLPROC) { 752*47112Sbostic commandname = savecmdname; 753*47112Sbostic if (flags & EV_EXIT) { 754*47112Sbostic exitshell(exitstatus); 755*47112Sbostic } 756*47112Sbostic } 757*47112Sbostic handler = savehandler; 758*47112Sbostic if (e != -1) { 759*47112Sbostic if (e != EXERROR || cmdentry.u.index == BLTINCMD 760*47112Sbostic || cmdentry.u.index == DOTCMD 761*47112Sbostic || cmdentry.u.index == EVALCMD 762*47112Sbostic || cmdentry.u.index == EXECCMD) 763*47112Sbostic exraise(e); 764*47112Sbostic FORCEINTON; 765*47112Sbostic } 766*47112Sbostic if (cmdentry.u.index != EXECCMD) 767*47112Sbostic popredir(); 768*47112Sbostic if (flags == EV_BACKCMD) { 769*47112Sbostic backcmd->buf = memout.buf; 770*47112Sbostic backcmd->nleft = memout.nextc - memout.buf; 771*47112Sbostic memout.buf = NULL; 772*47112Sbostic } 773*47112Sbostic } else { 774*47112Sbostic trputs("normal command: "); trargs(argv); 775*47112Sbostic clearredir(); 776*47112Sbostic redirect(cmd->ncmd.redirect, 0); 777*47112Sbostic if (varlist.list) { 778*47112Sbostic p = stalloc(strlen(pathval()) + 1); 779*47112Sbostic scopy(pathval(), p); 780*47112Sbostic } else { 781*47112Sbostic p = pathval(); 782*47112Sbostic } 783*47112Sbostic for (sp = varlist.list ; sp ; sp = sp->next) 784*47112Sbostic setvareq(sp->text, VEXPORT|VSTACK); 785*47112Sbostic envp = environment(); 786*47112Sbostic shellexec(argv, envp, p, cmdentry.u.index); 787*47112Sbostic /*NOTREACHED*/ 788*47112Sbostic } 789*47112Sbostic goto out; 790*47112Sbostic 791*47112Sbostic parent: /* parent process gets here (if we forked) */ 792*47112Sbostic if (mode == 0) { /* argument to fork */ 793*47112Sbostic INTOFF; 794*47112Sbostic exitstatus = waitforjob(jp); 795*47112Sbostic INTON; 796*47112Sbostic } else if (mode == 2) { 797*47112Sbostic backcmd->fd = pip[0]; 798*47112Sbostic close(pip[1]); 799*47112Sbostic backcmd->jp = jp; 800*47112Sbostic } 801*47112Sbostic 802*47112Sbostic out: 803*47112Sbostic if (lastarg) 804*47112Sbostic setvar("_", lastarg, 0); 805*47112Sbostic popstackmark(&smark); 806*47112Sbostic } 807*47112Sbostic 808*47112Sbostic 809*47112Sbostic 810*47112Sbostic /* 811*47112Sbostic * Search for a command. This is called before we fork so that the 812*47112Sbostic * location of the command will be available in the parent as well as 813*47112Sbostic * the child. The check for "goodname" is an overly conservative 814*47112Sbostic * check that the name will not be subject to expansion. 815*47112Sbostic */ 816*47112Sbostic 817*47112Sbostic STATIC void 818*47112Sbostic prehash(n) 819*47112Sbostic union node *n; 820*47112Sbostic { 821*47112Sbostic struct cmdentry entry; 822*47112Sbostic 823*47112Sbostic if (n->type == NCMD && goodname(n->ncmd.args->narg.text)) 824*47112Sbostic find_command(n->ncmd.args->narg.text, &entry, 0); 825*47112Sbostic } 826*47112Sbostic 827*47112Sbostic 828*47112Sbostic 829*47112Sbostic /* 830*47112Sbostic * Builtin commands. Builtin commands whose functions are closely 831*47112Sbostic * tied to evaluation are implemented here. 832*47112Sbostic */ 833*47112Sbostic 834*47112Sbostic /* 835*47112Sbostic * No command given, or a bltin command with no arguments. Set the 836*47112Sbostic * specified variables. 837*47112Sbostic */ 838*47112Sbostic 839*47112Sbostic bltincmd(argc, argv) char **argv; { 840*47112Sbostic listsetvar(cmdenviron); 841*47112Sbostic return exitstatus; 842*47112Sbostic } 843*47112Sbostic 844*47112Sbostic 845*47112Sbostic /* 846*47112Sbostic * Handle break and continue commands. Break, continue, and return are 847*47112Sbostic * all handled by setting the evalskip flag. The evaluation routines 848*47112Sbostic * above all check this flag, and if it is set they start skipping 849*47112Sbostic * commands rather than executing them. The variable skipcount is 850*47112Sbostic * the number of loops to break/continue, or the number of function 851*47112Sbostic * levels to return. (The latter is always 1.) It should probably 852*47112Sbostic * be an error to break out of more loops than exist, but it isn't 853*47112Sbostic * in the standard shell so we don't make it one here. 854*47112Sbostic */ 855*47112Sbostic 856*47112Sbostic breakcmd(argc, argv) char **argv; { 857*47112Sbostic int n; 858*47112Sbostic 859*47112Sbostic n = 1; 860*47112Sbostic if (argc > 1) 861*47112Sbostic n = number(argv[1]); 862*47112Sbostic if (n > loopnest) 863*47112Sbostic n = loopnest; 864*47112Sbostic if (n > 0) { 865*47112Sbostic evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; 866*47112Sbostic skipcount = n; 867*47112Sbostic } 868*47112Sbostic return 0; 869*47112Sbostic } 870*47112Sbostic 871*47112Sbostic 872*47112Sbostic /* 873*47112Sbostic * The return command. 874*47112Sbostic */ 875*47112Sbostic 876*47112Sbostic returncmd(argc, argv) char **argv; { 877*47112Sbostic int ret; 878*47112Sbostic 879*47112Sbostic ret = exitstatus; 880*47112Sbostic if (argc > 1) 881*47112Sbostic ret = number(argv[1]); 882*47112Sbostic if (funcnest) { 883*47112Sbostic evalskip = SKIPFUNC; 884*47112Sbostic skipcount = 1; 885*47112Sbostic } 886*47112Sbostic return ret; 887*47112Sbostic } 888*47112Sbostic 889*47112Sbostic 890*47112Sbostic truecmd(argc, argv) char **argv; { 891*47112Sbostic return 0; 892*47112Sbostic } 893*47112Sbostic 894*47112Sbostic 895*47112Sbostic execcmd(argc, argv) char **argv; { 896*47112Sbostic if (argc > 1) { 897*47112Sbostic iflag = 0; /* exit on error */ 898*47112Sbostic setinteractive(0); 899*47112Sbostic #if JOBS 900*47112Sbostic jflag = 0; 901*47112Sbostic setjobctl(0); 902*47112Sbostic #endif 903*47112Sbostic shellexec(argv + 1, environment(), pathval(), 0); 904*47112Sbostic 905*47112Sbostic } 906*47112Sbostic return 0; 907*47112Sbostic } 908