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