OSDN Git Service

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