1 /* $NetBSD: eval.c,v 1.109 2014/05/31 14:42:18 christos 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.109 2014/05/31 14:42:18 christos 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 <errno.h> 49 #include <limits.h> 50 #include <unistd.h> 51 #include <sys/fcntl.h> 52 #include <sys/times.h> 53 #include <sys/param.h> 54 #include <sys/types.h> 55 #include <sys/wait.h> 56 #include <sys/sysctl.h> 57 58 /* 59 * Evaluate a command. 60 */ 61 62 #include "shell.h" 63 #include "nodes.h" 64 #include "syntax.h" 65 #include "expand.h" 66 #include "parser.h" 67 #include "jobs.h" 68 #include "eval.h" 69 #include "builtins.h" 70 #include "options.h" 71 #include "exec.h" 72 #include "redir.h" 73 #include "input.h" 74 #include "output.h" 75 #include "trap.h" 76 #include "var.h" 77 #include "memalloc.h" 78 #include "error.h" 79 #include "show.h" 80 #include "mystring.h" 81 #include "main.h" 82 #ifndef SMALL 83 #include "myhistedit.h" 84 #endif 85 86 87 /* flags in argument to evaltree */ 88 #define EV_EXIT 01 /* exit after evaluating tree */ 89 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 90 #define EV_BACKCMD 04 /* command executing within back quotes */ 91 92 STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */ 93 STATIC int skipcount; /* number of levels to skip */ 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 evalpipe(union node *); 120 STATIC void evalcommand(union node *, int, struct backcmd *); 121 STATIC void prehash(union node *); 122 123 STATIC char *find_dot_file(char *); 124 125 /* 126 * Called to reset things after an exception. 127 */ 128 129 #ifdef mkinit 130 INCLUDE "eval.h" 131 132 RESET { 133 reset_eval(); 134 } 135 136 SHELLPROC { 137 exitstatus = 0; 138 } 139 #endif 140 141 void 142 reset_eval(void) 143 { 144 evalskip = SKIPNONE; 145 dot_funcnest = 0; 146 loopnest = 0; 147 funcnest = 0; 148 } 149 150 static int 151 sh_pipe(int fds[2]) 152 { 153 int nfd; 154 155 if (pipe(fds)) 156 return -1; 157 158 if (fds[0] < 3) { 159 nfd = fcntl(fds[0], F_DUPFD, 3); 160 if (nfd != -1) { 161 close(fds[0]); 162 fds[0] = nfd; 163 } 164 } 165 166 if (fds[1] < 3) { 167 nfd = fcntl(fds[1], F_DUPFD, 3); 168 if (nfd != -1) { 169 close(fds[1]); 170 fds[1] = nfd; 171 } 172 } 173 return 0; 174 } 175 176 177 /* 178 * The eval commmand. 179 */ 180 181 int 182 evalcmd(int argc, char **argv) 183 { 184 char *p; 185 char *concat; 186 char **ap; 187 188 if (argc > 1) { 189 p = argv[1]; 190 if (argc > 2) { 191 STARTSTACKSTR(concat); 192 ap = argv + 2; 193 for (;;) { 194 while (*p) 195 STPUTC(*p++, concat); 196 if ((p = *ap++) == NULL) 197 break; 198 STPUTC(' ', concat); 199 } 200 STPUTC('\0', concat); 201 p = grabstackstr(concat); 202 } 203 evalstring(p, builtin_flags & EV_TESTED); 204 } 205 return exitstatus; 206 } 207 208 209 /* 210 * Execute a command or commands contained in a string. 211 */ 212 213 void 214 evalstring(char *s, int flag) 215 { 216 union node *n; 217 struct stackmark smark; 218 219 setstackmark(&smark); 220 setinputstring(s, 1); 221 222 while ((n = parsecmd(0)) != NEOF) { 223 evaltree(n, flag); 224 popstackmark(&smark); 225 } 226 popfile(); 227 popstackmark(&smark); 228 } 229 230 231 232 /* 233 * Evaluate a parse tree. The value is left in the global variable 234 * exitstatus. 235 */ 236 237 void 238 evaltree(union node *n, int flags) 239 { 240 bool do_etest; 241 242 do_etest = false; 243 if (n == NULL) { 244 TRACE(("evaltree(NULL) called\n")); 245 exitstatus = 0; 246 goto out; 247 } 248 #ifndef SMALL 249 displayhist = 1; /* show history substitutions done with fc */ 250 #endif 251 TRACE(("pid %d, evaltree(%p: %d, %d) called\n", 252 getpid(), n, n->type, flags)); 253 switch (n->type) { 254 case NSEMI: 255 evaltree(n->nbinary.ch1, flags & EV_TESTED); 256 if (evalskip) 257 goto out; 258 evaltree(n->nbinary.ch2, flags); 259 break; 260 case NAND: 261 evaltree(n->nbinary.ch1, EV_TESTED); 262 if (evalskip || exitstatus != 0) 263 goto out; 264 evaltree(n->nbinary.ch2, flags); 265 break; 266 case NOR: 267 evaltree(n->nbinary.ch1, EV_TESTED); 268 if (evalskip || exitstatus == 0) 269 goto out; 270 evaltree(n->nbinary.ch2, flags); 271 break; 272 case NREDIR: 273 expredir(n->nredir.redirect); 274 redirect(n->nredir.redirect, REDIR_PUSH); 275 evaltree(n->nredir.n, flags); 276 popredir(); 277 break; 278 case NSUBSHELL: 279 evalsubshell(n, flags); 280 do_etest = !(flags & EV_TESTED); 281 break; 282 case NBACKGND: 283 evalsubshell(n, flags); 284 break; 285 case NIF: { 286 evaltree(n->nif.test, EV_TESTED); 287 if (evalskip) 288 goto out; 289 if (exitstatus == 0) 290 evaltree(n->nif.ifpart, flags); 291 else if (n->nif.elsepart) 292 evaltree(n->nif.elsepart, flags); 293 else 294 exitstatus = 0; 295 break; 296 } 297 case NWHILE: 298 case NUNTIL: 299 evalloop(n, flags); 300 break; 301 case NFOR: 302 evalfor(n, flags); 303 break; 304 case NCASE: 305 evalcase(n, flags); 306 break; 307 case NDEFUN: 308 defun(n->narg.text, n->narg.next); 309 exitstatus = 0; 310 break; 311 case NNOT: 312 evaltree(n->nnot.com, EV_TESTED); 313 exitstatus = !exitstatus; 314 break; 315 case NPIPE: 316 evalpipe(n); 317 do_etest = !(flags & EV_TESTED); 318 break; 319 case NCMD: 320 evalcommand(n, flags, NULL); 321 do_etest = !(flags & EV_TESTED); 322 break; 323 default: 324 out1fmt("Node type = %d\n", n->type); 325 flushout(&output); 326 break; 327 } 328 out: 329 if (pendingsigs) 330 dotrap(); 331 if ((flags & EV_EXIT) != 0 || (eflag && exitstatus != 0 && do_etest)) 332 exitshell(exitstatus); 333 } 334 335 336 STATIC void 337 evalloop(union node *n, int flags) 338 { 339 int status; 340 341 loopnest++; 342 status = 0; 343 for (;;) { 344 evaltree(n->nbinary.ch1, EV_TESTED); 345 if (evalskip) { 346 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 347 evalskip = SKIPNONE; 348 continue; 349 } 350 if (evalskip == SKIPBREAK && --skipcount <= 0) 351 evalskip = SKIPNONE; 352 break; 353 } 354 if (n->type == NWHILE) { 355 if (exitstatus != 0) 356 break; 357 } else { 358 if (exitstatus == 0) 359 break; 360 } 361 evaltree(n->nbinary.ch2, flags & EV_TESTED); 362 status = exitstatus; 363 if (evalskip) 364 goto skipping; 365 } 366 loopnest--; 367 exitstatus = status; 368 } 369 370 371 372 STATIC void 373 evalfor(union node *n, int flags) 374 { 375 struct arglist arglist; 376 union node *argp; 377 struct strlist *sp; 378 struct stackmark smark; 379 int status = 0; 380 381 setstackmark(&smark); 382 arglist.lastp = &arglist.list; 383 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { 384 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 385 if (evalskip) 386 goto out; 387 } 388 *arglist.lastp = NULL; 389 390 loopnest++; 391 for (sp = arglist.list ; sp ; sp = sp->next) { 392 setvar(n->nfor.var, sp->text, 0); 393 evaltree(n->nfor.body, flags & EV_TESTED); 394 status = exitstatus; 395 if (evalskip) { 396 if (evalskip == SKIPCONT && --skipcount <= 0) { 397 evalskip = SKIPNONE; 398 continue; 399 } 400 if (evalskip == SKIPBREAK && --skipcount <= 0) 401 evalskip = SKIPNONE; 402 break; 403 } 404 } 405 loopnest--; 406 exitstatus = status; 407 out: 408 popstackmark(&smark); 409 } 410 411 412 413 STATIC void 414 evalcase(union node *n, int flags) 415 { 416 union node *cp; 417 union node *patp; 418 struct arglist arglist; 419 struct stackmark smark; 420 int status = 0; 421 422 setstackmark(&smark); 423 arglist.lastp = &arglist.list; 424 expandarg(n->ncase.expr, &arglist, EXP_TILDE); 425 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { 426 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { 427 if (casematch(patp, arglist.list->text)) { 428 if (evalskip == 0) { 429 evaltree(cp->nclist.body, flags); 430 status = exitstatus; 431 } 432 goto out; 433 } 434 } 435 } 436 out: 437 exitstatus = status; 438 popstackmark(&smark); 439 } 440 441 442 443 /* 444 * Kick off a subshell to evaluate a tree. 445 */ 446 447 STATIC void 448 evalsubshell(union node *n, int flags) 449 { 450 struct job *jp; 451 int backgnd = (n->type == NBACKGND); 452 453 expredir(n->nredir.redirect); 454 INTOFF; 455 jp = makejob(n, 1); 456 if (forkshell(jp, n, backgnd ? FORK_BG : FORK_FG) == 0) { 457 INTON; 458 if (backgnd) 459 flags &=~ EV_TESTED; 460 redirect(n->nredir.redirect, 0); 461 /* never returns */ 462 evaltree(n->nredir.n, flags | EV_EXIT); 463 } 464 if (! backgnd) 465 exitstatus = waitforjob(jp); 466 INTON; 467 } 468 469 470 471 /* 472 * Compute the names of the files in a redirection list. 473 */ 474 475 STATIC void 476 expredir(union node *n) 477 { 478 union node *redir; 479 480 for (redir = n ; redir ; redir = redir->nfile.next) { 481 struct arglist fn; 482 fn.lastp = &fn.list; 483 switch (redir->type) { 484 case NFROMTO: 485 case NFROM: 486 case NTO: 487 case NCLOBBER: 488 case NAPPEND: 489 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 490 redir->nfile.expfname = fn.list->text; 491 break; 492 case NFROMFD: 493 case NTOFD: 494 if (redir->ndup.vname) { 495 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); 496 fixredir(redir, fn.list->text, 1); 497 } 498 break; 499 } 500 } 501 } 502 503 504 505 /* 506 * Evaluate a pipeline. All the processes in the pipeline are children 507 * of the process creating the pipeline. (This differs from some versions 508 * of the shell, which make the last process in a pipeline the parent 509 * of all the rest.) 510 */ 511 512 STATIC void 513 evalpipe(union node *n) 514 { 515 struct job *jp; 516 struct nodelist *lp; 517 int pipelen; 518 int prevfd; 519 int pip[2]; 520 521 TRACE(("evalpipe(0x%lx) called\n", (long)n)); 522 pipelen = 0; 523 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) 524 pipelen++; 525 INTOFF; 526 jp = makejob(n, pipelen); 527 prevfd = -1; 528 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 529 prehash(lp->n); 530 pip[1] = -1; 531 if (lp->next) { 532 if (sh_pipe(pip) < 0) { 533 if (prevfd >= 0) 534 close(prevfd); 535 error("Pipe call failed"); 536 } 537 } 538 if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) { 539 INTON; 540 if (prevfd > 0) { 541 close(0); 542 copyfd(prevfd, 0, 1); 543 close(prevfd); 544 } 545 if (pip[1] >= 0) { 546 close(pip[0]); 547 if (pip[1] != 1) { 548 close(1); 549 copyfd(pip[1], 1, 1); 550 close(pip[1]); 551 } 552 } 553 evaltree(lp->n, EV_EXIT); 554 } 555 if (prevfd >= 0) 556 close(prevfd); 557 prevfd = pip[0]; 558 close(pip[1]); 559 } 560 if (n->npipe.backgnd == 0) { 561 exitstatus = waitforjob(jp); 562 TRACE(("evalpipe: job done exit status %d\n", exitstatus)); 563 } 564 INTON; 565 } 566 567 568 569 /* 570 * Execute a command inside back quotes. If it's a builtin command, we 571 * want to save its output in a block obtained from malloc. Otherwise 572 * we fork off a subprocess and get the output of the command via a pipe. 573 * Should be called with interrupts off. 574 */ 575 576 void 577 evalbackcmd(union node *n, struct backcmd *result) 578 { 579 int pip[2]; 580 struct job *jp; 581 struct stackmark smark; /* unnecessary */ 582 583 setstackmark(&smark); 584 result->fd = -1; 585 result->buf = NULL; 586 result->nleft = 0; 587 result->jp = NULL; 588 if (n == NULL) { 589 goto out; 590 } 591 #ifdef notyet 592 /* 593 * For now we disable executing builtins in the same 594 * context as the shell, because we are not keeping 595 * enough state to recover from changes that are 596 * supposed only to affect subshells. eg. echo "`cd /`" 597 */ 598 if (n->type == NCMD) { 599 exitstatus = oexitstatus; 600 evalcommand(n, EV_BACKCMD, result); 601 } else 602 #endif 603 { 604 INTOFF; 605 if (sh_pipe(pip) < 0) 606 error("Pipe call failed"); 607 jp = makejob(n, 1); 608 if (forkshell(jp, n, FORK_NOJOB) == 0) { 609 FORCEINTON; 610 close(pip[0]); 611 if (pip[1] != 1) { 612 close(1); 613 copyfd(pip[1], 1, 1); 614 close(pip[1]); 615 } 616 eflag = 0; 617 evaltree(n, EV_EXIT); 618 /* NOTREACHED */ 619 } 620 close(pip[1]); 621 result->fd = pip[0]; 622 result->jp = jp; 623 INTON; 624 } 625 out: 626 popstackmark(&smark); 627 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", 628 result->fd, result->buf, result->nleft, result->jp)); 629 } 630 631 static const char * 632 syspath(void) 633 { 634 static char *sys_path = NULL; 635 static int mib[] = {CTL_USER, USER_CS_PATH}; 636 static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; 637 size_t len; 638 639 if (sys_path == NULL) { 640 if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && 641 (sys_path = ckmalloc(len + 5)) != NULL && 642 sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { 643 memcpy(sys_path, "PATH=", 5); 644 } else { 645 ckfree(sys_path); 646 /* something to keep things happy */ 647 sys_path = def_path; 648 } 649 } 650 return sys_path; 651 } 652 653 static int 654 parse_command_args(int argc, char **argv, int *use_syspath) 655 { 656 int sv_argc = argc; 657 char *cp, c; 658 659 *use_syspath = 0; 660 661 for (;;) { 662 argv++; 663 if (--argc == 0) 664 break; 665 cp = *argv; 666 if (*cp++ != '-') 667 break; 668 if (*cp == '-' && cp[1] == 0) { 669 argv++; 670 argc--; 671 break; 672 } 673 while ((c = *cp++)) { 674 switch (c) { 675 case 'p': 676 *use_syspath = 1; 677 break; 678 default: 679 /* run 'typecmd' for other options */ 680 return 0; 681 } 682 } 683 } 684 return sv_argc - argc; 685 } 686 687 int vforked = 0; 688 extern char *trap[]; 689 690 /* 691 * Execute a simple command. 692 */ 693 694 STATIC void 695 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd) 696 { 697 struct stackmark smark; 698 union node *argp; 699 struct arglist arglist; 700 struct arglist varlist; 701 volatile int flags = flgs; 702 char ** volatile argv; 703 volatile int argc; 704 char **envp; 705 int varflag; 706 struct strlist *sp; 707 volatile int mode; 708 int pip[2]; 709 struct cmdentry cmdentry; 710 struct job * volatile jp; 711 struct jmploc jmploc; 712 struct jmploc *volatile savehandler = NULL; 713 const char *volatile savecmdname; 714 volatile struct shparam saveparam; 715 struct localvar *volatile savelocalvars; 716 volatile int e; 717 char * volatile lastarg; 718 const char * volatile path = pathval(); 719 volatile int temp_path; 720 721 vforked = 0; 722 /* First expand the arguments. */ 723 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); 724 setstackmark(&smark); 725 back_exitstatus = 0; 726 727 arglist.lastp = &arglist.list; 728 varflag = 1; 729 /* Expand arguments, ignoring the initial 'name=value' ones */ 730 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 731 char *p = argp->narg.text; 732 if (varflag && is_name(*p)) { 733 do { 734 p++; 735 } while (is_in_name(*p)); 736 if (*p == '=') 737 continue; 738 } 739 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); 740 varflag = 0; 741 } 742 *arglist.lastp = NULL; 743 744 expredir(cmd->ncmd.redirect); 745 746 /* Now do the initial 'name=value' ones we skipped above */ 747 varlist.lastp = &varlist.list; 748 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { 749 char *p = argp->narg.text; 750 if (!is_name(*p)) 751 break; 752 do 753 p++; 754 while (is_in_name(*p)); 755 if (*p != '=') 756 break; 757 expandarg(argp, &varlist, EXP_VARTILDE); 758 } 759 *varlist.lastp = NULL; 760 761 argc = 0; 762 for (sp = arglist.list ; sp ; sp = sp->next) 763 argc++; 764 argv = stalloc(sizeof (char *) * (argc + 1)); 765 766 for (sp = arglist.list ; sp ; sp = sp->next) { 767 TRACE(("evalcommand arg: %s\n", sp->text)); 768 *argv++ = sp->text; 769 } 770 *argv = NULL; 771 lastarg = NULL; 772 if (iflag && funcnest == 0 && argc > 0) 773 lastarg = argv[-1]; 774 argv -= argc; 775 776 /* Print the command if xflag is set. */ 777 if (xflag) { 778 char sep = 0; 779 out2str(ps4val()); 780 for (sp = varlist.list ; sp ; sp = sp->next) { 781 if (sep != 0) 782 outc(sep, &errout); 783 out2shstr(sp->text); 784 sep = ' '; 785 } 786 for (sp = arglist.list ; sp ; sp = sp->next) { 787 if (sep != 0) 788 outc(sep, &errout); 789 out2shstr(sp->text); 790 sep = ' '; 791 } 792 outc('\n', &errout); 793 flushout(&errout); 794 } 795 796 /* Now locate the command. */ 797 if (argc == 0) { 798 cmdentry.cmdtype = CMDSPLBLTIN; 799 cmdentry.u.bltin = bltincmd; 800 } else { 801 static const char PATH[] = "PATH="; 802 int cmd_flags = DO_ERR; 803 804 /* 805 * Modify the command lookup path, if a PATH= assignment 806 * is present 807 */ 808 for (sp = varlist.list; sp; sp = sp->next) 809 if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) 810 path = sp->text + sizeof(PATH) - 1; 811 812 do { 813 int argsused, use_syspath; 814 find_command(argv[0], &cmdentry, cmd_flags, path); 815 if (cmdentry.cmdtype == CMDUNKNOWN) { 816 exitstatus = 127; 817 flushout(&errout); 818 goto out; 819 } 820 821 /* implement the 'command' builtin here */ 822 if (cmdentry.cmdtype != CMDBUILTIN || 823 cmdentry.u.bltin != bltincmd) 824 break; 825 cmd_flags |= DO_NOFUNC; 826 argsused = parse_command_args(argc, argv, &use_syspath); 827 if (argsused == 0) { 828 /* use 'type' builting to display info */ 829 cmdentry.u.bltin = typecmd; 830 break; 831 } 832 argc -= argsused; 833 argv += argsused; 834 if (use_syspath) 835 path = syspath() + 5; 836 } while (argc != 0); 837 if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC) 838 /* posix mandates that 'command <splbltin>' act as if 839 <splbltin> was a normal builtin */ 840 cmdentry.cmdtype = CMDBUILTIN; 841 } 842 843 /* Fork off a child process if necessary. */ 844 if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0) 845 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) 846 || ((flags & EV_BACKCMD) != 0 847 && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) 848 || cmdentry.u.bltin == dotcmd 849 || cmdentry.u.bltin == evalcmd))) { 850 INTOFF; 851 jp = makejob(cmd, 1); 852 mode = cmd->ncmd.backgnd; 853 if (flags & EV_BACKCMD) { 854 mode = FORK_NOJOB; 855 if (sh_pipe(pip) < 0) 856 error("Pipe call failed"); 857 } 858 #ifdef DO_SHAREDVFORK 859 /* It is essential that if DO_SHAREDVFORK is defined that the 860 * child's address space is actually shared with the parent as 861 * we rely on this. 862 */ 863 if (cmdentry.cmdtype == CMDNORMAL) { 864 pid_t pid; 865 int serrno; 866 867 savelocalvars = localvars; 868 localvars = NULL; 869 vforked = 1; 870 switch (pid = vfork()) { 871 case -1: 872 serrno = errno; 873 TRACE(("Vfork failed, errno=%d\n", serrno)); 874 INTON; 875 error("Cannot vfork (%s)", strerror(serrno)); 876 break; 877 case 0: 878 /* Make sure that exceptions only unwind to 879 * after the vfork(2) 880 */ 881 if (setjmp(jmploc.loc)) { 882 if (exception == EXSHELLPROC) { 883 /* We can't progress with the vfork, 884 * so, set vforked = 2 so the parent 885 * knows, and _exit(); 886 */ 887 vforked = 2; 888 _exit(0); 889 } else { 890 _exit(exerrno); 891 } 892 } 893 savehandler = handler; 894 handler = &jmploc; 895 listmklocal(varlist.list, VEXPORT | VNOFUNC); 896 forkchild(jp, cmd, mode, vforked); 897 break; 898 default: 899 handler = savehandler; /* restore from vfork(2) */ 900 poplocalvars(); 901 localvars = savelocalvars; 902 if (vforked == 2) { 903 vforked = 0; 904 905 (void)waitpid(pid, NULL, 0); 906 /* We need to progress in a normal fork fashion */ 907 goto normal_fork; 908 } 909 vforked = 0; 910 forkparent(jp, cmd, mode, pid); 911 goto parent; 912 } 913 } else { 914 normal_fork: 915 #endif 916 if (forkshell(jp, cmd, mode) != 0) 917 goto parent; /* at end of routine */ 918 FORCEINTON; 919 #ifdef DO_SHAREDVFORK 920 } 921 #endif 922 if (flags & EV_BACKCMD) { 923 if (!vforked) { 924 FORCEINTON; 925 } 926 close(pip[0]); 927 if (pip[1] != 1) { 928 close(1); 929 copyfd(pip[1], 1, 1); 930 close(pip[1]); 931 } 932 } 933 flags |= EV_EXIT; 934 } 935 936 /* This is the child process if a fork occurred. */ 937 /* Execute the command. */ 938 switch (cmdentry.cmdtype) { 939 case CMDFUNCTION: 940 #ifdef DEBUG 941 trputs("Shell function: "); trargs(argv); 942 #endif 943 redirect(cmd->ncmd.redirect, REDIR_PUSH); 944 saveparam = shellparam; 945 shellparam.malloc = 0; 946 shellparam.reset = 1; 947 shellparam.nparam = argc - 1; 948 shellparam.p = argv + 1; 949 shellparam.optnext = NULL; 950 INTOFF; 951 savelocalvars = localvars; 952 localvars = NULL; 953 INTON; 954 if (setjmp(jmploc.loc)) { 955 if (exception == EXSHELLPROC) { 956 freeparam((volatile struct shparam *) 957 &saveparam); 958 } else { 959 freeparam(&shellparam); 960 shellparam = saveparam; 961 } 962 poplocalvars(); 963 localvars = savelocalvars; 964 handler = savehandler; 965 longjmp(handler->loc, 1); 966 } 967 savehandler = handler; 968 handler = &jmploc; 969 listmklocal(varlist.list, VEXPORT); 970 /* stop shell blowing its stack */ 971 if (++funcnest > 1000) 972 error("too many nested function calls"); 973 evaltree(cmdentry.u.func, flags & EV_TESTED); 974 funcnest--; 975 INTOFF; 976 poplocalvars(); 977 localvars = savelocalvars; 978 freeparam(&shellparam); 979 shellparam = saveparam; 980 handler = savehandler; 981 popredir(); 982 INTON; 983 if (evalskip == SKIPFUNC) { 984 evalskip = SKIPNONE; 985 skipcount = 0; 986 } 987 if (flags & EV_EXIT) 988 exitshell(exitstatus); 989 break; 990 991 case CMDBUILTIN: 992 case CMDSPLBLTIN: 993 #ifdef DEBUG 994 trputs("builtin command: "); trargs(argv); 995 #endif 996 mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; 997 if (flags == EV_BACKCMD) { 998 memout.nleft = 0; 999 memout.nextc = memout.buf; 1000 memout.bufsize = 64; 1001 mode |= REDIR_BACKQ; 1002 } 1003 e = -1; 1004 savehandler = handler; 1005 savecmdname = commandname; 1006 handler = &jmploc; 1007 temp_path = 0; 1008 if (!setjmp(jmploc.loc)) { 1009 /* We need to ensure the command hash table isn't 1010 * corruped by temporary PATH assignments. 1011 * However we must ensure the 'local' command works! 1012 */ 1013 if (path != pathval() && (cmdentry.u.bltin == hashcmd || 1014 cmdentry.u.bltin == typecmd)) { 1015 savelocalvars = localvars; 1016 localvars = 0; 1017 temp_path = 1; 1018 mklocal(path - 5 /* PATH= */, 0); 1019 } 1020 redirect(cmd->ncmd.redirect, mode); 1021 1022 /* exec is a special builtin, but needs this list... */ 1023 cmdenviron = varlist.list; 1024 /* we must check 'readonly' flag for all builtins */ 1025 listsetvar(varlist.list, 1026 cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET); 1027 commandname = argv[0]; 1028 /* initialize nextopt */ 1029 argptr = argv + 1; 1030 optptr = NULL; 1031 /* and getopt */ 1032 optreset = 1; 1033 optind = 1; 1034 builtin_flags = flags; 1035 exitstatus = cmdentry.u.bltin(argc, argv); 1036 } else { 1037 e = exception; 1038 exitstatus = e == EXINT ? SIGINT + 128 : 1039 e == EXEXEC ? exerrno : 2; 1040 } 1041 handler = savehandler; 1042 flushall(); 1043 out1 = &output; 1044 out2 = &errout; 1045 freestdout(); 1046 if (temp_path) { 1047 poplocalvars(); 1048 localvars = savelocalvars; 1049 } 1050 cmdenviron = NULL; 1051 if (e != EXSHELLPROC) { 1052 commandname = savecmdname; 1053 if (flags & EV_EXIT) 1054 exitshell(exitstatus); 1055 } 1056 if (e != -1) { 1057 if ((e != EXERROR && e != EXEXEC) 1058 || cmdentry.cmdtype == CMDSPLBLTIN) 1059 exraise(e); 1060 FORCEINTON; 1061 } 1062 if (cmdentry.u.bltin != execcmd) 1063 popredir(); 1064 if (flags == EV_BACKCMD) { 1065 backcmd->buf = memout.buf; 1066 backcmd->nleft = memout.nextc - memout.buf; 1067 memout.buf = NULL; 1068 } 1069 break; 1070 1071 default: 1072 #ifdef DEBUG 1073 trputs("normal command: "); trargs(argv); 1074 #endif 1075 redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0); 1076 if (!vforked) 1077 for (sp = varlist.list ; sp ; sp = sp->next) 1078 setvareq(sp->text, VEXPORT|VSTACK); 1079 envp = environment(); 1080 shellexec(argv, envp, path, cmdentry.u.index, vforked); 1081 break; 1082 } 1083 goto out; 1084 1085 parent: /* parent process gets here (if we forked) */ 1086 if (mode == FORK_FG) { /* argument to fork */ 1087 exitstatus = waitforjob(jp); 1088 } else if (mode == FORK_NOJOB) { 1089 backcmd->fd = pip[0]; 1090 close(pip[1]); 1091 backcmd->jp = jp; 1092 } 1093 FORCEINTON; 1094 1095 out: 1096 if (lastarg) 1097 /* dsl: I think this is intended to be used to support 1098 * '_' in 'vi' command mode during line editing... 1099 * However I implemented that within libedit itself. 1100 */ 1101 setvar("_", lastarg, 0); 1102 popstackmark(&smark); 1103 } 1104 1105 1106 /* 1107 * Search for a command. This is called before we fork so that the 1108 * location of the command will be available in the parent as well as 1109 * the child. The check for "goodname" is an overly conservative 1110 * check that the name will not be subject to expansion. 1111 */ 1112 1113 STATIC void 1114 prehash(union node *n) 1115 { 1116 struct cmdentry entry; 1117 1118 if (n && n->type == NCMD && n->ncmd.args) 1119 if (goodname(n->ncmd.args->narg.text)) 1120 find_command(n->ncmd.args->narg.text, &entry, 0, 1121 pathval()); 1122 } 1123 1124 STATIC int 1125 in_function(void) 1126 { 1127 return funcnest; 1128 } 1129 1130 STATIC enum skipstate 1131 current_skipstate(void) 1132 { 1133 return evalskip; 1134 } 1135 1136 STATIC void 1137 stop_skipping(void) 1138 { 1139 evalskip = SKIPNONE; 1140 skipcount = 0; 1141 } 1142 1143 /* 1144 * Builtin commands. Builtin commands whose functions are closely 1145 * tied to evaluation are implemented here. 1146 */ 1147 1148 /* 1149 * No command given. 1150 */ 1151 1152 int 1153 bltincmd(int argc, char **argv) 1154 { 1155 /* 1156 * Preserve exitstatus of a previous possible redirection 1157 * as POSIX mandates 1158 */ 1159 return back_exitstatus; 1160 } 1161 1162 1163 /* 1164 * Handle break and continue commands. Break, continue, and return are 1165 * all handled by setting the evalskip flag. The evaluation routines 1166 * above all check this flag, and if it is set they start skipping 1167 * commands rather than executing them. The variable skipcount is 1168 * the number of loops to break/continue, or the number of function 1169 * levels to return. (The latter is always 1.) It should probably 1170 * be an error to break out of more loops than exist, but it isn't 1171 * in the standard shell so we don't make it one here. 1172 */ 1173 1174 int 1175 breakcmd(int argc, char **argv) 1176 { 1177 int n = argc > 1 ? number(argv[1]) : 1; 1178 1179 if (n > loopnest) 1180 n = loopnest; 1181 if (n > 0) { 1182 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; 1183 skipcount = n; 1184 } 1185 return 0; 1186 } 1187 1188 int 1189 dotcmd(int argc, char **argv) 1190 { 1191 exitstatus = 0; 1192 1193 if (argc >= 2) { /* That's what SVR2 does */ 1194 char *fullname; 1195 /* 1196 * dot_funcnest needs to be 0 when not in a dotcmd, so it 1197 * cannot be restored with (funcnest + 1). 1198 */ 1199 int dot_funcnest_old; 1200 struct stackmark smark; 1201 1202 setstackmark(&smark); 1203 fullname = find_dot_file(argv[1]); 1204 setinputfile(fullname, 1); 1205 commandname = fullname; 1206 dot_funcnest_old = dot_funcnest; 1207 dot_funcnest = funcnest + 1; 1208 cmdloop(0); 1209 dot_funcnest = dot_funcnest_old; 1210 popfile(); 1211 popstackmark(&smark); 1212 } 1213 return exitstatus; 1214 } 1215 1216 /* 1217 * Take commands from a file. To be compatible we should do a path 1218 * search for the file, which is necessary to find sub-commands. 1219 */ 1220 1221 STATIC char * 1222 find_dot_file(char *basename) 1223 { 1224 char *fullname; 1225 const char *path = pathval(); 1226 struct stat statb; 1227 1228 /* don't try this for absolute or relative paths */ 1229 if (strchr(basename, '/')) 1230 return basename; 1231 1232 while ((fullname = padvance(&path, basename)) != NULL) { 1233 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { 1234 /* 1235 * Don't bother freeing here, since it will 1236 * be freed by the caller. 1237 */ 1238 return fullname; 1239 } 1240 stunalloc(fullname); 1241 } 1242 1243 /* not found in the PATH */ 1244 error("%s: not found", basename); 1245 /* NOTREACHED */ 1246 } 1247 1248 1249 1250 /* 1251 * The return command. 1252 * 1253 * Quoth the POSIX standard: 1254 * The return utility shall cause the shell to stop executing the current 1255 * function or dot script. If the shell is not currently executing 1256 * a function or dot script, the results are unspecified. 1257 * 1258 * As for the unspecified part, there seems to be no de-facto standard: bash 1259 * ignores the return with a warning, zsh ignores the return in interactive 1260 * mode but seems to liken it to exit in a script. (checked May 2014) 1261 * 1262 * We choose to silently ignore the return. Older versions of this shell 1263 * set evalskip to SKIPFILE causing the shell to (indirectly) exit. This 1264 * had at least the problem of circumventing the check for stopped jobs, 1265 * which would occur for exit or ^D. 1266 */ 1267 1268 int 1269 returncmd(int argc, char **argv) 1270 { 1271 int ret = argc > 1 ? number(argv[1]) : exitstatus; 1272 1273 if ((dot_funcnest == 0 && funcnest) 1274 || (dot_funcnest > 0 && funcnest - (dot_funcnest - 1) > 0)) { 1275 evalskip = SKIPFUNC; 1276 skipcount = 1; 1277 } else if (dot_funcnest > 0) { 1278 evalskip = SKIPFILE; 1279 skipcount = 1; 1280 } else { 1281 /* XXX: should a warning be issued? */ 1282 ret = 0; 1283 } 1284 1285 return ret; 1286 } 1287 1288 1289 int 1290 falsecmd(int argc, char **argv) 1291 { 1292 return 1; 1293 } 1294 1295 1296 int 1297 truecmd(int argc, char **argv) 1298 { 1299 return 0; 1300 } 1301 1302 1303 int 1304 execcmd(int argc, char **argv) 1305 { 1306 if (argc > 1) { 1307 struct strlist *sp; 1308 1309 iflag = 0; /* exit on error */ 1310 mflag = 0; 1311 optschanged(); 1312 for (sp = cmdenviron; sp; sp = sp->next) 1313 setvareq(sp->text, VEXPORT|VSTACK); 1314 shellexec(argv + 1, environment(), pathval(), 0, 0); 1315 } 1316 return 0; 1317 } 1318 1319 static int 1320 conv_time(clock_t ticks, char *seconds, size_t l) 1321 { 1322 static clock_t tpm = 0; 1323 clock_t mins; 1324 int i; 1325 1326 if (!tpm) 1327 tpm = sysconf(_SC_CLK_TCK) * 60; 1328 1329 mins = ticks / tpm; 1330 snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm ); 1331 1332 if (seconds[0] == '6' && seconds[1] == '0') { 1333 /* 59.99995 got rounded up... */ 1334 mins++; 1335 strlcpy(seconds, "0.0", l); 1336 return mins; 1337 } 1338 1339 /* suppress trailing zeros */ 1340 i = strlen(seconds) - 1; 1341 for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--) 1342 seconds[i] = 0; 1343 return mins; 1344 } 1345 1346 int 1347 timescmd(int argc, char **argv) 1348 { 1349 struct tms tms; 1350 int u, s, cu, cs; 1351 char us[8], ss[8], cus[8], css[8]; 1352 1353 nextopt(""); 1354 1355 times(&tms); 1356 1357 u = conv_time(tms.tms_utime, us, sizeof(us)); 1358 s = conv_time(tms.tms_stime, ss, sizeof(ss)); 1359 cu = conv_time(tms.tms_cutime, cus, sizeof(cus)); 1360 cs = conv_time(tms.tms_cstime, css, sizeof(css)); 1361 1362 outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n", 1363 u, us, s, ss, cu, cus, cs, css); 1364 1365 return 0; 1366 } 1367