1 /*- 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; 36 #endif 37 #endif /* not lint */ 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include <paths.h> 42 #include <signal.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <sys/wait.h> /* For WIFSIGNALED(status) */ 46 #include <errno.h> 47 48 /* 49 * Evaluate a command. 50 */ 51 52 #include "shell.h" 53 #include "nodes.h" 54 #include "syntax.h" 55 #include "expand.h" 56 #include "parser.h" 57 #include "jobs.h" 58 #include "eval.h" 59 #include "builtins.h" 60 #include "options.h" 61 #include "exec.h" 62 #include "redir.h" 63 #include "input.h" 64 #include "output.h" 65 #include "trap.h" 66 #include "var.h" 67 #include "memalloc.h" 68 #include "error.h" 69 #include "show.h" 70 #include "mystring.h" 71 #ifndef NO_HISTORY 72 #include "myhistedit.h" 73 #endif 74 75 76 /* flags in argument to evaltree */ 77 #define EV_EXIT 01 /* exit after evaluating tree */ 78 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 79 #define EV_BACKCMD 04 /* command executing within back quotes */ 80 81 MKINIT int evalskip; /* set if we are skipping commands */ 82 STATIC int skipcount; /* number of levels to skip */ 83 MKINIT int loopnest; /* current loop nesting level */ 84 int funcnest; /* depth of function calls */ 85 86 87 char *commandname; 88 struct strlist *cmdenviron; 89 int exitstatus; /* exit status of last command */ 90 int oexitstatus; /* saved exit status */ 91 92 93 STATIC void evalloop(union node *, int); 94 STATIC void evalfor(union node *, int); 95 STATIC void evalcase(union node *, int); 96 STATIC void evalsubshell(union node *, int); 97 STATIC void expredir(union node *); 98 STATIC void evalpipe(union node *); 99 STATIC void evalcommand(union node *, int, struct backcmd *); 100 STATIC void prehash(union node *); 101 102 103 /* 104 * Called to reset things after an exception. 105 */ 106 107 #ifdef mkinit 108 INCLUDE "eval.h" 109 110 RESET { 111 evalskip = 0; 112 loopnest = 0; 113 funcnest = 0; 114 } 115 116 SHELLPROC { 117 exitstatus = 0; 118 } 119 #endif 120 121 122 123 /* 124 * The eval command. 125 */ 126 127 int 128 evalcmd(int argc, char **argv) 129 { 130 char *p; 131 char *concat; 132 char **ap; 133 134 if (argc > 1) { 135 p = argv[1]; 136 if (argc > 2) { 137 STARTSTACKSTR(concat); 138 ap = argv + 2; 139 for (;;) { 140 while (*p) 141 STPUTC(*p++, concat); 142 if ((p = *ap++) == NULL) 143 break; 144 STPUTC(' ', concat); 145 } 146 STPUTC('\0', concat); 147 p = grabstackstr(concat); 148 } 149 evalstring(p); 150 } 151 return exitstatus; 152 } 153 154 155 /* 156 * Execute a command or commands contained in a string. 157 */ 158 159 void 160 evalstring(char *s) 161 { 162 union node *n; 163 struct stackmark smark; 164 165 setstackmark(&smark); 166 setinputstring(s, 1); 167 while ((n = parsecmd(0)) != NEOF) { 168 evaltree(n, 0); 169 popstackmark(&smark); 170 } 171 popfile(); 172 popstackmark(&smark); 173 } 174 175 176 177 /* 178 * Evaluate a parse tree. The value is left in the global variable 179 * exitstatus. 180 */ 181 182 void 183 evaltree(union node *n, int flags) 184 { 185 int do_etest; 186 187 do_etest = 0; 188 if (n == NULL) { 189 TRACE(("evaltree(NULL) called\n")); 190 exitstatus = 0; 191 goto out; 192 } 193 #ifndef NO_HISTORY 194 displayhist = 1; /* show history substitutions done with fc */ 195 #endif 196 TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type)); 197 switch (n->type) { 198 case NSEMI: 199 evaltree(n->nbinary.ch1, flags & ~EV_EXIT); 200 if (evalskip) 201 goto out; 202 evaltree(n->nbinary.ch2, flags); 203 break; 204 case NAND: 205 evaltree(n->nbinary.ch1, EV_TESTED); 206 if (evalskip || exitstatus != 0) { 207 goto out; 208 } 209 evaltree(n->nbinary.ch2, flags); 210 break; 211 case NOR: 212 evaltree(n->nbinary.ch1, EV_TESTED); 213 if (evalskip || exitstatus == 0) 214 goto out; 215 evaltree(n->nbinary.ch2, flags); 216 break; 217 case NREDIR: 218 expredir(n->nredir.redirect); 219 redirect(n->nredir.redirect, REDIR_PUSH); 220 evaltree(n->nredir.n, flags); 221 popredir(); 222 break; 223 case NSUBSHELL: 224 evalsubshell(n, flags); 225 do_etest = !(flags & EV_TESTED); 226 break; 227 case NBACKGND: 228 evalsubshell(n, flags); 229 break; 230 case NIF: { 231 evaltree(n->nif.test, EV_TESTED); 232 if (evalskip) 233 goto out; 234 if (exitstatus == 0) 235 evaltree(n->nif.ifpart, flags); 236 else if (n->nif.elsepart) 237 evaltree(n->nif.elsepart, flags); 238 else 239 exitstatus = 0; 240 break; 241 } 242 case NWHILE: 243 case NUNTIL: 244 evalloop(n, flags & ~EV_EXIT); 245 break; 246 case NFOR: 247 evalfor(n, flags & ~EV_EXIT); 248 break; 249 case NCASE: 250 evalcase(n, flags); 251 break; 252 case NDEFUN: 253 defun(n->narg.text, n->narg.next); 254 exitstatus = 0; 255 break; 256 case NNOT: 257 evaltree(n->nnot.com, EV_TESTED); 258 exitstatus = !exitstatus; 259 break; 260 261 case NPIPE: 262 evalpipe(n); 263 do_etest = !(flags & EV_TESTED); 264 break; 265 case NCMD: 266 evalcommand(n, flags, (struct backcmd *)NULL); 267 do_etest = !(flags & EV_TESTED); 268 break; 269 default: 270 out1fmt("Node type = %d\n", n->type); 271 flushout(&output); 272 break; 273 } 274 out: 275 if (pendingsigs) 276 dotrap(); 277 if ((flags & EV_EXIT) || (eflag && exitstatus != 0 && do_etest)) 278 exitshell(exitstatus); 279 } 280 281 282 STATIC void 283 evalloop(union node *n, int flags) 284 { 285 int status; 286 287 loopnest++; 288 status = 0; 289 for (;;) { 290 evaltree(n->nbinary.ch1, EV_TESTED); 291 if (evalskip) { 292 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 293 evalskip = 0; 294 continue; 295 } 296 if (evalskip == SKIPBREAK && --skipcount <= 0) 297 evalskip = 0; 298 break; 299 } 300 if (n->type == NWHILE) { 301 if (exitstatus != 0) 302 break; 303 } else { 304 if (exitstatus == 0) 305 break; 306 } 307 evaltree(n->nbinary.ch2, flags); 308 status = exitstatus; 309 if (evalskip) 310 goto skipping; 311 } 312 loopnest--; 313 exitstatus = status; 314 } 315 316 317 318 STATIC void 319 evalfor(union node *n, int flags) 320 { 321 struct arglist arglist; 322 union node *argp; 323 struct strlist *sp; 324 struct stackmark smark; 325 326 setstackmark(&smark); 327 arglist.lastp = &arglist.list; 328 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { 329 oexitstatus = exitstatus; 330 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 331 if (evalskip) 332 goto out; 333 } 334 *arglist.lastp = NULL; 335 336 exitstatus = 0; 337 loopnest++; 338 for (sp = arglist.list ; sp ; sp = sp->next) { 339 setvar(n->nfor.var, sp->text, 0); 340 evaltree(n->nfor.body, flags); 341 if (evalskip) { 342 if (evalskip == SKIPCONT && --skipcount <= 0) { 343 evalskip = 0; 344 continue; 345 } 346 if (evalskip == SKIPBREAK && --skipcount <= 0) 347 evalskip = 0; 348 break; 349 } 350 } 351 loopnest--; 352 out: 353 popstackmark(&smark); 354 } 355 356 357 358 STATIC void 359 evalcase(union node *n, int flags) 360 { 361 union node *cp; 362 union node *patp; 363 struct arglist arglist; 364 struct stackmark smark; 365 366 setstackmark(&smark); 367 arglist.lastp = &arglist.list; 368 oexitstatus = exitstatus; 369 expandarg(n->ncase.expr, &arglist, EXP_TILDE); 370 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { 371 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { 372 if (casematch(patp, arglist.list->text)) { 373 if (evalskip == 0) { 374 evaltree(cp->nclist.body, flags); 375 } 376 goto out; 377 } 378 } 379 } 380 out: 381 popstackmark(&smark); 382 } 383 384 385 386 /* 387 * Kick off a subshell to evaluate a tree. 388 */ 389 390 STATIC void 391 evalsubshell(union node *n, int flags) 392 { 393 struct job *jp; 394 int backgnd = (n->type == NBACKGND); 395 396 expredir(n->nredir.redirect); 397 jp = makejob(n, 1); 398 if (forkshell(jp, n, backgnd) == 0) { 399 if (backgnd) 400 flags &=~ EV_TESTED; 401 redirect(n->nredir.redirect, 0); 402 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 403 } 404 if (! backgnd) { 405 INTOFF; 406 exitstatus = waitforjob(jp, (int *)NULL); 407 INTON; 408 } 409 } 410 411 412 413 /* 414 * Compute the names of the files in a redirection list. 415 */ 416 417 STATIC void 418 expredir(union node *n) 419 { 420 union node *redir; 421 422 for (redir = n ; redir ; redir = redir->nfile.next) { 423 struct arglist fn; 424 fn.lastp = &fn.list; 425 oexitstatus = exitstatus; 426 switch (redir->type) { 427 case NFROM: 428 case NTO: 429 case NFROMTO: 430 case NAPPEND: 431 case NCLOBBER: 432 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 433 redir->nfile.expfname = fn.list->text; 434 break; 435 case NFROMFD: 436 case NTOFD: 437 if (redir->ndup.vname) { 438 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); 439 fixredir(redir, fn.list->text, 1); 440 } 441 break; 442 } 443 } 444 } 445 446 447 448 /* 449 * Evaluate a pipeline. All the processes in the pipeline are children 450 * of the process creating the pipeline. (This differs from some versions 451 * of the shell, which make the last process in a pipeline the parent 452 * of all the rest.) 453 */ 454 455 STATIC void 456 evalpipe(union node *n) 457 { 458 struct job *jp; 459 struct nodelist *lp; 460 int pipelen; 461 int prevfd; 462 int pip[2]; 463 464 TRACE(("evalpipe(%p) called\n", (void *)n)); 465 pipelen = 0; 466 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) 467 pipelen++; 468 INTOFF; 469 jp = makejob(n, pipelen); 470 prevfd = -1; 471 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 472 prehash(lp->n); 473 pip[1] = -1; 474 if (lp->next) { 475 if (pipe(pip) < 0) { 476 close(prevfd); 477 error("Pipe call failed: %s", strerror(errno)); 478 } 479 } 480 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { 481 INTON; 482 if (prevfd > 0) { 483 dup2(prevfd, 0); 484 close(prevfd); 485 } 486 if (pip[1] >= 0) { 487 if (!(prevfd >= 0 && pip[0] == 0)) 488 close(pip[0]); 489 if (pip[1] != 1) { 490 dup2(pip[1], 1); 491 close(pip[1]); 492 } 493 } 494 evaltree(lp->n, EV_EXIT); 495 } 496 if (prevfd >= 0) 497 close(prevfd); 498 prevfd = pip[0]; 499 close(pip[1]); 500 } 501 INTON; 502 if (n->npipe.backgnd == 0) { 503 INTOFF; 504 exitstatus = waitforjob(jp, (int *)NULL); 505 TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 506 INTON; 507 } 508 } 509 510 511 512 /* 513 * Execute a command inside back quotes. If it's a builtin command, we 514 * want to save its output in a block obtained from malloc. Otherwise 515 * we fork off a subprocess and get the output of the command via a pipe. 516 * Should be called with interrupts off. 517 */ 518 519 void 520 evalbackcmd(union node *n, struct backcmd *result) 521 { 522 int pip[2]; 523 struct job *jp; 524 struct stackmark smark; /* unnecessary */ 525 526 setstackmark(&smark); 527 result->fd = -1; 528 result->buf = NULL; 529 result->nleft = 0; 530 result->jp = NULL; 531 if (n == NULL) { 532 exitstatus = 0; 533 goto out; 534 } 535 if (n->type == NCMD) { 536 exitstatus = oexitstatus; 537 evalcommand(n, EV_BACKCMD, result); 538 } else { 539 exitstatus = 0; 540 if (pipe(pip) < 0) 541 error("Pipe call failed: %s", strerror(errno)); 542 jp = makejob(n, 1); 543 if (forkshell(jp, n, FORK_NOJOB) == 0) { 544 FORCEINTON; 545 close(pip[0]); 546 if (pip[1] != 1) { 547 dup2(pip[1], 1); 548 close(pip[1]); 549 } 550 evaltree(n, EV_EXIT); 551 } 552 close(pip[1]); 553 result->fd = pip[0]; 554 result->jp = jp; 555 } 556 out: 557 popstackmark(&smark); 558 TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n", 559 result->fd, result->buf, result->nleft, result->jp)); 560 } 561 562 563 564 /* 565 * Execute a simple command. 566 */ 567 568 STATIC void 569 evalcommand(union node *cmd, int flags, struct backcmd *backcmd) 570 { 571 struct stackmark smark; 572 union node *argp; 573 struct arglist arglist; 574 struct arglist varlist; 575 char **argv; 576 int argc; 577 char **envp; 578 int varflag; 579 struct strlist *sp; 580 int mode; 581 int pip[2]; 582 struct cmdentry cmdentry; 583 struct job *jp; 584 struct jmploc jmploc; 585 struct jmploc *volatile savehandler; 586 char *volatile savecmdname; 587 volatile struct shparam saveparam; 588 struct localvar *volatile savelocalvars; 589 volatile int e; 590 char *lastarg; 591 int realstatus; 592 int do_clearcmdentry; 593 #if __GNUC__ 594 /* Avoid longjmp clobbering */ 595 (void) &argv; 596 (void) &argc; 597 (void) &lastarg; 598 (void) &flags; 599 (void) &do_clearcmdentry; 600 #endif 601 602 /* First expand the arguments. */ 603 TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); 604 setstackmark(&smark); 605 arglist.lastp = &arglist.list; 606 varlist.lastp = &varlist.list; 607 varflag = 1; 608 do_clearcmdentry = 0; 609 oexitstatus = exitstatus; 610 exitstatus = 0; 611 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 612 char *p = argp->narg.text; 613 if (varflag && is_name(*p)) { 614 do { 615 p++; 616 } while (is_in_name(*p)); 617 if (*p == '=') { 618 expandarg(argp, &varlist, EXP_VARTILDE); 619 continue; 620 } 621 } 622 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 623 varflag = 0; 624 } 625 *arglist.lastp = NULL; 626 *varlist.lastp = NULL; 627 expredir(cmd->ncmd.redirect); 628 argc = 0; 629 for (sp = arglist.list ; sp ; sp = sp->next) 630 argc++; 631 argv = stalloc(sizeof (char *) * (argc + 1)); 632 633 for (sp = arglist.list ; sp ; sp = sp->next) { 634 TRACE(("evalcommand arg: %s\n", sp->text)); 635 *argv++ = sp->text; 636 } 637 *argv = NULL; 638 lastarg = NULL; 639 if (iflag && funcnest == 0 && argc > 0) 640 lastarg = argv[-1]; 641 argv -= argc; 642 643 /* Print the command if xflag is set. */ 644 if (xflag) { 645 outc('+', &errout); 646 for (sp = varlist.list ; sp ; sp = sp->next) { 647 outc(' ', &errout); 648 out2str(sp->text); 649 } 650 for (sp = arglist.list ; sp ; sp = sp->next) { 651 outc(' ', &errout); 652 out2str(sp->text); 653 } 654 outc('\n', &errout); 655 flushout(&errout); 656 } 657 658 /* Now locate the command. */ 659 if (argc == 0) { 660 cmdentry.cmdtype = CMDBUILTIN; 661 cmdentry.u.index = BLTINCMD; 662 } else { 663 static const char PATH[] = "PATH="; 664 char *path = pathval(); 665 666 /* 667 * Modify the command lookup path, if a PATH= assignment 668 * is present 669 */ 670 for (sp = varlist.list ; sp ; sp = sp->next) 671 if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { 672 path = sp->text + sizeof(PATH) - 1; 673 /* 674 * On `PATH=... command`, we need to make 675 * sure that the command isn't using the 676 * non-updated hash table of the outer PATH 677 * setting and we need to make sure that 678 * the hash table isn't filled with items 679 * from the temporary setting. 680 * 681 * It would be better to forbit using and 682 * updating the table while this command 683 * runs, by the command finding mechanism 684 * is heavily integrated with hash handling, 685 * so we just delete the hash before and after 686 * the command runs. Partly deleting like 687 * changepatch() does doesn't seem worth the 688 * bookinging effort, since most such runs add 689 * directories in front of the new PATH. 690 */ 691 clearcmdentry(0); 692 do_clearcmdentry = 1; 693 } 694 695 find_command(argv[0], &cmdentry, 1, path); 696 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ 697 exitstatus = 127; 698 flushout(&errout); 699 return; 700 } 701 /* implement the bltin builtin here */ 702 if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { 703 for (;;) { 704 argv++; 705 if (--argc == 0) 706 break; 707 if ((cmdentry.u.index = find_builtin(*argv)) < 0) { 708 outfmt(&errout, "%s: not found\n", *argv); 709 exitstatus = 127; 710 flushout(&errout); 711 return; 712 } 713 if (cmdentry.u.index != BLTINCMD) 714 break; 715 } 716 } 717 } 718 719 /* Fork off a child process if necessary. */ 720 if (cmd->ncmd.backgnd 721 || (cmdentry.cmdtype == CMDNORMAL 722 && ((flags & EV_EXIT) == 0 || Tflag)) 723 || ((flags & EV_BACKCMD) != 0 724 && (cmdentry.cmdtype != CMDBUILTIN 725 || cmdentry.u.index == CDCMD 726 || cmdentry.u.index == DOTCMD 727 || cmdentry.u.index == EVALCMD)) 728 || (cmdentry.cmdtype == CMDBUILTIN && 729 cmdentry.u.index == COMMANDCMD)) { 730 jp = makejob(cmd, 1); 731 mode = cmd->ncmd.backgnd; 732 if (flags & EV_BACKCMD) { 733 mode = FORK_NOJOB; 734 if (pipe(pip) < 0) 735 error("Pipe call failed: %s", strerror(errno)); 736 } 737 if (forkshell(jp, cmd, mode) != 0) 738 goto parent; /* at end of routine */ 739 if (flags & EV_BACKCMD) { 740 FORCEINTON; 741 close(pip[0]); 742 if (pip[1] != 1) { 743 dup2(pip[1], 1); 744 close(pip[1]); 745 } 746 } 747 flags |= EV_EXIT; 748 } 749 750 /* This is the child process if a fork occurred. */ 751 /* Execute the command. */ 752 if (cmdentry.cmdtype == CMDFUNCTION) { 753 #ifdef DEBUG 754 trputs("Shell function: "); trargs(argv); 755 #endif 756 redirect(cmd->ncmd.redirect, REDIR_PUSH); 757 saveparam = shellparam; 758 shellparam.malloc = 0; 759 shellparam.reset = 1; 760 shellparam.nparam = argc - 1; 761 shellparam.p = argv + 1; 762 shellparam.optnext = NULL; 763 INTOFF; 764 savelocalvars = localvars; 765 localvars = NULL; 766 INTON; 767 if (setjmp(jmploc.loc)) { 768 if (exception == EXSHELLPROC) 769 freeparam((struct shparam *)&saveparam); 770 else { 771 freeparam(&shellparam); 772 shellparam = saveparam; 773 } 774 poplocalvars(); 775 localvars = savelocalvars; 776 handler = savehandler; 777 longjmp(handler->loc, 1); 778 } 779 savehandler = handler; 780 handler = &jmploc; 781 for (sp = varlist.list ; sp ; sp = sp->next) 782 mklocal(sp->text); 783 funcnest++; 784 if (flags & EV_TESTED) 785 evaltree(cmdentry.u.func, EV_TESTED); 786 else 787 evaltree(cmdentry.u.func, 0); 788 funcnest--; 789 INTOFF; 790 poplocalvars(); 791 localvars = savelocalvars; 792 freeparam(&shellparam); 793 shellparam = saveparam; 794 handler = savehandler; 795 popredir(); 796 INTON; 797 if (evalskip == SKIPFUNC) { 798 evalskip = 0; 799 skipcount = 0; 800 } 801 if (flags & EV_EXIT) 802 exitshell(exitstatus); 803 } else if (cmdentry.cmdtype == CMDBUILTIN) { 804 #ifdef DEBUG 805 trputs("builtin command: "); trargs(argv); 806 #endif 807 mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; 808 if (flags == EV_BACKCMD) { 809 memout.nleft = 0; 810 memout.nextc = memout.buf; 811 memout.bufsize = 64; 812 mode |= REDIR_BACKQ; 813 } 814 redirect(cmd->ncmd.redirect, mode); 815 savecmdname = commandname; 816 cmdenviron = varlist.list; 817 e = -1; 818 if (setjmp(jmploc.loc)) { 819 e = exception; 820 exitstatus = (e == EXINT)? SIGINT+128 : 2; 821 goto cmddone; 822 } 823 savehandler = handler; 824 handler = &jmploc; 825 commandname = argv[0]; 826 argptr = argv + 1; 827 optptr = NULL; /* initialize nextopt */ 828 exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); 829 flushall(); 830 cmddone: 831 cmdenviron = NULL; 832 out1 = &output; 833 out2 = &errout; 834 freestdout(); 835 if (e != EXSHELLPROC) { 836 commandname = savecmdname; 837 if (flags & EV_EXIT) { 838 exitshell(exitstatus); 839 } 840 } 841 handler = savehandler; 842 if (e != -1) { 843 if ((e != EXERROR && e != EXEXEC) 844 || cmdentry.u.index == BLTINCMD 845 || cmdentry.u.index == DOTCMD 846 || cmdentry.u.index == EVALCMD 847 #ifndef NO_HISTORY 848 || cmdentry.u.index == HISTCMD 849 #endif 850 || cmdentry.u.index == EXECCMD 851 || cmdentry.u.index == COMMANDCMD) 852 exraise(e); 853 FORCEINTON; 854 } 855 if (cmdentry.u.index != EXECCMD) 856 popredir(); 857 if (flags == EV_BACKCMD) { 858 backcmd->buf = memout.buf; 859 backcmd->nleft = memout.nextc - memout.buf; 860 memout.buf = NULL; 861 } 862 } else { 863 #ifdef DEBUG 864 trputs("normal command: "); trargs(argv); 865 #endif 866 clearredir(); 867 redirect(cmd->ncmd.redirect, 0); 868 for (sp = varlist.list ; sp ; sp = sp->next) 869 setvareq(sp->text, VEXPORT|VSTACK); 870 envp = environment(); 871 shellexec(argv, envp, pathval(), cmdentry.u.index); 872 /*NOTREACHED*/ 873 } 874 goto out; 875 876 parent: /* parent process gets here (if we forked) */ 877 if (mode == 0) { /* argument to fork */ 878 INTOFF; 879 exitstatus = waitforjob(jp, &realstatus); 880 INTON; 881 if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) { 882 evalskip = SKIPBREAK; 883 skipcount = loopnest; 884 } 885 } else if (mode == 2) { 886 backcmd->fd = pip[0]; 887 close(pip[1]); 888 backcmd->jp = jp; 889 } 890 891 out: 892 if (lastarg) 893 setvar("_", lastarg, 0); 894 if (do_clearcmdentry) 895 clearcmdentry(0); 896 popstackmark(&smark); 897 } 898 899 900 901 /* 902 * Search for a command. This is called before we fork so that the 903 * location of the command will be available in the parent as well as 904 * the child. The check for "goodname" is an overly conservative 905 * check that the name will not be subject to expansion. 906 */ 907 908 STATIC void 909 prehash(union node *n) 910 { 911 struct cmdentry entry; 912 913 if (n->type == NCMD && n->ncmd.args) 914 if (goodname(n->ncmd.args->narg.text)) 915 find_command(n->ncmd.args->narg.text, &entry, 0, 916 pathval()); 917 } 918 919 920 921 /* 922 * Builtin commands. Builtin commands whose functions are closely 923 * tied to evaluation are implemented here. 924 */ 925 926 /* 927 * No command given, or a bltin command with no arguments. Set the 928 * specified variables. 929 */ 930 931 int 932 bltincmd(int argc __unused, char **argv __unused) 933 { 934 listsetvar(cmdenviron); 935 /* 936 * Preserve exitstatus of a previous possible redirection 937 * as POSIX mandates 938 */ 939 return exitstatus; 940 } 941 942 943 /* 944 * Handle break and continue commands. Break, continue, and return are 945 * all handled by setting the evalskip flag. The evaluation routines 946 * above all check this flag, and if it is set they start skipping 947 * commands rather than executing them. The variable skipcount is 948 * the number of loops to break/continue, or the number of function 949 * levels to return. (The latter is always 1.) It should probably 950 * be an error to break out of more loops than exist, but it isn't 951 * in the standard shell so we don't make it one here. 952 */ 953 954 int 955 breakcmd(int argc, char **argv) 956 { 957 int n = argc > 1 ? number(argv[1]) : 1; 958 959 if (n > loopnest) 960 n = loopnest; 961 if (n > 0) { 962 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; 963 skipcount = n; 964 } 965 return 0; 966 } 967 968 /* 969 * The `command' command. 970 */ 971 int 972 commandcmd(int argc, char **argv) 973 { 974 static char stdpath[] = _PATH_STDPATH; 975 struct jmploc loc, *old; 976 struct strlist *sp; 977 char *path; 978 int ch; 979 980 for (sp = cmdenviron; sp ; sp = sp->next) 981 setvareq(sp->text, VEXPORT|VSTACK); 982 path = pathval(); 983 984 optind = optreset = 1; 985 opterr = 0; 986 while ((ch = getopt(argc, argv, "p")) != -1) { 987 switch (ch) { 988 case 'p': 989 path = stdpath; 990 break; 991 case '?': 992 default: 993 error("unknown option: -%c", optopt); 994 } 995 } 996 argc -= optind; 997 argv += optind; 998 999 if (argc != 0) { 1000 old = handler; 1001 handler = &loc; 1002 if (setjmp(handler->loc) == 0) 1003 shellexec(argv, environment(), path, 0); 1004 handler = old; 1005 if (exception == EXEXEC) 1006 exit(exerrno); 1007 exraise(exception); 1008 } 1009 1010 /* 1011 * Do nothing successfully if no command was specified; 1012 * ksh also does this. 1013 */ 1014 exit(0); 1015 } 1016 1017 1018 /* 1019 * The return command. 1020 */ 1021 1022 int 1023 returncmd(int argc, char **argv) 1024 { 1025 int ret = argc > 1 ? number(argv[1]) : oexitstatus; 1026 1027 if (funcnest) { 1028 evalskip = SKIPFUNC; 1029 skipcount = 1; 1030 } else { 1031 /* skip the rest of the file */ 1032 evalskip = SKIPFILE; 1033 skipcount = 1; 1034 } 1035 return ret; 1036 } 1037 1038 1039 int 1040 falsecmd(int argc __unused, char **argv __unused) 1041 { 1042 return 1; 1043 } 1044 1045 1046 int 1047 truecmd(int argc __unused, char **argv __unused) 1048 { 1049 return 0; 1050 } 1051 1052 1053 int 1054 execcmd(int argc, char **argv) 1055 { 1056 if (argc > 1) { 1057 struct strlist *sp; 1058 1059 iflag = 0; /* exit on error */ 1060 mflag = 0; 1061 optschanged(); 1062 for (sp = cmdenviron; sp ; sp = sp->next) 1063 setvareq(sp->text, VEXPORT|VSTACK); 1064 shellexec(argv + 1, environment(), pathval(), 0); 1065 1066 } 1067 return 0; 1068 } 1069