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