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@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
execute(struct op * volatile t,volatile int flags,volatile int * volatile xerrok)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, don’t 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
comexec(struct op * t,struct tbl * volatile tp,const char ** ap,volatile int flags,volatile int * xerrok)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
scriptexec(struct op * tp,const char ** ap)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
shcomexec(const char ** wp)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 *
findfunc(const char * name,uint32_t h,bool create)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
define(const char * name,struct op * t)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 *
builtin(const char * name,int (* func)(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 *
findcom(const char * name,int flags)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
flushcom(bool all)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
search_access(const char * fn,int mode)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 *
search_path(const char * name,const char * lpath,int mode,int * errnop)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
call_builtin(struct tbl * tp,const char ** wp,const char * where,bool resetspec)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
iosetup(struct ioword * iop,struct tbl * tp)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
hereinval(const char * content,int sub,char ** resbuf,struct shf * shf)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
herein(struct ioword * iop,char ** resbuf)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 *
do_selectargs(const char ** ap,bool print_menu)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 *
select_fmt_entry(char * buf,size_t buflen,unsigned int i,const void * arg)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
pr_menu(const char * const * ap)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 *
plain_fmt_entry(char * buf,size_t buflen,unsigned int i,const void * arg)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
pr_list(char * const * ap)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
dbteste_isa(Test_env * te,Test_meta meta)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 *
dbteste_getopnd(Test_env * te,Test_op op,bool do_eval)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
dbteste_error(Test_env * te,int offset,const char * msg)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