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 * 3. 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/resource.h> 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 int evalskip; /* set if we are skipping commands */ 77 int skipcount; /* number of levels to skip */ 78 static int loopnest; /* current loop nesting level */ 79 int funcnest; /* depth of function calls */ 80 static int builtin_flags; /* evalcommand flags for builtins */ 81 82 83 char *commandname; 84 struct arglist *cmdenviron; 85 int exitstatus; /* exit status of last command */ 86 int oexitstatus; /* saved exit status */ 87 88 89 static void evalloop(union node *, int); 90 static void evalfor(union node *, int); 91 static union node *evalcase(union node *); 92 static void evalsubshell(union node *, int); 93 static void evalredir(union node *, int); 94 static void exphere(union node *, struct arglist *); 95 static void expredir(union node *); 96 static void evalpipe(union node *); 97 static int is_valid_fast_cmdsubst(union node *n); 98 static void evalcommand(union node *, int, struct backcmd *); 99 static void prehash(union node *); 100 101 102 /* 103 * Called to reset things after an exception. 104 */ 105 106 void 107 reseteval(void) 108 { 109 evalskip = 0; 110 loopnest = 0; 111 } 112 113 114 /* 115 * The eval command. 116 */ 117 118 int 119 evalcmd(int argc, char **argv) 120 { 121 char *p; 122 char *concat; 123 char **ap; 124 125 if (argc > 1) { 126 p = argv[1]; 127 if (argc > 2) { 128 STARTSTACKSTR(concat); 129 ap = argv + 2; 130 for (;;) { 131 STPUTS(p, concat); 132 if ((p = *ap++) == NULL) 133 break; 134 STPUTC(' ', concat); 135 } 136 STPUTC('\0', concat); 137 p = grabstackstr(concat); 138 } 139 evalstring(p, builtin_flags); 140 } else 141 exitstatus = 0; 142 return exitstatus; 143 } 144 145 146 /* 147 * Execute a command or commands contained in a string. 148 */ 149 150 void 151 evalstring(const char *s, int flags) 152 { 153 union node *n; 154 struct stackmark smark; 155 int flags_exit; 156 int any; 157 158 flags_exit = flags & EV_EXIT; 159 flags &= ~EV_EXIT; 160 any = 0; 161 setstackmark(&smark); 162 setinputstring(s, 1); 163 while ((n = parsecmd(0)) != NEOF) { 164 if (n != NULL && !nflag) { 165 if (flags_exit && preadateof()) 166 evaltree(n, flags | EV_EXIT); 167 else 168 evaltree(n, flags); 169 any = 1; 170 if (evalskip) 171 break; 172 } 173 popstackmark(&smark); 174 setstackmark(&smark); 175 } 176 popfile(); 177 popstackmark(&smark); 178 if (!any) 179 exitstatus = 0; 180 if (flags_exit) 181 exraise(EXEXIT); 182 } 183 184 185 /* 186 * Evaluate a parse tree. The value is left in the global variable 187 * exitstatus. 188 */ 189 190 void 191 evaltree(union node *n, int flags) 192 { 193 int do_etest; 194 union node *next; 195 struct stackmark smark; 196 197 setstackmark(&smark); 198 do_etest = 0; 199 if (n == NULL) { 200 TRACE(("evaltree(NULL) called\n")); 201 exitstatus = 0; 202 goto out; 203 } 204 do { 205 next = NULL; 206 #ifndef NO_HISTORY 207 displayhist = 1; /* show history substitutions done with fc */ 208 #endif 209 TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type)); 210 switch (n->type) { 211 case NSEMI: 212 evaltree(n->nbinary.ch1, flags & ~EV_EXIT); 213 if (evalskip) 214 goto out; 215 next = n->nbinary.ch2; 216 break; 217 case NAND: 218 evaltree(n->nbinary.ch1, EV_TESTED); 219 if (evalskip || exitstatus != 0) { 220 goto out; 221 } 222 next = n->nbinary.ch2; 223 break; 224 case NOR: 225 evaltree(n->nbinary.ch1, EV_TESTED); 226 if (evalskip || exitstatus == 0) 227 goto out; 228 next = n->nbinary.ch2; 229 break; 230 case NREDIR: 231 evalredir(n, flags); 232 break; 233 case NSUBSHELL: 234 evalsubshell(n, flags); 235 do_etest = !(flags & EV_TESTED); 236 break; 237 case NBACKGND: 238 evalsubshell(n, flags); 239 break; 240 case NIF: { 241 evaltree(n->nif.test, EV_TESTED); 242 if (evalskip) 243 goto out; 244 if (exitstatus == 0) 245 next = n->nif.ifpart; 246 else if (n->nif.elsepart) 247 next = n->nif.elsepart; 248 else 249 exitstatus = 0; 250 break; 251 } 252 case NWHILE: 253 case NUNTIL: 254 evalloop(n, flags & ~EV_EXIT); 255 break; 256 case NFOR: 257 evalfor(n, flags & ~EV_EXIT); 258 break; 259 case NCASE: 260 next = evalcase(n); 261 break; 262 case NCLIST: 263 next = n->nclist.body; 264 break; 265 case NCLISTFALLTHRU: 266 if (n->nclist.body) { 267 evaltree(n->nclist.body, flags & ~EV_EXIT); 268 if (evalskip) 269 goto out; 270 } 271 next = n->nclist.next; 272 break; 273 case NDEFUN: 274 defun(n->narg.text, n->narg.next); 275 exitstatus = 0; 276 break; 277 case NNOT: 278 evaltree(n->nnot.com, EV_TESTED); 279 if (evalskip) 280 goto out; 281 exitstatus = !exitstatus; 282 break; 283 284 case NPIPE: 285 evalpipe(n); 286 do_etest = !(flags & EV_TESTED); 287 break; 288 case NCMD: 289 evalcommand(n, flags, (struct backcmd *)NULL); 290 do_etest = !(flags & EV_TESTED); 291 break; 292 default: 293 out1fmt("Node type = %d\n", n->type); 294 flushout(&output); 295 break; 296 } 297 n = next; 298 popstackmark(&smark); 299 setstackmark(&smark); 300 } while (n != NULL); 301 out: 302 popstackmark(&smark); 303 if (pendingsig) 304 dotrap(); 305 if (eflag && exitstatus != 0 && do_etest) 306 exitshell(exitstatus); 307 if (flags & EV_EXIT) 308 exraise(EXEXIT); 309 } 310 311 312 static void 313 evalloop(union node *n, int flags) 314 { 315 int status; 316 317 loopnest++; 318 status = 0; 319 for (;;) { 320 if (!evalskip) 321 evaltree(n->nbinary.ch1, EV_TESTED); 322 if (evalskip) { 323 if (evalskip == SKIPCONT && --skipcount <= 0) { 324 evalskip = 0; 325 continue; 326 } 327 if (evalskip == SKIPBREAK && --skipcount <= 0) 328 evalskip = 0; 329 if (evalskip == SKIPRETURN) 330 status = exitstatus; 331 break; 332 } 333 if (n->type == NWHILE) { 334 if (exitstatus != 0) 335 break; 336 } else { 337 if (exitstatus == 0) 338 break; 339 } 340 evaltree(n->nbinary.ch2, flags); 341 status = exitstatus; 342 } 343 loopnest--; 344 exitstatus = status; 345 } 346 347 348 349 static void 350 evalfor(union node *n, int flags) 351 { 352 struct arglist arglist; 353 union node *argp; 354 int i; 355 int status; 356 357 emptyarglist(&arglist); 358 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { 359 oexitstatus = exitstatus; 360 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 361 } 362 363 loopnest++; 364 status = 0; 365 for (i = 0; i < arglist.count; i++) { 366 setvar(n->nfor.var, arglist.args[i], 0); 367 evaltree(n->nfor.body, flags); 368 status = exitstatus; 369 if (evalskip) { 370 if (evalskip == SKIPCONT && --skipcount <= 0) { 371 evalskip = 0; 372 continue; 373 } 374 if (evalskip == SKIPBREAK && --skipcount <= 0) 375 evalskip = 0; 376 break; 377 } 378 } 379 loopnest--; 380 exitstatus = status; 381 } 382 383 384 /* 385 * Evaluate a case statement, returning the selected tree. 386 * 387 * The exit status needs care to get right. 388 */ 389 390 static union node * 391 evalcase(union node *n) 392 { 393 union node *cp; 394 union node *patp; 395 struct arglist arglist; 396 397 emptyarglist(&arglist); 398 oexitstatus = exitstatus; 399 expandarg(n->ncase.expr, &arglist, EXP_TILDE); 400 for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) { 401 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { 402 if (casematch(patp, arglist.args[0])) { 403 while (cp->nclist.next && 404 cp->type == NCLISTFALLTHRU && 405 cp->nclist.body == NULL) 406 cp = cp->nclist.next; 407 if (cp->nclist.next && 408 cp->type == NCLISTFALLTHRU) 409 return (cp); 410 if (cp->nclist.body == NULL) 411 exitstatus = 0; 412 return (cp->nclist.body); 413 } 414 } 415 } 416 exitstatus = 0; 417 return (NULL); 418 } 419 420 421 422 /* 423 * Kick off a subshell to evaluate a tree. 424 */ 425 426 static void 427 evalsubshell(union node *n, int flags) 428 { 429 struct job *jp; 430 int backgnd = (n->type == NBACKGND); 431 432 oexitstatus = exitstatus; 433 expredir(n->nredir.redirect); 434 if ((!backgnd && flags & EV_EXIT && !have_traps()) || 435 forkshell(jp = makejob(n, 1), n, backgnd) == 0) { 436 if (backgnd) 437 flags &=~ EV_TESTED; 438 redirect(n->nredir.redirect, 0); 439 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 440 } else if (! backgnd) { 441 INTOFF; 442 exitstatus = waitforjob(jp, (int *)NULL); 443 INTON; 444 } else 445 exitstatus = 0; 446 } 447 448 449 /* 450 * Evaluate a redirected compound command. 451 */ 452 453 static void 454 evalredir(union node *n, int flags) 455 { 456 struct jmploc jmploc; 457 struct jmploc *savehandler; 458 volatile int in_redirect = 1; 459 460 oexitstatus = exitstatus; 461 expredir(n->nredir.redirect); 462 savehandler = handler; 463 if (setjmp(jmploc.loc)) { 464 int e; 465 466 handler = savehandler; 467 e = exception; 468 popredir(); 469 if (e == EXERROR && in_redirect) { 470 FORCEINTON; 471 return; 472 } 473 longjmp(handler->loc, 1); 474 } else { 475 INTOFF; 476 handler = &jmploc; 477 redirect(n->nredir.redirect, REDIR_PUSH); 478 in_redirect = 0; 479 INTON; 480 evaltree(n->nredir.n, flags); 481 } 482 INTOFF; 483 handler = savehandler; 484 popredir(); 485 INTON; 486 } 487 488 489 static void 490 exphere(union node *redir, struct arglist *fn) 491 { 492 struct jmploc jmploc; 493 struct jmploc *savehandler; 494 struct localvar *savelocalvars; 495 int need_longjmp = 0; 496 unsigned char saveoptreset; 497 498 redir->nhere.expdoc = ""; 499 savelocalvars = localvars; 500 localvars = NULL; 501 saveoptreset = shellparam.reset; 502 forcelocal++; 503 savehandler = handler; 504 if (setjmp(jmploc.loc)) 505 need_longjmp = exception != EXERROR; 506 else { 507 handler = &jmploc; 508 expandarg(redir->nhere.doc, fn, 0); 509 redir->nhere.expdoc = fn->args[0]; 510 INTOFF; 511 } 512 handler = savehandler; 513 forcelocal--; 514 poplocalvars(); 515 localvars = savelocalvars; 516 shellparam.reset = saveoptreset; 517 if (need_longjmp) 518 longjmp(handler->loc, 1); 519 INTON; 520 } 521 522 523 /* 524 * Compute the names of the files in a redirection list. 525 */ 526 527 static void 528 expredir(union node *n) 529 { 530 union node *redir; 531 532 for (redir = n ; redir ; redir = redir->nfile.next) { 533 struct arglist fn; 534 emptyarglist(&fn); 535 switch (redir->type) { 536 case NFROM: 537 case NTO: 538 case NFROMTO: 539 case NAPPEND: 540 case NCLOBBER: 541 expandarg(redir->nfile.fname, &fn, EXP_TILDE); 542 redir->nfile.expfname = fn.args[0]; 543 break; 544 case NFROMFD: 545 case NTOFD: 546 if (redir->ndup.vname) { 547 expandarg(redir->ndup.vname, &fn, EXP_TILDE); 548 fixredir(redir, fn.args[0], 1); 549 } 550 break; 551 case NXHERE: 552 exphere(redir, &fn); 553 break; 554 } 555 } 556 } 557 558 559 560 /* 561 * Evaluate a pipeline. All the processes in the pipeline are children 562 * of the process creating the pipeline. (This differs from some versions 563 * of the shell, which make the last process in a pipeline the parent 564 * of all the rest.) 565 */ 566 567 static void 568 evalpipe(union node *n) 569 { 570 struct job *jp; 571 struct nodelist *lp; 572 int pipelen; 573 int prevfd; 574 int pip[2]; 575 576 TRACE(("evalpipe(%p) called\n", (void *)n)); 577 pipelen = 0; 578 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) 579 pipelen++; 580 INTOFF; 581 jp = makejob(n, pipelen); 582 prevfd = -1; 583 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 584 prehash(lp->n); 585 pip[1] = -1; 586 if (lp->next) { 587 if (pipe(pip) < 0) { 588 if (prevfd >= 0) 589 close(prevfd); 590 error("Pipe call failed: %s", strerror(errno)); 591 } 592 } 593 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { 594 INTON; 595 if (prevfd > 0) { 596 dup2(prevfd, 0); 597 close(prevfd); 598 } 599 if (pip[1] >= 0) { 600 if (!(prevfd >= 0 && pip[0] == 0)) 601 close(pip[0]); 602 if (pip[1] != 1) { 603 dup2(pip[1], 1); 604 close(pip[1]); 605 } 606 } 607 evaltree(lp->n, EV_EXIT); 608 } 609 if (prevfd >= 0) 610 close(prevfd); 611 prevfd = pip[0]; 612 if (pip[1] != -1) 613 close(pip[1]); 614 } 615 INTON; 616 if (n->npipe.backgnd == 0) { 617 INTOFF; 618 exitstatus = waitforjob(jp, (int *)NULL); 619 TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 620 INTON; 621 } else 622 exitstatus = 0; 623 } 624 625 626 627 static int 628 is_valid_fast_cmdsubst(union node *n) 629 { 630 631 return (n->type == NCMD); 632 } 633 634 /* 635 * Execute a command inside back quotes. If it's a builtin command, we 636 * want to save its output in a block obtained from malloc. Otherwise 637 * we fork off a subprocess and get the output of the command via a pipe. 638 * Should be called with interrupts off. 639 */ 640 641 void 642 evalbackcmd(union node *n, struct backcmd *result) 643 { 644 int pip[2]; 645 struct job *jp; 646 struct stackmark smark; 647 struct jmploc jmploc; 648 struct jmploc *savehandler; 649 struct localvar *savelocalvars; 650 unsigned char saveoptreset; 651 652 result->fd = -1; 653 result->buf = NULL; 654 result->nleft = 0; 655 result->jp = NULL; 656 if (n == NULL) { 657 exitstatus = 0; 658 return; 659 } 660 setstackmark(&smark); 661 exitstatus = oexitstatus; 662 if (is_valid_fast_cmdsubst(n)) { 663 savelocalvars = localvars; 664 localvars = NULL; 665 saveoptreset = shellparam.reset; 666 forcelocal++; 667 savehandler = handler; 668 if (setjmp(jmploc.loc)) { 669 if (exception == EXERROR) 670 /* nothing */; 671 else if (exception != 0) { 672 handler = savehandler; 673 forcelocal--; 674 poplocalvars(); 675 localvars = savelocalvars; 676 shellparam.reset = saveoptreset; 677 longjmp(handler->loc, 1); 678 } 679 } else { 680 handler = &jmploc; 681 evalcommand(n, EV_BACKCMD, result); 682 } 683 handler = savehandler; 684 forcelocal--; 685 poplocalvars(); 686 localvars = savelocalvars; 687 shellparam.reset = saveoptreset; 688 } else { 689 if (pipe(pip) < 0) 690 error("Pipe call failed: %s", strerror(errno)); 691 jp = makejob(n, 1); 692 if (forkshell(jp, n, FORK_NOJOB) == 0) { 693 FORCEINTON; 694 close(pip[0]); 695 if (pip[1] != 1) { 696 dup2(pip[1], 1); 697 close(pip[1]); 698 } 699 evaltree(n, EV_EXIT); 700 } 701 close(pip[1]); 702 result->fd = pip[0]; 703 result->jp = jp; 704 } 705 popstackmark(&smark); 706 TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n", 707 result->fd, result->buf, result->nleft, result->jp)); 708 } 709 710 static int 711 mustexpandto(const char *argtext, const char *mask) 712 { 713 for (;;) { 714 if (*argtext == CTLQUOTEMARK || *argtext == CTLQUOTEEND) { 715 argtext++; 716 continue; 717 } 718 if (*argtext == CTLESC) 719 argtext++; 720 else if (BASESYNTAX[(int)*argtext] == CCTL) 721 return (0); 722 if (*argtext != *mask) 723 return (0); 724 if (*argtext == '\0') 725 return (1); 726 argtext++; 727 mask++; 728 } 729 } 730 731 static int 732 isdeclarationcmd(struct narg *arg) 733 { 734 int have_command = 0; 735 736 if (arg == NULL) 737 return (0); 738 while (mustexpandto(arg->text, "command")) { 739 have_command = 1; 740 arg = &arg->next->narg; 741 if (arg == NULL) 742 return (0); 743 /* 744 * To also allow "command -p" and "command --" as part of 745 * a declaration command, add code here. 746 * We do not do this, as ksh does not do it either and it 747 * is not required by POSIX. 748 */ 749 } 750 return (mustexpandto(arg->text, "export") || 751 mustexpandto(arg->text, "readonly") || 752 (mustexpandto(arg->text, "local") && 753 (have_command || !isfunc("local")))); 754 } 755 756 static void 757 xtracecommand(struct arglist *varlist, int argc, char **argv) 758 { 759 char sep = 0; 760 const char *text, *p, *ps4; 761 int i; 762 763 ps4 = expandstr(ps4val()); 764 out2str(ps4 != NULL ? ps4 : ps4val()); 765 for (i = 0; i < varlist->count; i++) { 766 text = varlist->args[i]; 767 if (sep != 0) 768 out2c(' '); 769 p = strchr(text, '='); 770 if (p != NULL) { 771 p++; 772 outbin(text, p - text, out2); 773 out2qstr(p); 774 } else 775 out2qstr(text); 776 sep = ' '; 777 } 778 for (i = 0; i < argc; i++) { 779 text = argv[i]; 780 if (sep != 0) 781 out2c(' '); 782 out2qstr(text); 783 sep = ' '; 784 } 785 out2c('\n'); 786 flushout(&errout); 787 } 788 789 /* 790 * Check if a builtin can safely be executed in the same process, 791 * even though it should be in a subshell (command substitution). 792 * Note that jobid, jobs, times and trap can show information not 793 * available in a child process; this is deliberate. 794 * The arguments should already have been expanded. 795 */ 796 static int 797 safe_builtin(int idx, int argc, char **argv) 798 { 799 /* Generated from builtins.def. */ 800 if (safe_builtin_always(idx)) 801 return (1); 802 if (idx == EXPORTCMD || idx == TRAPCMD || idx == ULIMITCMD || 803 idx == UMASKCMD) 804 return (argc <= 1 || (argc == 2 && argv[1][0] == '-')); 805 if (idx == SETCMD) 806 return (argc <= 1 || (argc == 2 && (argv[1][0] == '-' || 807 argv[1][0] == '+') && argv[1][1] == 'o' && 808 argv[1][2] == '\0')); 809 return (0); 810 } 811 812 /* 813 * Execute a simple command. 814 * Note: This may or may not return if (flags & EV_EXIT). 815 */ 816 817 static void 818 evalcommand(union node *cmd, int flags, struct backcmd *backcmd) 819 { 820 union node *argp; 821 struct arglist arglist; 822 struct arglist varlist; 823 char **argv; 824 int argc; 825 char **envp; 826 int varflag; 827 int mode; 828 int pip[2]; 829 struct cmdentry cmdentry; 830 struct job *jp; 831 struct jmploc jmploc; 832 struct jmploc *savehandler; 833 char *savecmdname; 834 struct shparam saveparam; 835 struct localvar *savelocalvars; 836 struct parsefile *savetopfile; 837 volatile int e; 838 char *lastarg; 839 int signaled; 840 int do_clearcmdentry; 841 const char *path = pathval(); 842 int i; 843 844 /* First expand the arguments. */ 845 TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); 846 emptyarglist(&arglist); 847 emptyarglist(&varlist); 848 varflag = 1; 849 jp = NULL; 850 do_clearcmdentry = 0; 851 oexitstatus = exitstatus; 852 exitstatus = 0; 853 /* Add one slot at the beginning for tryexec(). */ 854 appendarglist(&arglist, nullstr); 855 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 856 if (varflag && isassignment(argp->narg.text)) { 857 expandarg(argp, varflag == 1 ? &varlist : &arglist, 858 EXP_VARTILDE); 859 continue; 860 } else if (varflag == 1) 861 varflag = isdeclarationcmd(&argp->narg) ? 2 : 0; 862 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 863 } 864 appendarglist(&arglist, nullstr); 865 expredir(cmd->ncmd.redirect); 866 argc = arglist.count - 2; 867 argv = &arglist.args[1]; 868 869 argv[argc] = NULL; 870 lastarg = NULL; 871 if (iflag && funcnest == 0 && argc > 0) 872 lastarg = argv[argc - 1]; 873 874 /* Print the command if xflag is set. */ 875 if (xflag) 876 xtracecommand(&varlist, argc, argv); 877 878 /* Now locate the command. */ 879 if (argc == 0) { 880 /* Variable assignment(s) without command */ 881 cmdentry.cmdtype = CMDBUILTIN; 882 cmdentry.u.index = BLTINCMD; 883 cmdentry.special = 0; 884 } else { 885 static const char PATH[] = "PATH="; 886 int cmd_flags = 0, bltinonly = 0; 887 888 /* 889 * Modify the command lookup path, if a PATH= assignment 890 * is present 891 */ 892 for (i = 0; i < varlist.count; i++) 893 if (strncmp(varlist.args[i], PATH, sizeof(PATH) - 1) == 0) { 894 path = varlist.args[i] + sizeof(PATH) - 1; 895 /* 896 * On `PATH=... command`, we need to make 897 * sure that the command isn't using the 898 * non-updated hash table of the outer PATH 899 * setting and we need to make sure that 900 * the hash table isn't filled with items 901 * from the temporary setting. 902 * 903 * It would be better to forbit using and 904 * updating the table while this command 905 * runs, by the command finding mechanism 906 * is heavily integrated with hash handling, 907 * so we just delete the hash before and after 908 * the command runs. Partly deleting like 909 * changepatch() does doesn't seem worth the 910 * bookinging effort, since most such runs add 911 * directories in front of the new PATH. 912 */ 913 clearcmdentry(); 914 do_clearcmdentry = 1; 915 } 916 917 for (;;) { 918 if (bltinonly) { 919 cmdentry.u.index = find_builtin(*argv, &cmdentry.special); 920 if (cmdentry.u.index < 0) { 921 cmdentry.u.index = BLTINCMD; 922 argv--; 923 argc++; 924 break; 925 } 926 } else 927 find_command(argv[0], &cmdentry, cmd_flags, path); 928 /* implement the bltin and command builtins here */ 929 if (cmdentry.cmdtype != CMDBUILTIN) 930 break; 931 if (cmdentry.u.index == BLTINCMD) { 932 if (argc == 1) 933 break; 934 argv++; 935 argc--; 936 bltinonly = 1; 937 } else if (cmdentry.u.index == COMMANDCMD) { 938 if (argc == 1) 939 break; 940 if (!strcmp(argv[1], "-p")) { 941 if (argc == 2) 942 break; 943 if (argv[2][0] == '-') { 944 if (strcmp(argv[2], "--")) 945 break; 946 if (argc == 3) 947 break; 948 argv += 3; 949 argc -= 3; 950 } else { 951 argv += 2; 952 argc -= 2; 953 } 954 path = _PATH_STDPATH; 955 clearcmdentry(); 956 do_clearcmdentry = 1; 957 } else if (!strcmp(argv[1], "--")) { 958 if (argc == 2) 959 break; 960 argv += 2; 961 argc -= 2; 962 } else if (argv[1][0] == '-') 963 break; 964 else { 965 argv++; 966 argc--; 967 } 968 cmd_flags |= DO_NOFUNC; 969 bltinonly = 0; 970 } else 971 break; 972 } 973 /* 974 * Special builtins lose their special properties when 975 * called via 'command'. 976 */ 977 if (cmd_flags & DO_NOFUNC) 978 cmdentry.special = 0; 979 } 980 981 /* Fork off a child process if necessary. */ 982 if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) 983 && ((flags & EV_EXIT) == 0 || have_traps())) 984 || ((flags & EV_BACKCMD) != 0 985 && (cmdentry.cmdtype != CMDBUILTIN || 986 !safe_builtin(cmdentry.u.index, argc, argv)))) { 987 jp = makejob(cmd, 1); 988 mode = FORK_FG; 989 if (flags & EV_BACKCMD) { 990 mode = FORK_NOJOB; 991 if (pipe(pip) < 0) 992 error("Pipe call failed: %s", strerror(errno)); 993 } 994 if (cmdentry.cmdtype == CMDNORMAL && 995 cmd->ncmd.redirect == NULL && 996 varlist.count == 0 && 997 (mode == FORK_FG || mode == FORK_NOJOB) && 998 !disvforkset() && !iflag && !mflag) { 999 vforkexecshell(jp, argv, environment(), path, 1000 cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); 1001 goto parent; 1002 } 1003 if (forkshell(jp, cmd, mode) != 0) 1004 goto parent; /* at end of routine */ 1005 if (flags & EV_BACKCMD) { 1006 FORCEINTON; 1007 close(pip[0]); 1008 if (pip[1] != 1) { 1009 dup2(pip[1], 1); 1010 close(pip[1]); 1011 } 1012 flags &= ~EV_BACKCMD; 1013 } 1014 flags |= EV_EXIT; 1015 } 1016 1017 /* This is the child process if a fork occurred. */ 1018 /* Execute the command. */ 1019 if (cmdentry.cmdtype == CMDFUNCTION) { 1020 #ifdef DEBUG 1021 trputs("Shell function: "); trargs(argv); 1022 #endif 1023 saveparam = shellparam; 1024 shellparam.malloc = 0; 1025 shellparam.reset = 1; 1026 shellparam.nparam = argc - 1; 1027 shellparam.p = argv + 1; 1028 shellparam.optp = NULL; 1029 shellparam.optnext = NULL; 1030 INTOFF; 1031 savelocalvars = localvars; 1032 localvars = NULL; 1033 reffunc(cmdentry.u.func); 1034 savehandler = handler; 1035 if (setjmp(jmploc.loc)) { 1036 popredir(); 1037 unreffunc(cmdentry.u.func); 1038 poplocalvars(); 1039 localvars = savelocalvars; 1040 freeparam(&shellparam); 1041 shellparam = saveparam; 1042 funcnest--; 1043 handler = savehandler; 1044 longjmp(handler->loc, 1); 1045 } 1046 handler = &jmploc; 1047 funcnest++; 1048 redirect(cmd->ncmd.redirect, REDIR_PUSH); 1049 INTON; 1050 for (i = 0; i < varlist.count; i++) 1051 mklocal(varlist.args[i]); 1052 exitstatus = oexitstatus; 1053 evaltree(getfuncnode(cmdentry.u.func), 1054 flags & (EV_TESTED | EV_EXIT)); 1055 INTOFF; 1056 unreffunc(cmdentry.u.func); 1057 poplocalvars(); 1058 localvars = savelocalvars; 1059 freeparam(&shellparam); 1060 shellparam = saveparam; 1061 handler = savehandler; 1062 funcnest--; 1063 popredir(); 1064 INTON; 1065 if (evalskip == SKIPRETURN) { 1066 evalskip = 0; 1067 skipcount = 0; 1068 } 1069 if (jp) 1070 exitshell(exitstatus); 1071 } else if (cmdentry.cmdtype == CMDBUILTIN) { 1072 #ifdef DEBUG 1073 trputs("builtin command: "); trargs(argv); 1074 #endif 1075 mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; 1076 if (flags == EV_BACKCMD) { 1077 memout.nextc = memout.buf; 1078 mode |= REDIR_BACKQ; 1079 } 1080 savecmdname = commandname; 1081 savetopfile = getcurrentfile(); 1082 cmdenviron = &varlist; 1083 e = -1; 1084 savehandler = handler; 1085 if (setjmp(jmploc.loc)) { 1086 e = exception; 1087 if (e == EXINT) 1088 exitstatus = SIGINT+128; 1089 goto cmddone; 1090 } 1091 handler = &jmploc; 1092 redirect(cmd->ncmd.redirect, mode); 1093 outclearerror(out1); 1094 /* 1095 * If there is no command word, redirection errors should 1096 * not be fatal but assignment errors should. 1097 */ 1098 if (argc == 0) 1099 cmdentry.special = 1; 1100 listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET); 1101 if (argc > 0) 1102 bltinsetlocale(); 1103 commandname = argv[0]; 1104 argptr = argv + 1; 1105 nextopt_optptr = NULL; /* initialize nextopt */ 1106 builtin_flags = flags; 1107 exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); 1108 flushall(); 1109 if (outiserror(out1)) { 1110 warning("write error on stdout"); 1111 if (exitstatus == 0 || exitstatus == 1) 1112 exitstatus = 2; 1113 } 1114 cmddone: 1115 if (argc > 0) 1116 bltinunsetlocale(); 1117 cmdenviron = NULL; 1118 out1 = &output; 1119 out2 = &errout; 1120 freestdout(); 1121 handler = savehandler; 1122 commandname = savecmdname; 1123 if (jp) 1124 exitshell(exitstatus); 1125 if (flags == EV_BACKCMD) { 1126 backcmd->buf = memout.buf; 1127 backcmd->nleft = memout.buf != NULL ? 1128 memout.nextc - memout.buf : 0; 1129 memout.buf = NULL; 1130 memout.nextc = NULL; 1131 memout.bufend = NULL; 1132 memout.bufsize = 64; 1133 } 1134 if (cmdentry.u.index != EXECCMD) 1135 popredir(); 1136 if (e != -1) { 1137 if (e != EXERROR || cmdentry.special) 1138 exraise(e); 1139 popfilesupto(savetopfile); 1140 if (flags != EV_BACKCMD) 1141 FORCEINTON; 1142 } 1143 } else { 1144 #ifdef DEBUG 1145 trputs("normal command: "); trargs(argv); 1146 #endif 1147 redirect(cmd->ncmd.redirect, 0); 1148 for (i = 0; i < varlist.count; i++) 1149 setvareq(varlist.args[i], VEXPORT|VSTACK); 1150 envp = environment(); 1151 shellexec(argv, envp, path, cmdentry.u.index); 1152 /*NOTREACHED*/ 1153 } 1154 goto out; 1155 1156 parent: /* parent process gets here (if we forked) */ 1157 if (mode == FORK_FG) { /* argument to fork */ 1158 INTOFF; 1159 exitstatus = waitforjob(jp, &signaled); 1160 INTON; 1161 if (iflag && loopnest > 0 && signaled) { 1162 evalskip = SKIPBREAK; 1163 skipcount = loopnest; 1164 } 1165 } else if (mode == FORK_NOJOB) { 1166 backcmd->fd = pip[0]; 1167 close(pip[1]); 1168 backcmd->jp = jp; 1169 } 1170 1171 out: 1172 if (lastarg) 1173 setvar("_", lastarg, 0); 1174 if (do_clearcmdentry) 1175 clearcmdentry(); 1176 } 1177 1178 1179 1180 /* 1181 * Search for a command. This is called before we fork so that the 1182 * location of the command will be available in the parent as well as 1183 * the child. The check for "goodname" is an overly conservative 1184 * check that the name will not be subject to expansion. 1185 */ 1186 1187 static void 1188 prehash(union node *n) 1189 { 1190 struct cmdentry entry; 1191 1192 if (n && n->type == NCMD && n->ncmd.args) 1193 if (goodname(n->ncmd.args->narg.text)) 1194 find_command(n->ncmd.args->narg.text, &entry, 0, 1195 pathval()); 1196 } 1197 1198 1199 1200 /* 1201 * Builtin commands. Builtin commands whose functions are closely 1202 * tied to evaluation are implemented here. 1203 */ 1204 1205 /* 1206 * No command given, a bltin command with no arguments, or a bltin command 1207 * with an invalid name. 1208 */ 1209 1210 int 1211 bltincmd(int argc, char **argv) 1212 { 1213 if (argc > 1) { 1214 out2fmt_flush("%s: not found\n", argv[1]); 1215 return 127; 1216 } 1217 /* 1218 * Preserve exitstatus of a previous possible command substitution 1219 * as POSIX mandates 1220 */ 1221 return exitstatus; 1222 } 1223 1224 1225 /* 1226 * Handle break and continue commands. Break, continue, and return are 1227 * all handled by setting the evalskip flag. The evaluation routines 1228 * above all check this flag, and if it is set they start skipping 1229 * commands rather than executing them. The variable skipcount is 1230 * the number of loops to break/continue, or the number of function 1231 * levels to return. (The latter is always 1.) It should probably 1232 * be an error to break out of more loops than exist, but it isn't 1233 * in the standard shell so we don't make it one here. 1234 */ 1235 1236 int 1237 breakcmd(int argc, char **argv) 1238 { 1239 long n; 1240 char *end; 1241 1242 if (argc > 1) { 1243 /* Allow arbitrarily large numbers. */ 1244 n = strtol(argv[1], &end, 10); 1245 if (!is_digit(argv[1][0]) || *end != '\0') 1246 error("Illegal number: %s", argv[1]); 1247 } else 1248 n = 1; 1249 if (n > loopnest) 1250 n = loopnest; 1251 if (n > 0) { 1252 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; 1253 skipcount = n; 1254 } 1255 return 0; 1256 } 1257 1258 /* 1259 * The `command' command. 1260 */ 1261 int 1262 commandcmd(int argc __unused, char **argv __unused) 1263 { 1264 const char *path; 1265 int ch; 1266 int cmd = -1; 1267 1268 path = bltinlookup("PATH", 1); 1269 1270 while ((ch = nextopt("pvV")) != '\0') { 1271 switch (ch) { 1272 case 'p': 1273 path = _PATH_STDPATH; 1274 break; 1275 case 'v': 1276 cmd = TYPECMD_SMALLV; 1277 break; 1278 case 'V': 1279 cmd = TYPECMD_BIGV; 1280 break; 1281 } 1282 } 1283 1284 if (cmd != -1) { 1285 if (*argptr == NULL || argptr[1] != NULL) 1286 error("wrong number of arguments"); 1287 return typecmd_impl(2, argptr - 1, cmd, path); 1288 } 1289 if (*argptr != NULL) 1290 error("commandcmd bad call"); 1291 1292 /* 1293 * Do nothing successfully if no command was specified; 1294 * ksh also does this. 1295 */ 1296 return 0; 1297 } 1298 1299 1300 /* 1301 * The return command. 1302 */ 1303 1304 int 1305 returncmd(int argc, char **argv) 1306 { 1307 int ret = argc > 1 ? number(argv[1]) : oexitstatus; 1308 1309 evalskip = SKIPRETURN; 1310 skipcount = 1; 1311 return ret; 1312 } 1313 1314 1315 int 1316 falsecmd(int argc __unused, char **argv __unused) 1317 { 1318 return 1; 1319 } 1320 1321 1322 int 1323 truecmd(int argc __unused, char **argv __unused) 1324 { 1325 return 0; 1326 } 1327 1328 1329 int 1330 execcmd(int argc, char **argv) 1331 { 1332 int i; 1333 1334 /* 1335 * Because we have historically not supported any options, 1336 * only treat "--" specially. 1337 */ 1338 if (argc > 1 && strcmp(argv[1], "--") == 0) 1339 argc--, argv++; 1340 if (argc > 1) { 1341 iflag = 0; /* exit on error */ 1342 mflag = 0; 1343 optschanged(); 1344 for (i = 0; i < cmdenviron->count; i++) 1345 setvareq(cmdenviron->args[i], VEXPORT|VSTACK); 1346 shellexec(argv + 1, environment(), pathval(), 0); 1347 1348 } 1349 return 0; 1350 } 1351 1352 1353 int 1354 timescmd(int argc __unused, char **argv __unused) 1355 { 1356 struct rusage ru; 1357 long shumins, shsmins, chumins, chsmins; 1358 double shusecs, shssecs, chusecs, chssecs; 1359 1360 if (getrusage(RUSAGE_SELF, &ru) < 0) 1361 return 1; 1362 shumins = ru.ru_utime.tv_sec / 60; 1363 shusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; 1364 shsmins = ru.ru_stime.tv_sec / 60; 1365 shssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; 1366 if (getrusage(RUSAGE_CHILDREN, &ru) < 0) 1367 return 1; 1368 chumins = ru.ru_utime.tv_sec / 60; 1369 chusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.; 1370 chsmins = ru.ru_stime.tv_sec / 60; 1371 chssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.; 1372 out1fmt("%ldm%.3fs %ldm%.3fs\n%ldm%.3fs %ldm%.3fs\n", shumins, 1373 shusecs, shsmins, shssecs, chumins, chusecs, chsmins, chssecs); 1374 return 0; 1375 } 1376