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