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