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