1 /* $OpenBSD: exec.c,v 1.51 2015/04/18 18:28:36 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 5 * 2011, 2012, 2013, 2014, 2015 6 * Thorsten Glaser <tg (at) mirbsd.org> 7 * 8 * Provided that these terms and disclaimer and all copyright notices 9 * are retained or reproduced in an accompanying document, permission 10 * is granted to deal in this work without restriction, including un- 11 * limited rights to use, publicly perform, distribute, sell, modify, 12 * merge, give away, or sublicence. 13 * 14 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 15 * the utmost extent permitted by applicable law, neither express nor 16 * implied; without malicious intent or gross negligence. In no event 17 * may a licensor, author or contributor be held liable for indirect, 18 * direct, other damage, loss, or other issues arising in any way out 19 * of dealing in the work, even if advised of the possibility of such 20 * damage or existence of a defect, except proven that it results out 21 * of said person's immediate fault when using the work as intended. 22 */ 23 24 #include "sh.h" 25 26 __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.137.2.4 2015/04/19 19:18:15 tg Exp $"); 27 28 #ifndef MKSH_DEFAULT_EXECSHELL 29 #define MKSH_DEFAULT_EXECSHELL "/bin/sh" 30 #endif 31 32 static int comexec(struct op *, struct tbl * volatile, const char **, 33 int volatile, volatile int *); 34 static void scriptexec(struct op *, const char **) MKSH_A_NORETURN; 35 static int call_builtin(struct tbl *, const char **, const char *, bool); 36 static int iosetup(struct ioword *, struct tbl *); 37 static int herein(struct ioword *, char **); 38 static const char *do_selectargs(const char **, bool); 39 static Test_op dbteste_isa(Test_env *, Test_meta); 40 static const char *dbteste_getopnd(Test_env *, Test_op, bool); 41 static void dbteste_error(Test_env *, int, const char *); 42 static int search_access(const char *, int); 43 /* XXX: horrible kludge to fit within the framework */ 44 static char *plain_fmt_entry(char *, size_t, unsigned int, const void *); 45 static char *select_fmt_entry(char *, size_t, unsigned int, const void *); 46 47 /* 48 * execute command tree 49 */ 50 int 51 execute(struct op * volatile t, 52 /* if XEXEC don't fork */ 53 volatile int flags, 54 volatile int * volatile xerrok) 55 { 56 int i; 57 volatile int rv = 0, dummy = 0; 58 int pv[2]; 59 const char ** volatile ap = NULL; 60 char ** volatile up; 61 const char *s, *ccp; 62 struct ioword **iowp; 63 struct tbl *tp = NULL; 64 char *cp; 65 66 if (t == NULL) 67 return (0); 68 69 /* Caller doesn't care if XERROK should propagate. */ 70 if (xerrok == NULL) 71 xerrok = &dummy; 72 73 if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE) 74 /* run in sub-process */ 75 return (exchild(t, flags & ~XTIME, xerrok, -1)); 76 77 newenv(E_EXEC); 78 if (trap) 79 runtraps(0); 80 81 /* we want to run an executable, do some variance checks */ 82 if (t->type == TCOM) { 83 /* check if this is 'var=<<EOF' */ 84 /*XXX this is broken, dont use! */ 85 /*XXX https://bugs.launchpad.net/mksh/+bug/1380389 */ 86 if ( 87 /* we have zero arguments, i.e. no programme to run */ 88 t->args[0] == NULL && 89 /* we have exactly one variable assignment */ 90 t->vars[0] != NULL && t->vars[1] == NULL && 91 /* we have exactly one I/O redirection */ 92 t->ioact != NULL && t->ioact[0] != NULL && 93 t->ioact[1] == NULL && 94 /* of type "here document" (or "here string") */ 95 (t->ioact[0]->ioflag & IOTYPE) == IOHERE && 96 /* the variable assignment begins with a valid varname */ 97 (ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] && 98 /* and has no right-hand side (i.e. "varname=") */ 99 ccp[0] == CHAR && ((ccp[1] == '=' && ccp[2] == EOS) || 100 /* or "varname+=" */ (ccp[1] == '+' && ccp[2] == CHAR && 101 ccp[3] == '=' && ccp[4] == EOS)) && 102 /* plus we can have a here document content */ 103 herein(t->ioact[0], &cp) == 0 && cp && *cp) { 104 char *sp = cp, *dp; 105 size_t n = ccp - t->vars[0] + (ccp[1] == '+' ? 4 : 2); 106 size_t z; 107 108 /* drop redirection (will be garbage collected) */ 109 t->ioact = NULL; 110 111 /* set variable to its expanded value */ 112 z = strlen(cp); 113 if (notoktomul(z, 2) || notoktoadd(z * 2, n + 1)) 114 internal_errorf(Toomem, (size_t)-1); 115 dp = alloc(z * 2 + n + 1, APERM); 116 memcpy(dp, t->vars[0], n); 117 t->vars[0] = dp; 118 dp += n; 119 while (*sp) { 120 *dp++ = QCHAR; 121 *dp++ = *sp++; 122 } 123 *dp = EOS; 124 /* free the expanded value */ 125 afree(cp, APERM); 126 } 127 128 /* 129 * Clear subst_exstat before argument expansion. Used by 130 * null commands (see comexec() and c_eval()) and by c_set(). 131 */ 132 subst_exstat = 0; 133 134 /* for $LINENO */ 135 current_lineno = t->lineno; 136 137 /* 138 * POSIX says expand command words first, then redirections, 139 * and assignments last.. 140 */ 141 up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE); 142 if (flags & XTIME) 143 /* Allow option parsing (bizarre, but POSIX) */ 144 timex_hook(t, &up); 145 ap = (const char **)up; 146 if (ap[0]) 147 tp = findcom(ap[0], FC_BI|FC_FUNC); 148 } 149 flags &= ~XTIME; 150 151 if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) { 152 e->savefd = alloc2(NUFILE, sizeof(short), ATEMP); 153 /* initialise to not redirected */ 154 memset(e->savefd, 0, NUFILE * sizeof(short)); 155 } 156 157 /* mark for replacement later (unless TPIPE) */ 158 vp_pipest->flag |= INT_L; 159 160 /* do redirection, to be restored in quitenv() */ 161 if (t->ioact != NULL) 162 for (iowp = t->ioact; *iowp != NULL; iowp++) { 163 if (iosetup(*iowp, tp) < 0) { 164 exstat = rv = 1; 165 /* 166 * Redirection failures for special commands 167 * cause (non-interactive) shell to exit. 168 */ 169 if (tp && tp->type == CSHELL && 170 (tp->flag & SPEC_BI)) 171 errorfz(); 172 /* Deal with FERREXIT, quitenv(), etc. */ 173 goto Break; 174 } 175 } 176 177 switch (t->type) { 178 case TCOM: 179 rv = comexec(t, tp, (const char **)ap, flags, xerrok); 180 break; 181 182 case TPAREN: 183 rv = execute(t->left, flags | XFORK, xerrok); 184 break; 185 186 case TPIPE: 187 flags |= XFORK; 188 flags &= ~XEXEC; 189 e->savefd[0] = savefd(0); 190 e->savefd[1] = savefd(1); 191 while (t->type == TPIPE) { 192 openpipe(pv); 193 /* stdout of curr */ 194 ksh_dup2(pv[1], 1, false); 195 /** 196 * Let exchild() close pv[0] in child 197 * (if this isn't done, commands like 198 * (: ; cat /etc/termcap) | sleep 1 199 * will hang forever). 200 */ 201 exchild(t->left, flags | XPIPEO | XCCLOSE, 202 NULL, pv[0]); 203 /* stdin of next */ 204 ksh_dup2(pv[0], 0, false); 205 closepipe(pv); 206 flags |= XPIPEI; 207 t = t->right; 208 } 209 /* stdout of last */ 210 restfd(1, e->savefd[1]); 211 /* no need to re-restore this */ 212 e->savefd[1] = 0; 213 /* Let exchild() close 0 in parent, after fork, before wait */ 214 i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0); 215 if (!(flags&XBGND) && !(flags&XXCOM)) 216 rv = i; 217 break; 218 219 case TLIST: 220 while (t->type == TLIST) { 221 execute(t->left, flags & XERROK, NULL); 222 t = t->right; 223 } 224 rv = execute(t, flags & XERROK, xerrok); 225 break; 226 227 case TCOPROC: { 228 #ifndef MKSH_NOPROSPECTOFWORK 229 sigset_t omask; 230 231 /* 232 * Block sigchild as we are using things changed in the 233 * signal handler 234 */ 235 sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); 236 e->type = E_ERRH; 237 if ((i = kshsetjmp(e->jbuf))) { 238 sigprocmask(SIG_SETMASK, &omask, NULL); 239 quitenv(NULL); 240 unwind(i); 241 /* NOTREACHED */ 242 } 243 #endif 244 /* Already have a (live) co-process? */ 245 if (coproc.job && coproc.write >= 0) 246 errorf("coprocess already exists"); 247 248 /* Can we re-use the existing co-process pipe? */ 249 coproc_cleanup(true); 250 251 /* do this before opening pipes, in case these fail */ 252 e->savefd[0] = savefd(0); 253 e->savefd[1] = savefd(1); 254 255 openpipe(pv); 256 if (pv[0] != 0) { 257 ksh_dup2(pv[0], 0, false); 258 close(pv[0]); 259 } 260 coproc.write = pv[1]; 261 coproc.job = NULL; 262 263 if (coproc.readw >= 0) 264 ksh_dup2(coproc.readw, 1, false); 265 else { 266 openpipe(pv); 267 coproc.read = pv[0]; 268 ksh_dup2(pv[1], 1, false); 269 /* closed before first read */ 270 coproc.readw = pv[1]; 271 coproc.njobs = 0; 272 /* create new coprocess id */ 273 ++coproc.id; 274 } 275 #ifndef MKSH_NOPROSPECTOFWORK 276 sigprocmask(SIG_SETMASK, &omask, NULL); 277 /* no more need for error handler */ 278 e->type = E_EXEC; 279 #endif 280 281 /* 282 * exchild() closes coproc.* in child after fork, 283 * will also increment coproc.njobs when the 284 * job is actually created. 285 */ 286 flags &= ~XEXEC; 287 exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE, 288 NULL, coproc.readw); 289 break; 290 } 291 292 case TASYNC: 293 /* 294 * XXX non-optimal, I think - "(foo &)", forks for (), 295 * forks again for async... parent should optimise 296 * this to "foo &"... 297 */ 298 rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok); 299 break; 300 301 case TOR: 302 case TAND: 303 rv = execute(t->left, XERROK, xerrok); 304 if ((rv == 0) == (t->type == TAND)) 305 rv = execute(t->right, flags & XERROK, xerrok); 306 else { 307 flags |= XERROK; 308 if (xerrok) 309 *xerrok = 1; 310 } 311 break; 312 313 case TBANG: 314 rv = !execute(t->right, XERROK, xerrok); 315 flags |= XERROK; 316 if (xerrok) 317 *xerrok = 1; 318 break; 319 320 case TDBRACKET: { 321 Test_env te; 322 323 te.flags = TEF_DBRACKET; 324 te.pos.wp = t->args; 325 te.isa = dbteste_isa; 326 te.getopnd = dbteste_getopnd; 327 te.eval = test_eval; 328 te.error = dbteste_error; 329 330 rv = test_parse(&te); 331 break; 332 } 333 334 case TFOR: 335 case TSELECT: { 336 volatile bool is_first = true; 337 338 ap = (t->vars == NULL) ? e->loc->argv + 1 : 339 (const char **)eval((const char **)t->vars, 340 DOBLANK | DOGLOB | DOTILDE); 341 e->type = E_LOOP; 342 while ((i = kshsetjmp(e->jbuf))) { 343 if ((e->flags&EF_BRKCONT_PASS) || 344 (i != LBREAK && i != LCONTIN)) { 345 quitenv(NULL); 346 unwind(i); 347 } else if (i == LBREAK) { 348 rv = 0; 349 goto Break; 350 } 351 } 352 /* in case of a continue */ 353 rv = 0; 354 if (t->type == TFOR) { 355 while (*ap != NULL) { 356 setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); 357 rv = execute(t->left, flags & XERROK, xerrok); 358 } 359 } else { 360 /* TSELECT */ 361 for (;;) { 362 if (!(ccp = do_selectargs(ap, is_first))) { 363 rv = 1; 364 break; 365 } 366 is_first = false; 367 setstr(global(t->str), ccp, KSH_UNWIND_ERROR); 368 execute(t->left, flags & XERROK, xerrok); 369 } 370 } 371 break; 372 } 373 374 case TWHILE: 375 case TUNTIL: 376 e->type = E_LOOP; 377 while ((i = kshsetjmp(e->jbuf))) { 378 if ((e->flags&EF_BRKCONT_PASS) || 379 (i != LBREAK && i != LCONTIN)) { 380 quitenv(NULL); 381 unwind(i); 382 } else if (i == LBREAK) { 383 rv = 0; 384 goto Break; 385 } 386 } 387 /* in case of a continue */ 388 rv = 0; 389 while ((execute(t->left, XERROK, NULL) == 0) == 390 (t->type == TWHILE)) 391 rv = execute(t->right, flags & XERROK, xerrok); 392 break; 393 394 case TIF: 395 case TELIF: 396 if (t->right == NULL) 397 /* should be error */ 398 break; 399 rv = execute(t->left, XERROK, NULL) == 0 ? 400 execute(t->right->left, flags & XERROK, xerrok) : 401 execute(t->right->right, flags & XERROK, xerrok); 402 break; 403 404 case TCASE: 405 i = 0; 406 ccp = evalstr(t->str, DOTILDE | DOSCALAR); 407 for (t = t->left; t != NULL && t->type == TPAT; t = t->right) { 408 for (ap = (const char **)t->vars; *ap; ap++) { 409 if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) && 410 gmatchx(ccp, s, false))) { 411 rv = execute(t->left, flags & XERROK, 412 xerrok); 413 i = 0; 414 switch (t->u.charflag) { 415 case '&': 416 i = 1; 417 /* FALLTHROUGH */ 418 case '|': 419 goto TCASE_next; 420 } 421 goto TCASE_out; 422 } 423 } 424 i = 0; 425 TCASE_next: 426 /* empty */; 427 } 428 TCASE_out: 429 break; 430 431 case TBRACE: 432 rv = execute(t->left, flags & XERROK, xerrok); 433 break; 434 435 case TFUNCT: 436 rv = define(t->str, t); 437 break; 438 439 case TTIME: 440 /* 441 * Clear XEXEC so nested execute() call doesn't exit 442 * (allows "ls -l | time grep foo"). 443 */ 444 rv = timex(t, flags & ~XEXEC, xerrok); 445 break; 446 447 case TEXEC: 448 /* an eval'd TCOM */ 449 up = makenv(); 450 restoresigs(); 451 cleanup_proc_env(); 452 { 453 union mksh_ccphack cargs; 454 455 cargs.ro = t->args; 456 execve(t->str, cargs.rw, up); 457 rv = errno; 458 } 459 if (rv == ENOEXEC) 460 scriptexec(t, (const char **)up); 461 else 462 errorf("%s: %s", t->str, cstrerror(rv)); 463 } 464 Break: 465 exstat = rv & 0xFF; 466 if (vp_pipest->flag & INT_L) { 467 unset(vp_pipest, 1); 468 vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY | 469 ARRAY | INT_U | INT_L; 470 vp_pipest->val.i = rv; 471 } 472 473 /* restores IO */ 474 quitenv(NULL); 475 if ((flags&XEXEC)) 476 /* exit child */ 477 unwind(LEXIT); 478 if (rv != 0 && !(flags & XERROK) && 479 (xerrok == NULL || !*xerrok)) { 480 if (Flag(FERREXIT) & 0x80) { 481 /* inside eval */ 482 Flag(FERREXIT) = 0; 483 } else { 484 trapsig(ksh_SIGERR); 485 if (Flag(FERREXIT)) 486 unwind(LERROR); 487 } 488 } 489 return (rv); 490 } 491 492 /* 493 * execute simple command 494 */ 495 496 static int 497 comexec(struct op *t, struct tbl * volatile tp, const char **ap, 498 volatile int flags, volatile int *xerrok) 499 { 500 int i; 501 volatile int rv = 0; 502 const char *cp; 503 const char **lastp; 504 /* Must be static (XXX but why?) */ 505 static struct op texec; 506 int type_flags; 507 bool resetspec; 508 int fcflags = FC_BI|FC_FUNC|FC_PATH; 509 struct block *l_expand, *l_assign; 510 int optc; 511 const char *exec_argv0 = NULL; 512 bool exec_clrenv = false; 513 514 /* snag the last argument for $_ */ 515 if (Flag(FTALKING) && *(lastp = ap)) { 516 /* 517 * XXX not the same as AT&T ksh, which only seems to set $_ 518 * after a newline (but not in functions/dot scripts, but in 519 * interactive and script) - perhaps save last arg here and 520 * set it in shell()?. 521 */ 522 while (*++lastp) 523 ; 524 /* setstr() can't fail here */ 525 setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp, 526 KSH_RETURN_ERROR); 527 } 528 529 /** 530 * Deal with the shell builtins builtin, exec and command since 531 * they can be followed by other commands. This must be done before 532 * we know if we should create a local block which must be done 533 * before we can do a path search (in case the assignments change 534 * PATH). 535 * Odd cases: 536 * FOO=bar exec >/dev/null FOO is kept but not exported 537 * FOO=bar exec foobar FOO is exported 538 * FOO=bar command exec >/dev/null FOO is neither kept nor exported 539 * FOO=bar command FOO is neither kept nor exported 540 * PATH=... foobar use new PATH in foobar search 541 */ 542 resetspec = false; 543 while (tp && tp->type == CSHELL) { 544 /* undo effects of command */ 545 fcflags = FC_BI|FC_FUNC|FC_PATH; 546 if (tp->val.f == c_builtin) { 547 if ((cp = *++ap) == NULL || 548 (!strcmp(cp, "--") && (cp = *++ap) == NULL)) { 549 tp = NULL; 550 break; 551 } 552 if ((tp = findcom(cp, FC_BI)) == NULL) 553 errorf("%s: %s: %s", Tbuiltin, cp, "not a builtin"); 554 continue; 555 } else if (tp->val.f == c_exec) { 556 if (ap[1] == NULL) 557 break; 558 ksh_getopt_reset(&builtin_opt, GF_ERROR); 559 while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1) 560 switch (optc) { 561 case 'a': 562 exec_argv0 = builtin_opt.optarg; 563 break; 564 case 'c': 565 exec_clrenv = true; 566 /* ensure we can actually do this */ 567 resetspec = true; 568 break; 569 default: 570 rv = 2; 571 goto Leave; 572 } 573 ap += builtin_opt.optind; 574 flags |= XEXEC; 575 } else if (tp->val.f == c_command) { 576 bool saw_p = false; 577 578 /* 579 * Ugly dealing with options in two places (here 580 * and in c_command(), but such is life) 581 */ 582 ksh_getopt_reset(&builtin_opt, 0); 583 while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p') 584 saw_p = true; 585 if (optc != -1) 586 /* command -vV or something */ 587 break; 588 /* don't look for functions */ 589 fcflags = FC_BI|FC_PATH; 590 if (saw_p) { 591 if (Flag(FRESTRICTED)) { 592 warningf(true, "%s: %s", 593 "command -p", "restricted"); 594 rv = 1; 595 goto Leave; 596 } 597 fcflags |= FC_DEFPATH; 598 } 599 ap += builtin_opt.optind; 600 /* 601 * POSIX says special builtins lose their status 602 * if accessed using command. 603 */ 604 resetspec = true; 605 if (!ap[0]) { 606 /* ensure command with no args exits with 0 */ 607 subst_exstat = 0; 608 break; 609 } 610 #ifndef MKSH_NO_EXTERNAL_CAT 611 } else if (tp->val.f == c_cat) { 612 /* 613 * if we have any flags, do not use the builtin 614 * in theory, we could allow -u, but that would 615 * mean to use ksh_getopt here and possibly ad- 616 * ded complexity and more code and isn't worth 617 * additional hassle (and the builtin must call 618 * ksh_getopt already but can't come back here) 619 */ 620 if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' && 621 /* argument, begins with -, is not - or -- */ 622 (ap[1][1] != '-' || ap[1][2] != '\0')) 623 /* don't look for builtins or functions */ 624 fcflags = FC_PATH; 625 else 626 /* go on, use the builtin */ 627 break; 628 #endif 629 } else if (tp->val.f == c_trap) { 630 t->u.evalflags &= ~DOTCOMEXEC; 631 break; 632 } else 633 break; 634 tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC)); 635 } 636 if (t->u.evalflags & DOTCOMEXEC) 637 flags |= XEXEC; 638 l_expand = e->loc; 639 if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN)))) 640 type_flags = 0; 641 else { 642 /* create new variable/function block */ 643 newblock(); 644 /* ksh functions don't keep assignments, POSIX functions do. */ 645 if (!resetspec && tp && tp->type == CFUNC && 646 !(tp->flag & FKSH)) 647 type_flags = EXPORT; 648 else 649 type_flags = LOCAL|LOCAL_COPY|EXPORT; 650 } 651 l_assign = e->loc; 652 if (exec_clrenv) 653 l_assign->flags |= BF_STOPENV; 654 if (Flag(FEXPORT)) 655 type_flags |= EXPORT; 656 if (Flag(FXTRACE)) 657 change_xtrace(2, false); 658 for (i = 0; t->vars[i]; i++) { 659 /* do NOT lookup in the new var/fn block just created */ 660 e->loc = l_expand; 661 cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR); 662 e->loc = l_assign; 663 if (Flag(FXTRACE)) { 664 const char *ccp; 665 666 ccp = skip_varname(cp, true); 667 if (*ccp == '+') 668 ++ccp; 669 if (*ccp == '=') 670 ++ccp; 671 shf_write(cp, ccp - cp, shl_xtrace); 672 print_value_quoted(shl_xtrace, ccp); 673 shf_putc(' ', shl_xtrace); 674 } 675 /* but assign in there as usual */ 676 typeset(cp, type_flags, 0, 0, 0); 677 } 678 679 if (Flag(FXTRACE)) { 680 change_xtrace(2, false); 681 if (ap[rv = 0]) { 682 xtrace_ap_loop: 683 print_value_quoted(shl_xtrace, ap[rv]); 684 if (ap[++rv]) { 685 shf_putc(' ', shl_xtrace); 686 goto xtrace_ap_loop; 687 } 688 } 689 change_xtrace(1, false); 690 } 691 692 if ((cp = *ap) == NULL) { 693 rv = subst_exstat; 694 goto Leave; 695 } else if (!tp) { 696 if (Flag(FRESTRICTED) && vstrchr(cp, '/')) { 697 warningf(true, "%s: %s", cp, "restricted"); 698 rv = 1; 699 goto Leave; 700 } 701 tp = findcom(cp, fcflags); 702 } 703 704 switch (tp->type) { 705 706 /* shell built-in */ 707 case CSHELL: 708 rv = call_builtin(tp, (const char **)ap, null, resetspec); 709 if (resetspec && tp->val.f == c_shift) { 710 l_expand->argc = l_assign->argc; 711 l_expand->argv = l_assign->argv; 712 } 713 break; 714 715 /* function call */ 716 case CFUNC: { 717 volatile unsigned char old_xflag; 718 volatile uint32_t old_inuse; 719 const char * volatile old_kshname; 720 721 if (!(tp->flag & ISSET)) { 722 struct tbl *ftp; 723 724 if (!tp->u.fpath) { 725 rv = (tp->u2.errnov == ENOENT) ? 127 : 126; 726 warningf(true, "%s: %s %s: %s", cp, 727 "can't find", "function definition file", 728 cstrerror(tp->u2.errnov)); 729 break; 730 } 731 if (include(tp->u.fpath, 0, NULL, false) < 0) { 732 warningf(true, "%s: %s %s %s: %s", cp, 733 "can't open", "function definition file", 734 tp->u.fpath, cstrerror(errno)); 735 rv = 127; 736 break; 737 } 738 if (!(ftp = findfunc(cp, hash(cp), false)) || 739 !(ftp->flag & ISSET)) { 740 warningf(true, "%s: %s %s", cp, 741 "function not defined by", tp->u.fpath); 742 rv = 127; 743 break; 744 } 745 tp = ftp; 746 } 747 748 /* 749 * ksh functions set $0 to function name, POSIX 750 * functions leave $0 unchanged. 751 */ 752 old_kshname = kshname; 753 if (tp->flag & FKSH) 754 kshname = ap[0]; 755 else 756 ap[0] = kshname; 757 e->loc->argv = ap; 758 for (i = 0; *ap++ != NULL; i++) 759 ; 760 e->loc->argc = i - 1; 761 /* 762 * ksh-style functions handle getopts sanely, 763 * Bourne/POSIX functions are insane... 764 */ 765 if (tp->flag & FKSH) { 766 e->loc->flags |= BF_DOGETOPTS; 767 e->loc->getopts_state = user_opt; 768 getopts_reset(1); 769 } 770 771 old_xflag = Flag(FXTRACE) ? 1 : 0; 772 change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) | 773 ((tp->flag & TRACE) ? 1 : 0), false); 774 old_inuse = tp->flag & FINUSE; 775 tp->flag |= FINUSE; 776 777 e->type = E_FUNC; 778 if (!(i = kshsetjmp(e->jbuf))) { 779 execute(tp->val.t, flags & XERROK, NULL); 780 i = LRETURN; 781 } 782 783 kshname = old_kshname; 784 change_xtrace(old_xflag, false); 785 tp->flag = (tp->flag & ~FINUSE) | old_inuse; 786 787 /* 788 * Were we deleted while executing? If so, free the 789 * execution tree. 790 */ 791 if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) { 792 if (tp->flag & ALLOC) { 793 tp->flag &= ~ALLOC; 794 tfree(tp->val.t, tp->areap); 795 } 796 tp->flag = 0; 797 } 798 switch (i) { 799 case LRETURN: 800 case LERROR: 801 rv = exstat & 0xFF; 802 break; 803 case LINTR: 804 case LEXIT: 805 case LLEAVE: 806 case LSHELL: 807 quitenv(NULL); 808 unwind(i); 809 /* NOTREACHED */ 810 default: 811 quitenv(NULL); 812 internal_errorf("%s %d", "CFUNC", i); 813 } 814 break; 815 } 816 817 /* executable command */ 818 case CEXEC: 819 /* tracked alias */ 820 case CTALIAS: 821 if (!(tp->flag&ISSET)) { 822 if (tp->u2.errnov == ENOENT) { 823 rv = 127; 824 warningf(true, "%s: %s", cp, "not found"); 825 } else { 826 rv = 126; 827 warningf(true, "%s: %s: %s", cp, "can't execute", 828 cstrerror(tp->u2.errnov)); 829 } 830 break; 831 } 832 833 /* set $_ to program's full path */ 834 /* setstr() can't fail here */ 835 setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0), 836 tp->val.s, KSH_RETURN_ERROR); 837 838 /* to fork, we set up a TEXEC node and call execute */ 839 texec.type = TEXEC; 840 /* for vistree/dumptree */ 841 texec.left = t; 842 texec.str = tp->val.s; 843 texec.args = ap; 844 845 /* in this case we do not fork, of course */ 846 if (flags & XEXEC) { 847 if (exec_argv0) 848 texec.args[0] = exec_argv0; 849 j_exit(); 850 if (!(flags & XBGND) 851 #ifndef MKSH_UNEMPLOYED 852 || Flag(FMONITOR) 853 #endif 854 ) { 855 setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG); 856 setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG); 857 } 858 } 859 860 rv = exchild(&texec, flags, xerrok, -1); 861 break; 862 } 863 Leave: 864 if (flags & XEXEC) { 865 exstat = rv & 0xFF; 866 unwind(LLEAVE); 867 } 868 return (rv); 869 } 870 871 static void 872 scriptexec(struct op *tp, const char **ap) 873 { 874 const char *sh; 875 #ifndef MKSH_SMALL 876 int fd; 877 unsigned char buf[68]; 878 #endif 879 union mksh_ccphack args, cap; 880 881 sh = str_val(global("EXECSHELL")); 882 if (sh && *sh) 883 sh = search_path(sh, path, X_OK, NULL); 884 if (!sh || !*sh) 885 sh = MKSH_DEFAULT_EXECSHELL; 886 887 *tp->args-- = tp->str; 888 889 #ifndef MKSH_SMALL 890 if ((fd = open(tp->str, O_RDONLY | O_BINARY)) >= 0) { 891 unsigned char *cp; 892 unsigned short m; 893 ssize_t n; 894 895 /* read first couple of octets from file */ 896 n = read(fd, buf, sizeof(buf) - 1); 897 close(fd); 898 /* read error or short read? */ 899 if (n < 5) 900 goto nomagic; 901 /* terminate buffer */ 902 buf[n] = '\0'; 903 904 /* skip UTF-8 Byte Order Mark, if present */ 905 cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) && 906 (buf[2] == 0xBF)) ? 3 : 0); 907 908 /* scan for newline or NUL (end of buffer) */ 909 while (*cp && *cp != '\n') 910 ++cp; 911 /* if the shebang line is longer than MAXINTERP, bail out */ 912 if (!*cp) 913 goto noshebang; 914 /* replace newline by NUL */ 915 *cp = '\0'; 916 917 /* restore begin of shebang position (buf+0 or buf+3) */ 918 cp = buf + n; 919 /* bail out if no shebang magic found */ 920 if ((cp[0] != '#') || (cp[1] != '!')) 921 goto noshebang; 922 923 cp += 2; 924 /* skip whitespace before shell name */ 925 while (*cp == ' ' || *cp == '\t') 926 ++cp; 927 /* just whitespace on the line? */ 928 if (*cp == '\0') 929 goto noshebang; 930 /* no, we actually found an interpreter name */ 931 sh = (char *)cp; 932 /* look for end of shell/interpreter name */ 933 while (*cp != ' ' && *cp != '\t' && *cp != '\0') 934 ++cp; 935 /* any arguments? */ 936 if (*cp) { 937 *cp++ = '\0'; 938 /* skip spaces before arguments */ 939 while (*cp == ' ' || *cp == '\t') 940 ++cp; 941 /* pass it all in ONE argument (historic reasons) */ 942 if (*cp) 943 *tp->args-- = (char *)cp; 944 } 945 goto nomagic; 946 noshebang: 947 m = buf[0] << 8 | buf[1]; 948 if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F') 949 errorf("%s: not executable: %d-bit ELF file", tp->str, 950 32 * buf[4]); 951 if ((m == /* OMAGIC */ 0407) || 952 (m == /* NMAGIC */ 0410) || 953 (m == /* ZMAGIC */ 0413) || 954 (m == /* QMAGIC */ 0314) || 955 (m == /* ECOFF_I386 */ 0x4C01) || 956 (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) || 957 (m == /* ECOFF_SH */ 0x0500 || m == 0x0005) || 958 (m == /* "MZ" */ 0x4D5A) || 959 (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D)) 960 errorf("%s: not executable: magic %04X", tp->str, m); 961 nomagic: 962 ; 963 } 964 #endif 965 args.ro = tp->args; 966 *args.ro = sh; 967 968 cap.ro = ap; 969 execve(args.rw[0], args.rw, cap.rw); 970 971 /* report both the programme that was run and the bogus interpreter */ 972 errorf("%s: %s: %s", tp->str, sh, cstrerror(errno)); 973 } 974 975 int 976 shcomexec(const char **wp) 977 { 978 struct tbl *tp; 979 980 tp = ktsearch(&builtins, *wp, hash(*wp)); 981 return (call_builtin(tp, wp, "shcomexec", false)); 982 } 983 984 /* 985 * Search function tables for a function. If create set, a table entry 986 * is created if none is found. 987 */ 988 struct tbl * 989 findfunc(const char *name, uint32_t h, bool create) 990 { 991 struct block *l; 992 struct tbl *tp = NULL; 993 994 for (l = e->loc; l; l = l->next) { 995 tp = ktsearch(&l->funs, name, h); 996 if (tp) 997 break; 998 if (!l->next && create) { 999 tp = ktenter(&l->funs, name, h); 1000 tp->flag = DEFINED; 1001 tp->type = CFUNC; 1002 tp->val.t = NULL; 1003 break; 1004 } 1005 } 1006 return (tp); 1007 } 1008 1009 /* 1010 * define function. Returns 1 if function is being undefined (t == 0) and 1011 * function did not exist, returns 0 otherwise. 1012 */ 1013 int 1014 define(const char *name, struct op *t) 1015 { 1016 uint32_t nhash; 1017 struct tbl *tp; 1018 bool was_set = false; 1019 1020 nhash = hash(name); 1021 1022 if (t != NULL && !tobool(t->u.ksh_func)) { 1023 /* drop same-name aliases for POSIX functions */ 1024 if ((tp = ktsearch(&aliases, name, nhash))) 1025 ktdelete(tp); 1026 } 1027 1028 while (/* CONSTCOND */ 1) { 1029 tp = findfunc(name, nhash, true); 1030 1031 if (tp->flag & ISSET) 1032 was_set = true; 1033 /* 1034 * If this function is currently being executed, we zap 1035 * this table entry so findfunc() won't see it 1036 */ 1037 if (tp->flag & FINUSE) { 1038 tp->name[0] = '\0'; 1039 /* ensure it won't be found */ 1040 tp->flag &= ~DEFINED; 1041 tp->flag |= FDELETE; 1042 } else 1043 break; 1044 } 1045 1046 if (tp->flag & ALLOC) { 1047 tp->flag &= ~(ISSET|ALLOC); 1048 tfree(tp->val.t, tp->areap); 1049 } 1050 1051 if (t == NULL) { 1052 /* undefine */ 1053 ktdelete(tp); 1054 return (was_set ? 0 : 1); 1055 } 1056 1057 tp->val.t = tcopy(t->left, tp->areap); 1058 tp->flag |= (ISSET|ALLOC); 1059 if (t->u.ksh_func) 1060 tp->flag |= FKSH; 1061 1062 return (0); 1063 } 1064 1065 /* 1066 * add builtin 1067 */ 1068 const char * 1069 builtin(const char *name, int (*func) (const char **)) 1070 { 1071 struct tbl *tp; 1072 uint32_t flag = DEFINED; 1073 1074 /* see if any flags should be set for this builtin */ 1075 while (1) { 1076 if (*name == '=') 1077 /* command does variable assignment */ 1078 flag |= KEEPASN; 1079 else if (*name == '*') 1080 /* POSIX special builtin */ 1081 flag |= SPEC_BI; 1082 else 1083 break; 1084 name++; 1085 } 1086 1087 tp = ktenter(&builtins, name, hash(name)); 1088 tp->flag = flag; 1089 tp->type = CSHELL; 1090 tp->val.f = func; 1091 1092 return (name); 1093 } 1094 1095 /* 1096 * find command 1097 * either function, hashed command, or built-in (in that order) 1098 */ 1099 struct tbl * 1100 findcom(const char *name, int flags) 1101 { 1102 static struct tbl temp; 1103 uint32_t h = hash(name); 1104 struct tbl *tp = NULL, *tbi; 1105 /* insert if not found */ 1106 unsigned char insert = Flag(FTRACKALL); 1107 /* for function autoloading */ 1108 char *fpath; 1109 union mksh_cchack npath; 1110 1111 if (vstrchr(name, '/')) { 1112 insert = 0; 1113 /* prevent FPATH search below */ 1114 flags &= ~FC_FUNC; 1115 goto Search; 1116 } 1117 tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL; 1118 /* 1119 * POSIX says special builtins first, then functions, then 1120 * regular builtins, then search path... 1121 */ 1122 if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI)) 1123 tp = tbi; 1124 if (!tp && (flags & FC_FUNC)) { 1125 tp = findfunc(name, h, false); 1126 if (tp && !(tp->flag & ISSET)) { 1127 if ((fpath = str_val(global("FPATH"))) == null) { 1128 tp->u.fpath = NULL; 1129 tp->u2.errnov = ENOENT; 1130 } else 1131 tp->u.fpath = search_path(name, fpath, R_OK, 1132 &tp->u2.errnov); 1133 } 1134 } 1135 if (!tp && (flags & FC_NORMBI) && tbi) 1136 tp = tbi; 1137 if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) { 1138 tp = ktsearch(&taliases, name, h); 1139 if (tp && (tp->flag & ISSET) && 1140 ksh_access(tp->val.s, X_OK) != 0) { 1141 if (tp->flag & ALLOC) { 1142 tp->flag &= ~ALLOC; 1143 afree(tp->val.s, APERM); 1144 } 1145 tp->flag &= ~ISSET; 1146 } 1147 } 1148 1149 Search: 1150 if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) && 1151 (flags & FC_PATH)) { 1152 if (!tp) { 1153 if (insert && !(flags & FC_DEFPATH)) { 1154 tp = ktenter(&taliases, name, h); 1155 tp->type = CTALIAS; 1156 } else { 1157 tp = &temp; 1158 tp->type = CEXEC; 1159 } 1160 /* make ~ISSET */ 1161 tp->flag = DEFINED; 1162 } 1163 npath.ro = search_path(name, 1164 (flags & FC_DEFPATH) ? def_path : path, 1165 X_OK, &tp->u2.errnov); 1166 if (npath.ro) { 1167 strdupx(tp->val.s, npath.ro, APERM); 1168 if (npath.ro != name) 1169 afree(npath.rw, ATEMP); 1170 tp->flag |= ISSET|ALLOC; 1171 } else if ((flags & FC_FUNC) && 1172 (fpath = str_val(global("FPATH"))) != null && 1173 (npath.ro = search_path(name, fpath, R_OK, 1174 &tp->u2.errnov)) != NULL) { 1175 /* 1176 * An undocumented feature of AT&T ksh is that 1177 * it searches FPATH if a command is not found, 1178 * even if the command hasn't been set up as an 1179 * autoloaded function (ie, no typeset -uf). 1180 */ 1181 tp = &temp; 1182 tp->type = CFUNC; 1183 /* make ~ISSET */ 1184 tp->flag = DEFINED; 1185 tp->u.fpath = npath.ro; 1186 } 1187 } 1188 return (tp); 1189 } 1190 1191 /* 1192 * flush executable commands with relative paths 1193 * (just relative or all?) 1194 */ 1195 void 1196 flushcom(bool all) 1197 { 1198 struct tbl *tp; 1199 struct tstate ts; 1200 1201 for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; ) 1202 if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) { 1203 if (tp->flag&ALLOC) { 1204 tp->flag &= ~(ALLOC|ISSET); 1205 afree(tp->val.s, APERM); 1206 } 1207 tp->flag &= ~ISSET; 1208 } 1209 } 1210 1211 /* check if path is something we want to find */ 1212 static int 1213 search_access(const char *fn, int mode) 1214 { 1215 struct stat sb; 1216 1217 if (stat(fn, &sb) < 0) 1218 /* file does not exist */ 1219 return (ENOENT); 1220 /* LINTED use of access */ 1221 if (access(fn, mode) < 0) 1222 /* file exists, but we can't access it */ 1223 return (errno); 1224 if (mode == X_OK && (!S_ISREG(sb.st_mode) || 1225 !(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) 1226 /* access(2) may say root can execute everything */ 1227 return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES); 1228 return (0); 1229 } 1230 1231 /* 1232 * search for command with PATH 1233 */ 1234 const char * 1235 search_path(const char *name, const char *lpath, 1236 /* R_OK or X_OK */ 1237 int mode, 1238 /* set if candidate found, but not suitable */ 1239 int *errnop) 1240 { 1241 const char *sp, *p; 1242 char *xp; 1243 XString xs; 1244 size_t namelen; 1245 int ec = 0, ev; 1246 1247 if (vstrchr(name, '/')) { 1248 if ((ec = search_access(name, mode)) == 0) { 1249 search_path_ok: 1250 if (errnop) 1251 *errnop = 0; 1252 return (name); 1253 } 1254 goto search_path_err; 1255 } 1256 1257 namelen = strlen(name) + 1; 1258 Xinit(xs, xp, 128, ATEMP); 1259 1260 sp = lpath; 1261 while (sp != NULL) { 1262 xp = Xstring(xs, xp); 1263 if (!(p = cstrchr(sp, ':'))) 1264 p = sp + strlen(sp); 1265 if (p != sp) { 1266 XcheckN(xs, xp, p - sp); 1267 memcpy(xp, sp, p - sp); 1268 xp += p - sp; 1269 *xp++ = '/'; 1270 } 1271 sp = p; 1272 XcheckN(xs, xp, namelen); 1273 memcpy(xp, name, namelen); 1274 if ((ev = search_access(Xstring(xs, xp), mode)) == 0) { 1275 name = Xclose(xs, xp + namelen); 1276 goto search_path_ok; 1277 } 1278 /* accumulate non-ENOENT errors only */ 1279 if (ev != ENOENT && ec == 0) 1280 ec = ev; 1281 if (*sp++ == '\0') 1282 sp = NULL; 1283 } 1284 Xfree(xs, xp); 1285 search_path_err: 1286 if (errnop) 1287 *errnop = ec ? ec : ENOENT; 1288 return (NULL); 1289 } 1290 1291 static int 1292 call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec) 1293 { 1294 int rv; 1295 1296 if (!tp) 1297 internal_errorf("%s: %s", where, wp[0]); 1298 builtin_argv0 = wp[0]; 1299 builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI)); 1300 shf_reopen(1, SHF_WR, shl_stdout); 1301 shl_stdout_ok = true; 1302 ksh_getopt_reset(&builtin_opt, GF_ERROR); 1303 rv = (*tp->val.f)(wp); 1304 shf_flush(shl_stdout); 1305 shl_stdout_ok = false; 1306 builtin_argv0 = NULL; 1307 builtin_spec = false; 1308 return (rv); 1309 } 1310 1311 /* 1312 * set up redirection, saving old fds in e->savefd 1313 */ 1314 static int 1315 iosetup(struct ioword *iop, struct tbl *tp) 1316 { 1317 int u = -1; 1318 char *cp = iop->name; 1319 int iotype = iop->ioflag & IOTYPE; 1320 bool do_open = true, do_close = false; 1321 int flags = 0; 1322 struct ioword iotmp; 1323 struct stat statb; 1324 1325 if (iotype != IOHERE) 1326 cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0)); 1327 1328 /* Used for tracing and error messages to print expanded cp */ 1329 iotmp = *iop; 1330 iotmp.name = (iotype == IOHERE) ? NULL : cp; 1331 iotmp.ioflag |= IONAMEXP; 1332 1333 if (Flag(FXTRACE)) { 1334 change_xtrace(2, false); 1335 fptreef(shl_xtrace, 0, "%R", &iotmp); 1336 change_xtrace(1, false); 1337 } 1338 1339 switch (iotype) { 1340 case IOREAD: 1341 flags = O_RDONLY; 1342 break; 1343 1344 case IOCAT: 1345 flags = O_WRONLY | O_APPEND | O_CREAT; 1346 break; 1347 1348 case IOWRITE: 1349 flags = O_WRONLY | O_CREAT | O_TRUNC; 1350 /* 1351 * The stat() is here to allow redirections to 1352 * things like /dev/null without error. 1353 */ 1354 if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB) && 1355 (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode))) 1356 flags |= O_EXCL; 1357 break; 1358 1359 case IORDWR: 1360 flags = O_RDWR | O_CREAT; 1361 break; 1362 1363 case IOHERE: 1364 do_open = false; 1365 /* herein() returns -2 if error has been printed */ 1366 u = herein(iop, NULL); 1367 /* cp may have wrong name */ 1368 break; 1369 1370 case IODUP: { 1371 const char *emsg; 1372 1373 do_open = false; 1374 if (*cp == '-' && !cp[1]) { 1375 /* prevent error return below */ 1376 u = 1009; 1377 do_close = true; 1378 } else if ((u = check_fd(cp, 1379 X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK), 1380 &emsg)) < 0) { 1381 char *sp; 1382 1383 warningf(true, "%s: %s", 1384 (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg); 1385 afree(sp, ATEMP); 1386 return (-1); 1387 } 1388 if (u == (int)iop->unit) 1389 /* "dup from" == "dup to" */ 1390 return (0); 1391 break; 1392 } 1393 } 1394 1395 if (do_open) { 1396 if (Flag(FRESTRICTED) && (flags & O_CREAT)) { 1397 warningf(true, "%s: %s", cp, "restricted"); 1398 return (-1); 1399 } 1400 u = open(cp, flags | O_BINARY, 0666); 1401 } 1402 if (u < 0) { 1403 /* herein() may already have printed message */ 1404 if (u == -1) { 1405 u = errno; 1406 warningf(true, "can't %s %s: %s", 1407 iotype == IODUP ? "dup" : 1408 (iotype == IOREAD || iotype == IOHERE) ? 1409 "open" : "create", cp, cstrerror(u)); 1410 } 1411 return (-1); 1412 } 1413 /* Do not save if it has already been redirected (i.e. "cat >x >y"). */ 1414 if (e->savefd[iop->unit] == 0) { 1415 /* If these are the same, it means unit was previously closed */ 1416 if (u == (int)iop->unit) 1417 e->savefd[iop->unit] = -1; 1418 else 1419 /* 1420 * c_exec() assumes e->savefd[fd] set for any 1421 * redirections. Ask savefd() not to close iop->unit; 1422 * this allows error messages to be seen if iop->unit 1423 * is 2; also means we can't lose the fd (eg, both 1424 * dup2 below and dup2 in restfd() failing). 1425 */ 1426 e->savefd[iop->unit] = savefd(iop->unit); 1427 } 1428 1429 if (do_close) 1430 close(iop->unit); 1431 else if (u != (int)iop->unit) { 1432 if (ksh_dup2(u, iop->unit, true) < 0) { 1433 int eno; 1434 char *sp; 1435 1436 eno = errno; 1437 warningf(true, "%s %s %s", 1438 "can't finish (dup) redirection", 1439 (sp = snptreef(NULL, 32, "%R", &iotmp)), 1440 cstrerror(eno)); 1441 afree(sp, ATEMP); 1442 if (iotype != IODUP) 1443 close(u); 1444 return (-1); 1445 } 1446 if (iotype != IODUP) 1447 close(u); 1448 /* 1449 * Touching any co-process fd in an empty exec 1450 * causes the shell to close its copies 1451 */ 1452 else if (tp && tp->type == CSHELL && tp->val.f == c_exec) { 1453 if (iop->ioflag & IORDUP) 1454 /* possible exec <&p */ 1455 coproc_read_close(u); 1456 else 1457 /* possible exec >&p */ 1458 coproc_write_close(u); 1459 } 1460 } 1461 if (u == 2) 1462 /* Clear any write errors */ 1463 shf_reopen(2, SHF_WR, shl_out); 1464 return (0); 1465 } 1466 1467 /* 1468 * Process here documents by providing the content, either as 1469 * result (globally allocated) string or in a temp file; if 1470 * unquoted, the string is expanded first. 1471 */ 1472 static int 1473 hereinval(const char *content, int sub, char **resbuf, struct shf *shf) 1474 { 1475 const char * volatile ccp = content; 1476 struct source *s, *osource; 1477 1478 osource = source; 1479 newenv(E_ERRH); 1480 if (kshsetjmp(e->jbuf)) { 1481 source = osource; 1482 quitenv(shf); 1483 /* special to iosetup(): don't print error */ 1484 return (-2); 1485 } 1486 if (sub) { 1487 /* do substitutions on the content of heredoc */ 1488 s = pushs(SSTRING, ATEMP); 1489 s->start = s->str = ccp; 1490 source = s; 1491 if (yylex(sub) != LWORD) 1492 internal_errorf("%s: %s", "herein", "yylex"); 1493 source = osource; 1494 ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC); 1495 } 1496 1497 if (resbuf == NULL) 1498 shf_puts(ccp, shf); 1499 else 1500 strdupx(*resbuf, ccp, APERM); 1501 1502 quitenv(NULL); 1503 return (0); 1504 } 1505 1506 static int 1507 herein(struct ioword *iop, char **resbuf) 1508 { 1509 int fd = -1; 1510 struct shf *shf; 1511 struct temp *h; 1512 int i; 1513 1514 /* ksh -c 'cat <<EOF' can cause this... */ 1515 if (iop->heredoc == NULL) { 1516 warningf(true, "%s missing", "here document"); 1517 /* special to iosetup(): don't print error */ 1518 return (-2); 1519 } 1520 1521 /* lexer substitution flags */ 1522 i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0; 1523 1524 /* skip all the fd setup if we just want the value */ 1525 if (resbuf != NULL) 1526 return (hereinval(iop->heredoc, i, resbuf, NULL)); 1527 1528 /* 1529 * Create temp file to hold content (done before newenv 1530 * so temp doesn't get removed too soon). 1531 */ 1532 h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); 1533 if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY | O_BINARY, 0)) < 0) { 1534 i = errno; 1535 warningf(true, "can't %s temporary file %s: %s", 1536 !shf ? "create" : "open", h->tffn, cstrerror(i)); 1537 if (shf) 1538 shf_close(shf); 1539 /* special to iosetup(): don't print error */ 1540 return (-2); 1541 } 1542 1543 if (hereinval(iop->heredoc, i, NULL, shf) == -2) { 1544 close(fd); 1545 /* special to iosetup(): don't print error */ 1546 return (-2); 1547 } 1548 1549 if (shf_close(shf) == -1) { 1550 i = errno; 1551 close(fd); 1552 warningf(true, "can't %s temporary file %s: %s", 1553 "write", h->tffn, cstrerror(i)); 1554 /* special to iosetup(): don't print error */ 1555 return (-2); 1556 } 1557 1558 return (fd); 1559 } 1560 1561 /* 1562 * ksh special - the select command processing section 1563 * print the args in column form - assuming that we can 1564 */ 1565 static const char * 1566 do_selectargs(const char **ap, bool print_menu) 1567 { 1568 static const char *read_args[] = { 1569 "read", "-r", "REPLY", NULL 1570 }; 1571 char *s; 1572 int i, argct; 1573 1574 for (argct = 0; ap[argct]; argct++) 1575 ; 1576 while (/* CONSTCOND */ 1) { 1577 /*- 1578 * Menu is printed if 1579 * - this is the first time around the select loop 1580 * - the user enters a blank line 1581 * - the REPLY parameter is empty 1582 */ 1583 if (print_menu || !*str_val(global("REPLY"))) 1584 pr_menu(ap); 1585 shellf("%s", str_val(global("PS3"))); 1586 if (call_builtin(findcom("read", FC_BI), read_args, Tselect, 1587 false)) 1588 return (NULL); 1589 if (*(s = str_val(global("REPLY")))) 1590 return ((getn(s, &i) && i >= 1 && i <= argct) ? 1591 ap[i - 1] : null); 1592 print_menu = true; 1593 } 1594 } 1595 1596 struct select_menu_info { 1597 const char * const *args; 1598 int num_width; 1599 }; 1600 1601 /* format a single select menu item */ 1602 static char * 1603 select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) 1604 { 1605 const struct select_menu_info *smi = 1606 (const struct select_menu_info *)arg; 1607 1608 shf_snprintf(buf, buflen, "%*u) %s", 1609 smi->num_width, i + 1, smi->args[i]); 1610 return (buf); 1611 } 1612 1613 /* 1614 * print a select style menu 1615 */ 1616 void 1617 pr_menu(const char * const *ap) 1618 { 1619 struct select_menu_info smi; 1620 const char * const *pp; 1621 size_t acols = 0, aocts = 0, i; 1622 unsigned int n; 1623 1624 /* 1625 * width/column calculations were done once and saved, but this 1626 * means select can't be used recursively so we re-calculate 1627 * each time (could save in a structure that is returned, but 1628 * it's probably not worth the bother) 1629 */ 1630 1631 /* 1632 * get dimensions of the list 1633 */ 1634 for (n = 0, pp = ap; *pp; n++, pp++) { 1635 i = strlen(*pp); 1636 if (i > aocts) 1637 aocts = i; 1638 i = utf_mbswidth(*pp); 1639 if (i > acols) 1640 acols = i; 1641 } 1642 1643 /* 1644 * we will print an index of the form "%d) " in front of 1645 * each entry, so get the maximum width of this 1646 */ 1647 for (i = n, smi.num_width = 1; i >= 10; i /= 10) 1648 smi.num_width++; 1649 1650 smi.args = ap; 1651 print_columns(shl_out, n, select_fmt_entry, (void *)&smi, 1652 smi.num_width + 2 + aocts, smi.num_width + 2 + acols, 1653 true); 1654 } 1655 1656 static char * 1657 plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) 1658 { 1659 strlcpy(buf, ((const char * const *)arg)[i], buflen); 1660 return (buf); 1661 } 1662 1663 void 1664 pr_list(char * const *ap) 1665 { 1666 size_t acols = 0, aocts = 0, i; 1667 unsigned int n; 1668 char * const *pp; 1669 1670 for (n = 0, pp = ap; *pp; n++, pp++) { 1671 i = strlen(*pp); 1672 if (i > aocts) 1673 aocts = i; 1674 i = utf_mbswidth(*pp); 1675 if (i > acols) 1676 acols = i; 1677 } 1678 1679 print_columns(shl_out, n, plain_fmt_entry, (const void *)ap, 1680 aocts, acols, false); 1681 } 1682 1683 /* 1684 * [[ ... ]] evaluation routines 1685 */ 1686 1687 /* 1688 * Test if the current token is a whatever. Accepts the current token if 1689 * it is. Returns 0 if it is not, non-zero if it is (in the case of 1690 * TM_UNOP and TM_BINOP, the returned value is a Test_op). 1691 */ 1692 static Test_op 1693 dbteste_isa(Test_env *te, Test_meta meta) 1694 { 1695 Test_op ret = TO_NONOP; 1696 bool uqword; 1697 const char *p; 1698 1699 if (!*te->pos.wp) 1700 return (meta == TM_END ? TO_NONNULL : TO_NONOP); 1701 1702 /* unquoted word? */ 1703 for (p = *te->pos.wp; *p == CHAR; p += 2) 1704 ; 1705 uqword = *p == EOS; 1706 1707 if (meta == TM_UNOP || meta == TM_BINOP) { 1708 if (uqword) { 1709 /* longer than the longest operator */ 1710 char buf[8]; 1711 char *q = buf; 1712 1713 p = *te->pos.wp; 1714 while (*p++ == CHAR && 1715 (size_t)(q - buf) < sizeof(buf) - 1) 1716 *q++ = *p++; 1717 *q = '\0'; 1718 ret = test_isop(meta, buf); 1719 } 1720 } else if (meta == TM_END) 1721 ret = TO_NONOP; 1722 else 1723 ret = (uqword && !strcmp(*te->pos.wp, 1724 dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP; 1725 1726 /* Accept the token? */ 1727 if (ret != TO_NONOP) 1728 te->pos.wp++; 1729 1730 return (ret); 1731 } 1732 1733 static const char * 1734 dbteste_getopnd(Test_env *te, Test_op op, bool do_eval) 1735 { 1736 const char *s = *te->pos.wp; 1737 int flags = DOTILDE | DOSCALAR; 1738 1739 if (!s) 1740 return (NULL); 1741 1742 te->pos.wp++; 1743 1744 if (!do_eval) 1745 return (null); 1746 1747 if (op == TO_STEQL || op == TO_STNEQ) 1748 flags |= DOPAT; 1749 1750 return (evalstr(s, flags)); 1751 } 1752 1753 static void 1754 dbteste_error(Test_env *te, int offset, const char *msg) 1755 { 1756 te->flags |= TEF_ERROR; 1757 internal_warningf("dbteste_error: %s (offset %d)", msg, offset); 1758 } 1759