1 /* $NetBSD: eval.c,v 1.201 2026/08/23 10:26:45 nia Exp $ */ 2 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 <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; 39 #else 40 __RCSID("$NetBSD: eval.c,v 1.201 2026/08/23 10:26:45 nia Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <stdbool.h> 45 #include <stdlib.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <string.h> 49 #include <errno.h> 50 #include <limits.h> 51 #include <unistd.h> 52 #include <fcntl.h> 53 #include <sys/stat.h> 54 #include <sys/times.h> 55 #include <sys/param.h> 56 #include <sys/types.h> 57 #include <sys/wait.h> 58 #include <sys/sysctl.h> 59 60 /* 61 * Evaluate a command. 62 */ 63 64 #include "shell.h" 65 #include "nodes.h" 66 #include "syntax.h" 67 #include "expand.h" 68 #include "parser.h" 69 #include "jobs.h" 70 #include "eval.h" 71 #include "builtins.h" 72 #include "options.h" 73 #include "exec.h" 74 #include "redir.h" 75 #include "input.h" 76 #include "output.h" 77 #include "trap.h" 78 #include "var.h" 79 #include "memalloc.h" 80 #include "error.h" 81 #include "show.h" 82 #include "mystring.h" 83 #include "main.h" 84 #ifndef SMALL 85 #include "nodenames.h" 86 #include "myhistedit.h" 87 #endif 88 89 90 STATIC struct skipsave s_k_i_p; 91 #define evalskip (s_k_i_p.state) 92 #define skipcount (s_k_i_p.count) 93 94 STATIC int loopnest; /* current loop nesting level */ 95 STATIC int funcnest; /* depth of function calls */ 96 STATIC int builtin_flags; /* evalcommand flags for builtins */ 97 /* 98 * Base function nesting level inside a dot command. Set to 0 initially 99 * and to (funcnest + 1) before every dot command to enable 100 * 1) detection of being in a file sourced by a dot command and 101 * 2) counting of function nesting in that file for the implementation 102 * of the return command. 103 * The value is reset to its previous value after the dot command. 104 */ 105 STATIC int dot_funcnest; 106 107 108 const char *commandname; 109 struct strlist *cmdenviron; 110 int exitstatus; /* exit status of last command */ 111 int back_exitstatus; /* exit status of backquoted command */ 112 113 114 STATIC void evalloop(union node *, int); 115 STATIC void evalfor(union node *, int); 116 STATIC void evalcase(union node *, int); 117 STATIC void evalsubshell(union node *, int); 118 STATIC void expredir(union node *); 119 STATIC void evalredir(union node *, int); 120 STATIC void evalpipe(union node *); 121 STATIC void evalcommand(union node *, int, struct backcmd *); 122 STATIC void prehash(union node *); 123 124 STATIC char *find_dot_file(char *); 125 126 /* 127 * Called to reset things after an exception. 128 */ 129 130 #ifdef mkinit 131 INCLUDE "eval.h" 132 133 RESET { 134 reset_eval(); 135 } 136 137 SHELLPROC { 138 exitstatus = 0; 139 } 140 #endif 141 142 void 143 reset_eval(void) 144 { 145 evalskip = SKIPNONE; 146 dot_funcnest = 0; 147 loopnest = 0; 148 funcnest = 0; 149 } 150 151 static int 152 sh_pipe(int fds[2]) 153 { 154 int nfd; 155 156 if (pipe(fds)) 157 return -1; 158 159 if (fds[0] < 3) { 160 nfd = fcntl(fds[0], F_DUPFD, 3); 161 if (nfd != -1) { 162 close(fds[0]); 163 fds[0] = nfd; 164 } 165 } 166 167 if (fds[1] < 3) { 168 nfd = fcntl(fds[1], F_DUPFD, 3); 169 if (nfd != -1) { 170 close(fds[1]); 171 fds[1] = nfd; 172 } 173 } 174 return 0; 175 } 176 177 178 /* 179 * The eval command. 180 */ 181 182 int 183 evalcmd(int argc, char **argv) 184 { 185 char *p; 186 char *concat; 187 char **ap; 188 189 if (argc > 1) { 190 p = argv[1]; 191 if (argc > 2) { 192 STARTSTACKSTR(concat); 193 ap = argv + 2; 194 for (;;) { 195 while (*p) 196 STPUTC(*p++, concat); 197 if ((p = *ap++) == NULL) 198 break; 199 STPUTC(' ', concat); 200 } 201 STPUTC('\0', concat); 202 p = grabstackstr(concat); 203 } 204 evalstring(p, builtin_flags & EV_TESTED); 205 } else 206 exitstatus = 0; 207 return exitstatus; 208 } 209 210 211 /* 212 * Execute a command or commands contained in a string. 213 */ 214 215 void 216 evalstring(const char *s, int flag) 217 { 218 union node *n; 219 struct stackmark smark; 220 int last; 221 int any; 222 223 last = flag & EV_EXIT; 224 flag &= ~EV_EXIT; 225 226 setstackmark(&smark); 227 setinputstring(s, 1, line_number); 228 229 any = 0; /* to determine if exitstatus will have been set */ 230 while ((n = parsecmd(0)) != NEOF) { 231 XTRACE(DBG_EVAL, ("evalstring: "), showtree(n)); 232 if (n && nflag == 0) { 233 if (last && at_eof()) 234 evaltree(n, flag | EV_EXIT); 235 else 236 evaltree(n, flag); 237 any = 1; 238 if (evalskip) 239 break; 240 } 241 rststackmark(&smark); 242 } 243 popfile(); 244 popstackmark(&smark); 245 if (!any) 246 exitstatus = 0; 247 if (last) 248 exraise(EXEXIT); 249 } 250 251 252 253 /* 254 * Evaluate a parse tree. The value is left in the global variable 255 * exitstatus. 256 */ 257 258 void 259 evaltree(union node *n, int flags) 260 { 261 bool do_etest; 262 int sflags = flags & ~EV_EXIT; 263 union node *next; 264 struct stackmark smark; 265 266 do_etest = false; 267 if (n == NULL || nflag) { 268 VTRACE(DBG_EVAL, ("evaltree(%s) called\n", 269 n == NULL ? "NULL" : "-n")); 270 if (nflag == 0) 271 exitstatus = 0; 272 goto out2; 273 } 274 275 setstackmark(&smark); 276 do { 277 #ifndef SMALL 278 displayhist = 1; /* show history substitutions done with fc */ 279 #endif 280 next = NULL; 281 CTRACE(DBG_EVAL, ("pid %d, evaltree(%p: %s(%d), %#x) called\n", 282 getpid(), n, NODETYPENAME(n->type), n->type, flags)); 283 /* 284 if (n->type != NCMD && traps_invalid) 285 free_traps(); 286 */ 287 switch (n->type) { 288 case NSEMI: 289 evaltree(n->nbinary.ch1, sflags); 290 if (nflag || evalskip) 291 goto out1; 292 next = n->nbinary.ch2; 293 break; 294 case NAND: 295 evaltree(n->nbinary.ch1, EV_TESTED); 296 if (nflag || evalskip || exitstatus != 0) 297 goto out1; 298 next = n->nbinary.ch2; 299 break; 300 case NOR: 301 evaltree(n->nbinary.ch1, EV_TESTED); 302 if (nflag || evalskip || exitstatus == 0) 303 goto out1; 304 next = n->nbinary.ch2; 305 break; 306 case NREDIR: 307 if (traps_invalid) 308 free_traps(); 309 evalredir(n, flags); 310 break; 311 case NSUBSHELL: 312 evalsubshell(n, flags); 313 do_etest = !(flags & EV_TESTED); 314 break; 315 case NBACKGND: 316 if (traps_invalid) 317 free_traps(); 318 evalsubshell(n, flags); 319 break; 320 case NIF: { 321 if (traps_invalid) 322 free_traps(); 323 evaltree(n->nif.test, EV_TESTED); 324 if (nflag || evalskip) 325 goto out1; 326 if (exitstatus == 0) 327 next = n->nif.ifpart; 328 else if (n->nif.elsepart) 329 next = n->nif.elsepart; 330 else 331 exitstatus = 0; 332 break; 333 } 334 case NWHILE: 335 case NUNTIL: 336 if (traps_invalid) 337 free_traps(); 338 evalloop(n, sflags); 339 break; 340 case NFOR: 341 if (traps_invalid) 342 free_traps(); 343 evalfor(n, sflags); 344 break; 345 case NCASE: 346 if (traps_invalid) 347 free_traps(); 348 evalcase(n, sflags); 349 break; 350 case NDEFUN: 351 if (traps_invalid) 352 free_traps(); 353 CTRACE(DBG_EVAL, ("Defining fn %s @%d%s\n", 354 n->narg.text, n->narg.lineno, 355 fnline1 ? " LINENO=1" : "")); 356 defun(n->narg.text, n->narg.next, n->narg.lineno); 357 exitstatus = 0; 358 break; 359 case NNOT: 360 evaltree(n->nnot.com, EV_TESTED); 361 exitstatus = !exitstatus; 362 break; 363 case NDNOT: 364 evaltree(n->nnot.com, EV_TESTED); 365 if (exitstatus != 0) 366 exitstatus = 1; 367 break; 368 case NPIPE: 369 if (traps_invalid) 370 free_traps(); 371 evalpipe(n); 372 do_etest = !(flags & EV_TESTED); 373 break; 374 case NCMD: 375 evalcommand(n, flags, NULL); 376 do_etest = !(flags & EV_TESTED); 377 break; 378 default: 379 #ifdef NODETYPENAME 380 out1fmt("Node type = %d(%s)\n", 381 n->type, NODETYPENAME(n->type)); 382 #else 383 out1fmt("Node type = %d\n", n->type); 384 #endif 385 flushout(&output); 386 break; 387 } 388 n = next; 389 rststackmark(&smark); 390 } while(n != NULL); 391 out1: 392 popstackmark(&smark); 393 out2: 394 if (pendingsigs) 395 dotrap(); 396 if (eflag && exitstatus != 0 && do_etest) 397 exitshell(exitstatus); 398 if (flags & EV_EXIT) 399 exraise(EXEXIT); 400 } 401 402 403 STATIC void 404 evalloop(union node *n, int flags) 405 { 406 int status; 407 408 loopnest++; 409 status = 0; 410 411 CTRACE(DBG_EVAL, ("evalloop %s:", NODETYPENAME(n->type))); 412 VXTRACE(DBG_EVAL, (" "), showtree(n->nbinary.ch1)); 413 VXTRACE(DBG_EVAL, ("evalloop do: "), showtree(n->nbinary.ch2)); 414 VTRACE(DBG_EVAL, ("evalloop done\n")); 415 CTRACE(DBG_EVAL, ("\n")); 416 417 for (;;) { 418 evaltree(n->nbinary.ch1, EV_TESTED); 419 if (nflag) 420 break; 421 if (evalskip) { 422 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 423 evalskip = SKIPNONE; 424 continue; 425 } 426 if (evalskip == SKIPBREAK && --skipcount <= 0) 427 evalskip = SKIPNONE; 428 if (evalskip == SKIPFUNC || evalskip == SKIPFILE) 429 status = exitstatus; 430 break; 431 } 432 if (n->type == NWHILE) { 433 if (exitstatus != 0) 434 break; 435 } else { 436 if (exitstatus == 0) 437 break; 438 } 439 evaltree(n->nbinary.ch2, flags & EV_TESTED); 440 status = exitstatus; 441 if (evalskip) 442 goto skipping; 443 } 444 loopnest--; 445 exitstatus = status; 446 } 447 448 449 450 STATIC void 451 evalfor(union node *n, int flags) 452 { 453 struct arglist arglist; 454 union node *argp; 455 struct strlist *sp; 456 struct stackmark smark; 457 int status; 458 459 status = nflag ? exitstatus : 0; 460 461 setstackmark(&smark); 462 arglist.lastp = &arglist.list; 463 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { 464 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 465 if (evalskip) 466 goto out; 467 } 468 *arglist.lastp = NULL; 469 470 loopnest++; 471 for (sp = arglist.list ; sp ; sp = sp->next) { 472 line_number = n->nfor.lineno; 473 if (xflag) { 474 outxstr(expandstr(ps4val(), line_number)); 475 outxstr("for "); 476 outxstr(n->nfor.var); 477 outxc('='); 478 outxshstr(sp->text); 479 outxc('\n'); 480 flushout(outx); 481 } 482 483 setvar(n->nfor.var, sp->text, 0); 484 evaltree(n->nfor.body, flags & EV_TESTED); 485 status = exitstatus; 486 if (nflag) 487 break; 488 if (evalskip) { 489 if (evalskip == SKIPCONT && --skipcount <= 0) { 490 evalskip = SKIPNONE; 491 continue; 492 } 493 if (evalskip == SKIPBREAK && --skipcount <= 0) 494 evalskip = SKIPNONE; 495 break; 496 } 497 } 498 loopnest--; 499 exitstatus = status; 500 out: 501 popstackmark(&smark); 502 } 503 504 505 506 STATIC void 507 evalcase(union node *n, int flags) 508 { 509 union node *cp, *ncp; 510 union node *patp; 511 struct arglist arglist; 512 struct stackmark smark; 513 int status = 0; 514 515 setstackmark(&smark); 516 arglist.lastp = &arglist.list; 517 line_number = n->ncase.lineno; 518 expandarg(n->ncase.expr, &arglist, EXP_TILDE); 519 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) { 520 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) { 521 line_number = patp->narg.lineno; 522 if (casematch(patp, arglist.list->text)) { 523 while (cp != NULL && evalskip == 0 && 524 nflag == 0) { 525 if (cp->type == NCLISTCONT) 526 ncp = cp->nclist.next; 527 else 528 ncp = NULL; 529 line_number = cp->nclist.lineno; 530 evaltree(cp->nclist.body, flags); 531 status = exitstatus; 532 cp = ncp; 533 } 534 goto out; 535 } 536 } 537 } 538 out: 539 exitstatus = status; 540 popstackmark(&smark); 541 } 542 543 544 545 /* 546 * Kick off a subshell to evaluate a tree. 547 */ 548 549 STATIC void 550 evalsubshell(union node *n, int flags) 551 { 552 struct job *jp= NULL; 553 int backgnd = (n->type == NBACKGND); 554 555 expredir(n->nredir.redirect); 556 if (xflag && n->nredir.redirect) { 557 union node *rn; 558 559 outxstr(expandstr(ps4val(), line_number)); 560 outxstr("using redirections:"); 561 for (rn = n->nredir.redirect; rn; rn = rn->nfile.next) 562 (void) outredir(outx, rn, ' '); 563 outxstr(" do subshell ("/*)*/); 564 if (backgnd) 565 outxstr(/*(*/") &"); 566 outxc('\n'); 567 flushout(outx); 568 } 569 INTOFF; 570 if ((!backgnd && flags & EV_EXIT && !have_traps() && !anyjobs()) || 571 forkshell(jp = makejob(n, 1), n, backgnd?FORK_BG:FORK_FG) == 0) { 572 if (backgnd) 573 flags &=~ EV_TESTED; 574 INTON; 575 redirect(n->nredir.redirect, REDIR_KEEP); 576 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 577 } else if (backgnd) { 578 jobstarted(jp); 579 exitstatus = 0; 580 } else 581 exitstatus = waitforjob(jp); 582 INTON; 583 584 if (!backgnd && xflag && n->nredir.redirect) { 585 outxstr(expandstr(ps4val(), line_number)); 586 outxstr(/*(*/") done subshell\n"); 587 flushout(outx); 588 } 589 } 590 591 592 593 /* 594 * Compute the names of the files in a redirection list. 595 */ 596 597 STATIC void 598 expredir(union node *n) 599 { 600 union node *redir; 601 602 for (redir = n ; redir ; redir = redir->nfile.next) { 603 struct arglist fn; 604 605 fn.lastp = &fn.list; 606 switch (redir->type) { 607 case NFROMTO: 608 case NFROM: 609 case NTO: 610 case NCLOBBER: 611 case NAPPEND: 612 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 613 redir->nfile.expfname = fn.list->text; 614 break; 615 case NFROMFD: 616 case NTOFD: 617 if (redir->ndup.vname) { 618 expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR); 619 fixredir(redir, fn.list->text, 1); 620 } 621 break; 622 case NHERE: 623 redir->nhere.text = redir->nhere.doc->narg.text; 624 break; 625 case NXHERE: 626 redir->nhere.text = expandhere(redir->nhere.doc); 627 break; 628 } 629 } 630 } 631 632 /* 633 * Perform redirections for a compound command, and then do it (and restore) 634 */ 635 STATIC void 636 evalredir(union node *n, int flags) 637 { 638 struct jmploc jmploc; 639 struct jmploc * const savehandler = handler; 640 volatile int in_redirect = 1; 641 const char * volatile PS4 = NULL; 642 643 expredir(n->nredir.redirect); 644 645 if (xflag && n->nredir.redirect) { 646 union node *rn; 647 648 outxstr(PS4 = expandstr(ps4val(), line_number)); 649 outxstr("using redirections:"); 650 for (rn = n->nredir.redirect; rn != NULL; rn = rn->nfile.next) 651 (void) outredir(outx, rn, ' '); 652 outxstr(" do {\n"); /* } */ 653 flushout(outx); 654 } 655 656 if (setjmp(jmploc.loc)) { 657 int e; 658 659 handler = savehandler; 660 e = exception; 661 popredir(POPREDIR_UNDO); 662 if (PS4 != NULL) { 663 outxstr(PS4); 664 /* { */ outxstr("} failed\n"); 665 flushout(outx); 666 } 667 if (e == EXERROR || e == EXEXEC) { 668 if (in_redirect) { 669 exitstatus = 2; 670 return; 671 } 672 } 673 longjmp(handler->loc, 1); 674 } else { 675 INTOFF; 676 handler = &jmploc; 677 redirect(n->nredir.redirect, REDIR_PUSH | REDIR_KEEP); 678 in_redirect = 0; 679 INTON; 680 evaltree(n->nredir.n, flags); 681 } 682 INTOFF; 683 handler = savehandler; 684 popredir(POPREDIR_UNDO); 685 INTON; 686 687 if (PS4 != NULL) { 688 outxstr(PS4); 689 /* { */ outxstr("} done\n"); 690 flushout(outx); 691 } 692 } 693 694 695 /* 696 * Evaluate a pipeline. All the processes in the pipeline are children 697 * of the process creating the pipeline. (This differs from some versions 698 * of the shell, which make the last process in a pipeline the parent 699 * of all the rest.) 700 */ 701 702 STATIC void 703 evalpipe(union node *n) 704 { 705 struct job *jp; 706 struct nodelist *lp; 707 int pipelen; 708 int prevfd; 709 int pip[2]; 710 711 CTRACE(DBG_EVAL, ("evalpipe(%p) called\n", n)); 712 pipelen = 0; 713 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) 714 pipelen++; 715 INTOFF; 716 jp = makejob(n, pipelen); 717 prevfd = -1; 718 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 719 prehash(lp->n); 720 pip[1] = -1; 721 if (lp->next) { 722 if (sh_pipe(pip) < 0) { 723 if (prevfd >= 0) 724 close(prevfd); 725 error("Pipe call failed: %s", strerror(errno)); 726 } 727 } 728 if (forkshell(jp, lp->n, 729 n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) { 730 INTON; 731 if (prevfd > 0) 732 movefd(prevfd, 0); 733 if (pip[1] >= 0) { 734 close(pip[0]); 735 movefd(pip[1], 1); 736 } 737 evaltree(lp->n, EV_EXIT); 738 } 739 if (prevfd >= 0) 740 close(prevfd); 741 prevfd = pip[0]; 742 close(pip[1]); 743 } 744 if (n->npipe.backgnd == 0) { 745 exitstatus = waitforjob(jp); 746 CTRACE(DBG_EVAL, ("evalpipe: job done exit status %d\n", 747 exitstatus)); 748 } else { 749 jobstarted(jp); 750 exitstatus = 0; 751 } 752 INTON; 753 } 754 755 756 757 /* 758 * Execute a command inside back quotes. If it's a builtin command, we 759 * want to save its output in a block obtained from malloc. Otherwise 760 * we fork off a subprocess and get the output of the command via a pipe. 761 * Should be called with interrupts off. 762 */ 763 764 void 765 evalbackcmd(union node *n, struct backcmd *result) 766 { 767 int pip[2]; 768 struct job *jp; 769 struct stackmark smark; /* unnecessary (because we fork) */ 770 771 result->fd = -1; 772 result->buf = NULL; 773 result->nleft = 0; 774 result->jp = NULL; 775 776 if (nflag || n == NULL) 777 goto out; 778 779 setstackmark(&smark); 780 781 #ifdef notyet 782 /* 783 * For now we disable executing builtins in the same 784 * context as the shell, because we are not keeping 785 * enough state to recover from changes that are 786 * supposed only to affect subshells. eg. echo "`cd /`" 787 */ 788 if (n->type == NCMD) { 789 exitstatus = oexitstatus; /* XXX o... no longer exists */ 790 evalcommand(n, EV_BACKCMD, result); 791 } else 792 #endif 793 { 794 INTOFF; 795 if (sh_pipe(pip) < 0) 796 error("Pipe call failed"); 797 jp = makejob(n, 0); /* 0 --> leave jobs_invalid, no jobctl */ 798 if (forkshell(jp, n, FORK_NOJOB) == 0) { 799 FORCEINTON; 800 close(pip[0]); 801 movefd(pip[1], 1); 802 evaltree(n, EV_EXIT); 803 /* NOTREACHED */ 804 } 805 close(pip[1]); 806 result->fd = pip[0]; 807 result->jp = jp; 808 INTON; 809 } 810 popstackmark(&smark); 811 out: 812 CTRACE(DBG_EVAL, ("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", 813 result->fd, result->buf, result->nleft, result->jp)); 814 } 815 816 const char * 817 syspath(void) 818 { 819 static char *sys_path = NULL; 820 static int mib[] = {CTL_USER, USER_CS_PATH}; 821 static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; 822 size_t len; 823 824 if (sys_path == NULL) { 825 if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && 826 (sys_path = ckmalloc(len + 5)) != NULL && 827 sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { 828 memcpy(sys_path, "PATH=", 5); 829 } else { 830 ckfree(sys_path); 831 /* something to keep things happy */ 832 sys_path = def_path; 833 } 834 } 835 return sys_path; 836 } 837 838 static int 839 parse_command_args(int argc, char **argv, int *use_syspath) 840 { 841 int sv_argc = argc; 842 char *cp, c; 843 844 *use_syspath = 0; 845 846 for (;;) { 847 argv++; 848 if (--argc == 0) 849 break; 850 cp = *argv; 851 if (*cp++ != '-') 852 break; 853 if (*cp == '-' && cp[1] == 0) { 854 argv++; 855 argc--; 856 break; 857 } 858 while ((c = *cp++)) { 859 switch (c) { 860 case 'p': 861 *use_syspath = 1; 862 break; 863 default: 864 /* run 'typecmd' for other options */ 865 return 0; 866 } 867 } 868 } 869 return sv_argc - argc; 870 } 871 872 volatile int vforking = 0; 873 874 /* 875 * Execute a simple command. 876 */ 877 878 STATIC void 879 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd) 880 { 881 struct stackmark smark; 882 union node *argp; 883 struct arglist arglist; 884 struct arglist varlist; 885 volatile int flags = flgs; 886 char ** volatile argv; 887 volatile int argc; 888 char **envp; 889 int varflag; 890 struct strlist *sp; 891 volatile int mode; 892 int pip[2]; 893 struct cmdentry cmdentry; 894 struct job * volatile jp; 895 struct jmploc jmploc; 896 struct jmploc *volatile savehandler = NULL; 897 const char *volatile savecmdname; 898 volatile struct shparam saveparam; 899 struct localvar *volatile savelocalvars; 900 struct parsefile *volatile savetopfile; 901 volatile int e; 902 char * volatile lastarg; 903 const char * volatile path = pathval(); 904 volatile int temp_path; 905 const int savefuncline = funclinebase; 906 const int savefuncabs = funclineabs; 907 volatile int cmd_flags = 0; 908 909 vforking = 0; 910 /* First expand the arguments. */ 911 CTRACE(DBG_EVAL, ("evalcommand(%p, %d) called [%s]\n", cmd, flags, 912 cmd->ncmd.args ? cmd->ncmd.args->narg.text : "")); 913 setstackmark(&smark); 914 back_exitstatus = 0; 915 916 line_number = cmd->ncmd.lineno; 917 918 arglist.lastp = &arglist.list; 919 varflag = 1; 920 /* Expand arguments, ignoring the initial 'name=value' ones */ 921 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 922 if (varflag && isassignment(argp->narg.text)) 923 continue; 924 varflag = 0; 925 line_number = argp->narg.lineno; 926 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 927 } 928 *arglist.lastp = NULL; 929 930 expredir(cmd->ncmd.redirect); 931 932 /* Now do the initial 'name=value' ones we skipped above */ 933 varlist.lastp = &varlist.list; 934 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 935 line_number = argp->narg.lineno; 936 if (!isassignment(argp->narg.text)) 937 break; 938 /* EXP_CASE handles CTL* chars in expansions properly */ 939 expandarg(argp, &varlist, EXP_VARTILDE | EXP_CASE); 940 } 941 *varlist.lastp = NULL; 942 943 argc = 0; 944 for (sp = arglist.list ; sp ; sp = sp->next) 945 argc++; 946 argv = stalloc(sizeof (char *) * (argc + 1)); 947 948 for (sp = arglist.list ; sp ; sp = sp->next) { 949 VTRACE(DBG_EVAL, ("evalcommand arg: %s\n", sp->text)); 950 *argv++ = sp->text; 951 } 952 *argv = NULL; 953 lastarg = NULL; 954 if (iflag && funcnest == 0 && argc > 0) 955 lastarg = argv[-1]; 956 argv -= argc; 957 958 /* Print the command if xflag is set. */ 959 if (xflag) { 960 char sep = 0; 961 union node *rn; 962 963 outxstr(expandstr(ps4val(), line_number)); 964 for (sp = varlist.list ; sp ; sp = sp->next) { 965 char *p; 966 967 if (sep != 0) 968 outxc(sep); 969 970 /* 971 * The "var=" part should not be quoted, regardless 972 * of the value, or it would not represent an 973 * assignment, but rather a command 974 */ 975 p = strchr(sp->text, '='); 976 if (p != NULL) { 977 *p = '\0'; /*XXX*/ 978 outxshstr(sp->text); 979 outxc('='); 980 *p++ = '='; /*XXX*/ 981 } else 982 p = sp->text; 983 outxshstr(p); 984 sep = ' '; 985 } 986 for (sp = arglist.list ; sp ; sp = sp->next) { 987 if (sep != 0) 988 outxc(sep); 989 outxshstr(sp->text); 990 sep = ' '; 991 } 992 for (rn = cmd->ncmd.redirect; rn; rn = rn->nfile.next) 993 if (outredir(outx, rn, sep)) 994 sep = ' '; 995 outxc('\n'); 996 flushout(outx); 997 } 998 999 /* Now locate the command. */ 1000 if (argc == 0) { 1001 /* 1002 * the empty command begins as a normal builtin, and 1003 * remains that way while redirects are processed, then 1004 * will become special before we get to doing the 1005 * var assigns. 1006 */ 1007 cmdentry.cmdtype = CMDBUILTIN; 1008 cmdentry.u.bltin = bltincmd; 1009 VTRACE(DBG_CMDS, ("No command name, assume \"command\"\n")); 1010 } else { 1011 static const char PATH[] = "PATH="; 1012 1013 /* 1014 * Modify the command lookup path, if a PATH= assignment 1015 * is present 1016 */ 1017 for (sp = varlist.list; sp; sp = sp->next) 1018 if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) 1019 path = sp->text + sizeof(PATH) - 1; 1020 1021 do { 1022 int argsused, use_syspath; 1023 1024 find_command(argv[0], &cmdentry, cmd_flags, path); 1025 VTRACE(DBG_CMDS, ("Command %s type %d\n", argv[0], 1026 cmdentry.cmdtype)); 1027 #if 0 1028 /* 1029 * This short circuits all of the processing that 1030 * should be done (including processing the 1031 * redirects), so just don't ... 1032 * 1033 * (eventually this whole #if'd block will vanish) 1034 */ 1035 if (cmdentry.cmdtype == CMDUNKNOWN) { 1036 exitstatus = 127; 1037 flushout(&errout); 1038 goto out; 1039 } 1040 #endif 1041 1042 /* implement the 'command' builtin here */ 1043 if (cmdentry.cmdtype != CMDBUILTIN || 1044 cmdentry.u.bltin != bltincmd) 1045 break; 1046 VTRACE(DBG_CMDS, ("Command \"command\"\n")); 1047 cmd_flags |= DO_NOFUNC; 1048 argsused = parse_command_args(argc, argv, &use_syspath); 1049 if (argsused == 0) { 1050 /* use 'type' builtin to display info */ 1051 VTRACE(DBG_CMDS, 1052 ("Command \"command\" -> \"type\"\n")); 1053 cmdentry.u.bltin = typecmd; 1054 break; 1055 } 1056 argc -= argsused; 1057 argv += argsused; 1058 if (use_syspath) 1059 path = syspath() + 5; 1060 } while (argc != 0); 1061 if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC) 1062 /* posix mandates that 'command <splbltin>' act as if 1063 <splbltin> was a normal builtin */ 1064 cmdentry.cmdtype = CMDBUILTIN; 1065 } 1066 1067 /* 1068 * When traps are invalid, we permit the following: 1069 * trap 1070 * command trap 1071 * eval trap 1072 * command eval trap 1073 * eval command trap 1074 * without zapping the traps completely, in all other cases we do. 1075 * Function calls also do not zap the traps (but commands they execute 1076 * probably will) - this allows a function like 1077 * trapstate() { trap -p; } 1078 * called as save_traps=$(trapstate). 1079 * 1080 * The test here permits eval "anything" but when evalstring() comes 1081 * back here again, the "anything" will be validated. 1082 * This means we can actually do: 1083 * eval eval eval command eval eval command trap 1084 * as long as we end up with just "trap" 1085 * 1086 * We permit "command" by allowing CMDBUILTIN as well as CMDSPLBLTIN 1087 * 1088 * trapcmd() takes care of doing free_traps() if it is needed there. 1089 */ 1090 if (traps_invalid && 1091 cmdentry.cmdtype != CMDFUNCTION && 1092 ((cmdentry.cmdtype!=CMDSPLBLTIN && cmdentry.cmdtype!=CMDBUILTIN) || 1093 (cmdentry.u.bltin != trapcmd && cmdentry.u.bltin != evalcmd))) 1094 free_traps(); 1095 1096 /* Fork off a child process if necessary. */ 1097 if (cmd->ncmd.backgnd 1098 || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) 1099 && (have_traps() || (flags & EV_EXIT) == 0)) 1100 #ifdef notyet /* EV_BACKCMD is never set currently */ 1101 /* this will need more work if/when it gets used */ 1102 || ((flags & EV_BACKCMD) != 0 1103 && (cmdentry.cmdtype != CMDBUILTIN 1104 && cmdentry.cmdtype != CMDSPLBLTIN) 1105 || cmdentry.u.bltin == dotcmd 1106 || cmdentry.u.bltin == evalcmd) 1107 #endif 1108 ) { 1109 INTOFF; 1110 jp = makejob(cmd, 1); 1111 mode = cmd->ncmd.backgnd; 1112 if (flags & EV_BACKCMD) { 1113 mode = FORK_NOJOB; 1114 if (sh_pipe(pip) < 0) 1115 error("Pipe call failed"); 1116 } 1117 #ifdef DO_SHAREDVFORK 1118 /* It is essential that if DO_SHAREDVFORK is defined that the 1119 * child's address space is actually shared with the parent as 1120 * we rely on this. 1121 */ 1122 if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL && 1123 (!cmd->ncmd.backgnd || cmd->ncmd.redirect == NULL)) { 1124 pid_t pid; 1125 int serrno; 1126 sigset_t block_all, olds; 1127 1128 (void)sigfillset(&block_all); 1129 savelocalvars = localvars; 1130 localvars = NULL; 1131 1132 /* see jobs.c:forkshell() for explanation */ 1133 (void)sigprocmask(SIG_BLOCK, &block_all, &olds); 1134 vforking = 1; 1135 VFORK_BLOCK 1136 switch (pid = vfork()) { 1137 case -1: 1138 serrno = errno; 1139 vforking = 0; 1140 (void)sigprocmask(SIG_SETMASK, &olds, NULL); 1141 VTRACE(DBG_EVAL, ("vfork() failed, errno=%d\n", 1142 serrno)); 1143 INTON; 1144 error("Cannot vfork (%s)", strerror(serrno)); 1145 break; 1146 case 0: 1147 /* 1148 * Make sure that exceptions only unwind to 1149 * after the vfork(2) 1150 */ 1151 SHELL_FORKED(); 1152 if (setjmp(jmploc.loc)) { 1153 VTRACE(DBG_EVAL|DBG_ERRS| 1154 DBG_PROCS|DBG_CMDS|DBG_TRAP, 1155 ("vfork child exit exception:%d " 1156 "exitstatus:%d exerrno:%d\n", 1157 exception, exitstatus, exerrno)); 1158 1159 if (exception == EXSHELLPROC) { 1160 /* 1161 * We can't progress with the 1162 * vfork, so, set vforking = 2 1163 * so the parent knows, 1164 * and _exit(); 1165 */ 1166 vforking = 2; 1167 _exit(0); 1168 } else { 1169 _exit(exception == EXEXIT ? 1170 exitstatus : exerrno); 1171 } 1172 } 1173 savehandler = handler; 1174 handler = &jmploc; 1175 listmklocal(varlist.list, 1176 VDOEXPORT | VEXPORT | VNOFUNC); 1177 forkchild(jp, cmd, mode, vforking, &olds); 1178 break; 1179 default: 1180 VFORK_UNDO(); 1181 /* restore from vfork(2) */ 1182 /* 1183 * We need to know what happened to the 1184 * vfork() (currently in vforking) but 1185 * we need to restore signals asap, and 1186 * vforking cannot remain set after that. 1187 * so ... 1188 */ 1189 { 1190 int vforkresult = vforking; 1191 1192 vforking = 0; 1193 (void)sigprocmask(SIG_SETMASK, &olds, NULL); 1194 1195 CTRACE(DBG_PROCS|DBG_CMDS, 1196 ("parent after vfork - vforking=%d\n", 1197 vforkresult)); 1198 1199 handler = savehandler; 1200 poplocalvars(); 1201 localvars = savelocalvars; 1202 if (vforkresult == 2) { 1203 /* 1204 * obliterate the deceased zombie 1205 * (known to have exited already) 1206 */ 1207 (void)waitpid(pid, NULL, 0); 1208 1209 /* 1210 * We need to progress in a 1211 * normal fork fashion 1212 */ 1213 goto normal_fork; 1214 } 1215 } 1216 1217 /* 1218 * Here the child has left home, 1219 * getting on with its life, so 1220 * so must we... 1221 */ 1222 forkparent(jp, cmd, mode, pid); 1223 goto parent; 1224 } 1225 VFORK_END 1226 } else { 1227 normal_fork: 1228 #endif 1229 if (forkshell(jp, cmd, mode) != 0) 1230 goto parent; /* at end of routine */ 1231 CTRACE(DBG_PROCS|DBG_CMDS, ("Child sets EV_EXIT\n")); 1232 flags |= EV_EXIT; 1233 FORCEINTON; 1234 #ifdef DO_SHAREDVFORK 1235 } 1236 #endif 1237 if (flags & EV_BACKCMD) { 1238 if (!vforking) { 1239 FORCEINTON; 1240 } 1241 close(pip[0]); 1242 movefd(pip[1], 1); 1243 } 1244 flags |= EV_EXIT; 1245 } 1246 1247 /* 1248 * This is the child process if a fork occurred. 1249 * (or "the" process if there was no fork at all) 1250 * 1251 * Execute the command. 1252 */ 1253 1254 switch (cmdentry.cmdtype) { 1255 volatile int saved; 1256 struct funcdef * volatile savefunc; 1257 const char * volatile savectx; 1258 1259 case CMDFUNCTION: 1260 VXTRACE(DBG_EVAL, ("Shell function%s: ",vforking?" VF":""), 1261 trargs(argv)); 1262 redirect(cmd->ncmd.redirect, REDIR_KEEP | (saved = 1263 !(flags & EV_EXIT) || have_traps() ? REDIR_PUSH : 0)); 1264 saveparam = shellparam; 1265 shellparam.malloc = 0; 1266 shellparam.reset = 1; 1267 shellparam.nparam = argc - 1; 1268 shellparam.p = argv + 1; 1269 shellparam.optnext = NULL; 1270 INTOFF; 1271 savelocalvars = localvars; 1272 savectx = currentcontext; 1273 localvars = NULL; 1274 reffunc(savefunc = cmdentry.u.func); 1275 INTON; 1276 if (setjmp(jmploc.loc)) { 1277 if (exception == EXSHELLPROC) { 1278 freeparam((volatile struct shparam *) 1279 &saveparam); 1280 } else { 1281 freeparam(&shellparam); 1282 shellparam = saveparam; 1283 } 1284 if (saved) 1285 popredir(POPREDIR_UNDO); 1286 unreffunc(savefunc); 1287 poplocalvars(); 1288 localvars = savelocalvars; 1289 funclinebase = savefuncline; 1290 funclineabs = savefuncabs; 1291 currentcontext = savectx; 1292 handler = savehandler; 1293 longjmp(handler->loc, 1); 1294 } 1295 savehandler = handler; 1296 handler = &jmploc; 1297 if (cmdentry.u.func) { 1298 if (cmdentry.lno_frel) 1299 funclinebase = cmdentry.lineno - 1; 1300 else 1301 funclinebase = 0; 1302 funclineabs = cmdentry.lineno; 1303 currentcontext = argv[0]; 1304 1305 VTRACE(DBG_EVAL, 1306 ("function: node: %d '%s' # %d%s; funclinebase=%d\n", 1307 getfuncnode(cmdentry.u.func)->type, 1308 NODETYPENAME(getfuncnode(cmdentry.u.func)->type), 1309 cmdentry.lineno, cmdentry.lno_frel?" (=1)":"", 1310 funclinebase)); 1311 } 1312 listmklocal(varlist.list, VDOEXPORT | VEXPORT); 1313 /* stop shell blowing its stack */ 1314 if (++funcnest > 1000) 1315 error("too many nested function calls"); 1316 evaltree(getfuncnode(cmdentry.u.func), 1317 flags & (EV_TESTED|EV_EXIT)); 1318 funcnest--; 1319 INTOFF; 1320 unreffunc(cmdentry.u.func); 1321 poplocalvars(); 1322 localvars = savelocalvars; 1323 funclinebase = savefuncline; 1324 funclineabs = savefuncabs; 1325 currentcontext = savectx; 1326 freeparam(&shellparam); 1327 shellparam = saveparam; 1328 handler = savehandler; 1329 if (saved) 1330 popredir(POPREDIR_UNDO); 1331 INTON; 1332 if (evalskip == SKIPFUNC) { 1333 evalskip = SKIPNONE; 1334 skipcount = 0; 1335 } 1336 if (flags & EV_EXIT) 1337 exitshell(exitstatus); 1338 break; 1339 1340 case CMDSPLBLTIN: 1341 VTRACE(DBG_EVAL, ("special ")); 1342 case CMDBUILTIN: 1343 VXTRACE(DBG_EVAL, ("builtin command [%d]%s: ", argc, 1344 vforking ? " VF" : ""), trargs(argv)); 1345 1346 if (cmdentry.u.bltin == execcmd) { 1347 char **ap; 1348 1349 /* 1350 * Work out how we should process redirections 1351 * on the "exec" command. We need REDIR_KEEP 1352 * if we must not set close-on-exec, and REDIR_PUSH 1353 * if we need to be able to undo them (in the 1354 * exec command, only on some kind of error). 1355 * 1356 * Skip "exec" (argv[0]) then examine args. 1357 * 1358 * This must be done manually, as nextopt() 1359 * hasn't been init'd for this command yet. 1360 * And it won't be until after redirections are done. 1361 * 1362 * "exec" currently takes no options (except "--"), 1363 * but might one day, and this needs to keep working, 1364 * so do it, kind of, properly. 1365 * 1366 * Note in the common cases argv[1] will be NULL 1367 * (for exec just setting up redirectons) or will 1368 * not start with a '-' ("exec cmd") so normally 1369 * this loop will either never start or will break 1370 * at the first test of the first iteration. 1371 */ 1372 for (ap = argv + 1; *ap != NULL; ap++) { 1373 1374 if (ap[0][0] != '-') 1375 break; 1376 1377 if (ap[0][1] == '\0') /* "exec -" */ 1378 break; /* or continue ?? */ 1379 1380 if (ap[0][1] == '-' && ap[0][2] == '\0') { 1381 ap++; 1382 break; 1383 } 1384 1385 #if defined(DUMMY_EXAMPLE_CODE) && 0 1386 /* 1387 * if options are added to "exec" then 1388 * any which take an arg (like the common 1389 * in other shells "-a cmdname") need to 1390 * be recognised here, lest "cmdname" be 1391 * thought to be the cmd to exec 1392 */ 1393 1394 for (char *op = ap[0] + 1; *op; op++) { 1395 switch (*op) { 1396 case 'a': 1397 case any others similar: 1398 /* options needing an optarg */ 1399 if (op[1] == '\0' && ap[1]) 1400 ap++; 1401 break; 1402 1403 default: 1404 /* options with no optarg */ 1405 continue; 1406 } 1407 break; 1408 } 1409 #endif /* DUMMY EXAMPLE CODE */ 1410 } 1411 1412 if (*ap != NULL) 1413 mode = REDIR_KEEP; /* exec cmd <... */ 1414 else 1415 mode = 0; /* exec < .... */ 1416 1417 /* 1418 * always save old fd setup in case of error() 1419 * execcmd() will undo this if no error occurs 1420 * (that is, in the case the shell has not vanished) 1421 */ 1422 mode |= REDIR_PUSH; 1423 } else /* any builtin execpt "exec" */ 1424 mode = REDIR_PUSH | REDIR_KEEP; 1425 1426 if (flags == EV_BACKCMD) { 1427 memout.nleft = 0; 1428 memout.nextc = memout.buf; 1429 memout.bufsize = 64; 1430 mode |= REDIR_BACKQ; 1431 } 1432 1433 e = -1; 1434 savecmdname = commandname; 1435 savetopfile = getcurrentfile(); 1436 savehandler = handler; 1437 temp_path = 0; 1438 1439 if (!setjmp(jmploc.loc)) { 1440 handler = &jmploc; 1441 1442 /* 1443 * We need to ensure the command hash table isn't 1444 * corrupted by temporary PATH assignments. 1445 * However we must ensure the 'local' command works! 1446 */ 1447 if (path != pathval() && (cmdentry.u.bltin == hashcmd || 1448 cmdentry.u.bltin == typecmd)) { 1449 savelocalvars = localvars; 1450 localvars = 0; 1451 temp_path = 1; 1452 mklocal(path - 5 /* PATH= */, 0); 1453 } 1454 redirect(cmd->ncmd.redirect, mode); 1455 1456 /* 1457 * the empty command is regarded as a normal 1458 * builtin for the purposes of redirects, but 1459 * is a special builtin for var assigns. 1460 * (unless we are the "command" command.) 1461 */ 1462 if (argc == 0 && !(cmd_flags & DO_NOFUNC)) 1463 cmdentry.cmdtype = CMDSPLBLTIN; 1464 1465 /* exec is a special builtin, but needs this list... */ 1466 cmdenviron = varlist.list; 1467 /* we must check 'readonly' flag for all builtins */ 1468 listsetvar(varlist.list, 1469 cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET); 1470 commandname = argv[0]; 1471 /* initialize nextopt */ 1472 argptr = argv + 1; 1473 optptr = NULL; 1474 /* and getopt */ 1475 optreset = 1; 1476 optind = 1; 1477 builtin_flags = flags; 1478 clr_err(out1); /* discard previous I/O errors */ 1479 exitstatus = cmdentry.u.bltin(argc, argv); 1480 } else { 1481 e = exception; 1482 if (e == EXINT) 1483 exitstatus = SIGINT + 128; 1484 else if (e == EXEXEC) 1485 exitstatus = exerrno; 1486 else if (e != EXEXIT) 1487 exitstatus = 2; 1488 } 1489 handler = savehandler; 1490 flushall(); 1491 out1 = &output; 1492 out2 = &errout; 1493 freestdout(); 1494 if (temp_path) { 1495 poplocalvars(); 1496 localvars = savelocalvars; 1497 } 1498 cmdenviron = NULL; 1499 if (e != EXSHELLPROC) { 1500 commandname = savecmdname; 1501 if (flags & EV_EXIT) 1502 exitshell(exitstatus); 1503 } 1504 if (e != -1) { 1505 if ((e != EXERROR && e != EXEXEC) 1506 || cmdentry.cmdtype == CMDSPLBLTIN) 1507 exraise(e); 1508 popfilesupto(savetopfile); 1509 FORCEINTON; 1510 } 1511 1512 if (cmdentry.u.bltin != execcmd) 1513 popredir(POPREDIR_UNDO); 1514 1515 if (flags == EV_BACKCMD) { 1516 backcmd->buf = memout.buf; 1517 backcmd->nleft = memout.nextc - memout.buf; 1518 memout.buf = NULL; 1519 } 1520 break; 1521 1522 default: 1523 VXTRACE(DBG_EVAL, ("normal command%s: ", vforking?" VF":""), 1524 trargs(argv)); 1525 redirect(cmd->ncmd.redirect, 1526 (vforking ? REDIR_VFORK : 0) | REDIR_KEEP); 1527 if (!vforking) 1528 for (sp = varlist.list ; sp ; sp = sp->next) 1529 setvareq(sp->text, VDOEXPORT|VEXPORT|VSTACK); 1530 envp = environment(); 1531 shellexec(argv, envp, path, cmdentry.u.index, vforking); 1532 break; 1533 } 1534 goto out; 1535 1536 parent: /* parent process gets here (if we forked) */ 1537 1538 exitstatus = 0; /* if not altered just below */ 1539 if (mode == FORK_FG) { /* argument to fork */ 1540 exitstatus = waitforjob(jp); 1541 } else if (mode == FORK_NOJOB) { 1542 backcmd->fd = pip[0]; 1543 close(pip[1]); 1544 backcmd->jp = jp; 1545 } else 1546 jobstarted(jp); 1547 1548 FORCEINTON; 1549 1550 out: 1551 if (lastarg) 1552 /* implement $_ for whatever use that really is */ 1553 (void) setvarsafe("_", lastarg, VNOERROR); 1554 popstackmark(&smark); 1555 } 1556 1557 1558 /* 1559 * Search for a command. This is called before we fork so that the 1560 * location of the command will be available in the parent as well as 1561 * the child. The check for "goodname" is an overly conservative 1562 * check that the name will not be subject to expansion. 1563 */ 1564 1565 STATIC void 1566 prehash(union node *n) 1567 { 1568 struct cmdentry entry; 1569 1570 if (n && n->type == NCMD && n->ncmd.args) 1571 if (goodname(n->ncmd.args->narg.text)) 1572 find_command(n->ncmd.args->narg.text, &entry, 0, 1573 pathval()); 1574 } 1575 1576 int 1577 in_function(void) 1578 { 1579 return funcnest; 1580 } 1581 1582 enum skipstate 1583 current_skipstate(void) 1584 { 1585 return evalskip; 1586 } 1587 1588 void 1589 save_skipstate(struct skipsave *p) 1590 { 1591 *p = s_k_i_p; 1592 } 1593 1594 void 1595 restore_skipstate(const struct skipsave *p) 1596 { 1597 s_k_i_p = *p; 1598 } 1599 1600 void 1601 stop_skipping(void) 1602 { 1603 evalskip = SKIPNONE; 1604 skipcount = 0; 1605 } 1606 1607 /* 1608 * Builtin commands. Builtin commands whose functions are closely 1609 * tied to evaluation are implemented here. 1610 */ 1611 1612 /* 1613 * No command given. 1614 */ 1615 1616 int 1617 bltincmd(int argc, char **argv) 1618 { 1619 /* 1620 * Preserve exitstatus of a previous possible redirection 1621 * as POSIX mandates 1622 */ 1623 return back_exitstatus; 1624 } 1625 1626 1627 /* 1628 * Handle break and continue commands. Break, continue, and return are 1629 * all handled by setting the evalskip flag. The evaluation routines 1630 * above all check this flag, and if it is set they start skipping 1631 * commands rather than executing them. The variable skipcount is 1632 * the number of loops to break/continue, or the number of function 1633 * levels to return. (The latter is always 1.) It should probably 1634 * be an error to break out of more loops than exist, but it isn't 1635 * in the standard shell so we don't make it one here. 1636 */ 1637 1638 int 1639 breakcmd(int argc, char **argv) 1640 { 1641 int n = argc > 1 ? number(argv[1]) : 1; 1642 1643 if (n <= 0) 1644 error("invalid count: %d", n); 1645 if (n > loopnest) 1646 n = loopnest; 1647 if (n > 0) { 1648 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; 1649 skipcount = n; 1650 } 1651 return 0; 1652 } 1653 1654 int 1655 dotcmd(int argc, char **argv) 1656 { 1657 exitstatus = 0; 1658 1659 (void) nextopt(NULL); /* ignore a leading "--" */ 1660 1661 if (*argptr != NULL) { /* That's what SVR2 does */ 1662 char *fullname; 1663 /* 1664 * dot_funcnest needs to be 0 when not in a dotcmd, so it 1665 * cannot be restored with (funcnest + 1). 1666 */ 1667 int dot_funcnest_old; 1668 struct stackmark smark; 1669 1670 setstackmark(&smark); 1671 fullname = find_dot_file(*argptr); 1672 setinputfile(fullname, 1); 1673 commandname = fullname; 1674 dot_funcnest_old = dot_funcnest; 1675 dot_funcnest = funcnest + 1; 1676 cmdloop(0); 1677 dot_funcnest = dot_funcnest_old; 1678 popfile(); 1679 popstackmark(&smark); 1680 } 1681 return exitstatus; 1682 } 1683 1684 /* 1685 * allow dotfile function nesting to be manipulated 1686 * (for read_profile). This allows profile files to 1687 * be treated as if they were used as '.' commands, 1688 * (approximately) and in particular, for "return" to work. 1689 */ 1690 int 1691 set_dot_funcnest(int new) 1692 { 1693 int rv = dot_funcnest; 1694 1695 if (new >= 0) 1696 dot_funcnest = new; 1697 1698 return rv; 1699 } 1700 1701 /* 1702 * Take commands from a file. To be compatible we should do a path 1703 * search for the file, which is necessary to find sub-commands. 1704 */ 1705 1706 STATIC char * 1707 find_dot_file(char *basename) 1708 { 1709 char *fullname; 1710 const char *path = pathval(); 1711 struct stat statb; 1712 1713 /* don't try this for absolute or relative paths */ 1714 if (strchr(basename, '/')) { 1715 if (stat(basename, &statb) == 0) { 1716 if (S_ISDIR(statb.st_mode)) 1717 error("%s: is a directory", basename); 1718 if (S_ISBLK(statb.st_mode)) 1719 error("%s: is a block device", basename); 1720 return basename; 1721 } 1722 } else while ((fullname = padvance(&path, basename, 1)) != NULL) { 1723 if ((stat(fullname, &statb) == 0)) { 1724 /* weird format is to ease future code... */ 1725 if (S_ISDIR(statb.st_mode) || S_ISBLK(statb.st_mode)) 1726 ; 1727 #if notyet 1728 else if (unreadable()) { 1729 /* 1730 * testing this via st_mode is ugly to get 1731 * correct (and would ignore ACLs). 1732 * better way is just to open the file. 1733 * But doing that here would (currently) 1734 * mean opening the file twice, which 1735 * might not be safe. So, defer this 1736 * test until code is restructures so 1737 * we can return a fd. Then we also 1738 * get to fix the mem leak just below... 1739 */ 1740 } 1741 #endif 1742 else { 1743 /* 1744 * Don't bother freeing here, since 1745 * it will be freed by the caller. 1746 * XXX no it won't - a bug for later. 1747 */ 1748 return fullname; 1749 } 1750 } 1751 stunalloc(fullname); 1752 } 1753 1754 /* not found in the PATH */ 1755 error("%s: not found", basename); 1756 /* NOTREACHED */ 1757 } 1758 1759 1760 1761 /* 1762 * The return command. 1763 * 1764 * Quoth the POSIX standard: 1765 * The return utility shall cause the shell to stop executing the current 1766 * function or dot script. If the shell is not currently executing 1767 * a function or dot script, the results are unspecified. 1768 * 1769 * As for the unspecified part, there seems to be no de-facto standard: bash 1770 * ignores the return with a warning, zsh ignores the return in interactive 1771 * mode but seems to liken it to exit in a script. (checked May 2014) 1772 * 1773 * We choose to silently ignore the return. Older versions of this shell 1774 * set evalskip to SKIPFILE causing the shell to (indirectly) exit. This 1775 * had at least the problem of circumventing the check for stopped jobs, 1776 * which would occur for exit or ^D. 1777 */ 1778 1779 int 1780 returncmd(int argc, char **argv) 1781 { 1782 int ret = argc > 1 ? number(argv[1]) : exitstatus; 1783 1784 if ((dot_funcnest == 0 && funcnest) 1785 || (dot_funcnest > 0 && funcnest - (dot_funcnest - 1) > 0)) { 1786 evalskip = SKIPFUNC; 1787 skipcount = 1; 1788 } else if (dot_funcnest > 0) { 1789 evalskip = SKIPFILE; 1790 skipcount = 1; 1791 } else { 1792 /* XXX: should a warning be issued? */ 1793 ret = 0; 1794 } 1795 1796 return ret; 1797 } 1798 1799 1800 int 1801 falsecmd(int argc, char **argv) 1802 { 1803 return 1; 1804 } 1805 1806 1807 int 1808 truecmd(int argc, char **argv) 1809 { 1810 return 0; 1811 } 1812 1813 1814 int 1815 execcmd(int argc, char **argv) 1816 { 1817 /* 1818 * BEWARE: if any options are added here, they must 1819 * also be added in evalcommand(), look for "DUMMY_EXAMPLE_CODE" 1820 * for example code for there. Here the options would be 1821 * processed completely normally. 1822 */ 1823 (void) nextopt(""); /* ignore a leading "--" */ 1824 1825 if (*argptr) { 1826 struct strlist *sp; 1827 1828 iflag = 0; /* exit on error */ 1829 mflag = 0; 1830 optschanged(); 1831 for (sp = cmdenviron; sp; sp = sp->next) 1832 setvareq(sp->text, VDOEXPORT|VEXPORT|VSTACK); 1833 shellexec(argptr, environment(), pathval(), 0, 0); 1834 /* NOTREACHED */ 1835 } 1836 popredir(POPREDIR_PERMANENT); /* make any redirections permanent */ 1837 return 0; 1838 } 1839 1840 static int 1841 conv_time(clock_t ticks, char *seconds, size_t l) 1842 { 1843 static clock_t tpm = 0; 1844 clock_t mins; 1845 int i; 1846 1847 if (!tpm) 1848 tpm = sysconf(_SC_CLK_TCK) * 60; 1849 1850 mins = ticks / tpm; 1851 snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm ); 1852 1853 if (seconds[0] == '6' && seconds[1] == '0') { 1854 /* 59.99995 got rounded up... */ 1855 mins++; 1856 strlcpy(seconds, "0.0", l); 1857 return mins; 1858 } 1859 1860 /* suppress trailing zeros */ 1861 i = strlen(seconds) - 1; 1862 for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--) 1863 seconds[i] = 0; 1864 return mins; 1865 } 1866 1867 int 1868 timescmd(int argc, char **argv) 1869 { 1870 struct tms tms; 1871 int u, s, cu, cs; 1872 char us[8], ss[8], cus[8], css[8]; 1873 1874 nextopt(""); 1875 1876 times(&tms); 1877 1878 u = conv_time(tms.tms_utime, us, sizeof(us)); 1879 s = conv_time(tms.tms_stime, ss, sizeof(ss)); 1880 cu = conv_time(tms.tms_cutime, cus, sizeof(cus)); 1881 cs = conv_time(tms.tms_cstime, css, sizeof(css)); 1882 1883 outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n", 1884 u, us, s, ss, cu, cus, cs, css); 1885 1886 return 0; 1887 } 1888