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