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