OSDN Git Service

50ec9ca486fea247be09d066f2884469226e63e5
[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
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.125 2013/07/21 20:44:44 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;
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 #if !defined(MKSH_SMALL)
608                 } else if (tp->val.f == c_trap) {
609                         t->u.evalflags &= ~DOTCOMEXEC;
610                         break;
611 #endif
612                 } else
613                         break;
614                 tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
615         }
616 #if !defined(MKSH_SMALL)
617         if (t->u.evalflags & DOTCOMEXEC)
618                 flags |= XEXEC;
619 #endif
620         l_expand = e->loc;
621         if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN))))
622                 type_flags = 0;
623         else {
624                 /* create new variable/function block */
625                 newblock();
626                 /* ksh functions don't keep assignments, POSIX functions do. */
627                 if (keepasn_ok && tp && tp->type == CFUNC &&
628                     !(tp->flag & FKSH)) {
629                         bourne_function_call = true;
630                         type_flags = EXPORT;
631                 } else
632                         type_flags = LOCAL|LOCAL_COPY|EXPORT;
633         }
634         l_assign = e->loc;
635         if (Flag(FEXPORT))
636                 type_flags |= EXPORT;
637         if (Flag(FXTRACE))
638                 change_xtrace(2, false);
639         for (i = 0; t->vars[i]; i++) {
640                 /* do NOT lookup in the new var/fn block just created */
641                 e->loc = l_expand;
642                 cp = evalstr(t->vars[i], DOASNTILDE);
643                 e->loc = l_assign;
644                 if (Flag(FXTRACE)) {
645                         const char *ccp;
646
647                         ccp = skip_varname(cp, true);
648                         if (*ccp == '+')
649                                 ++ccp;
650                         if (*ccp == '=')
651                                 ++ccp;
652                         shf_write(cp, ccp - cp, shl_xtrace);
653                         print_value_quoted(shl_xtrace, ccp);
654                         shf_putc(' ', shl_xtrace);
655                 }
656                 /* but assign in there as usual */
657                 typeset(cp, type_flags, 0, 0, 0);
658                 if (bourne_function_call && !(type_flags & EXPORT))
659                         typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0);
660         }
661
662         if (Flag(FXTRACE)) {
663                 change_xtrace(2, false);
664                 if (ap[rv = 0]) {
665  xtrace_ap_loop:
666                         print_value_quoted(shl_xtrace, ap[rv]);
667                         if (ap[++rv]) {
668                                 shf_putc(' ', shl_xtrace);
669                                 goto xtrace_ap_loop;
670                         }
671                 }
672                 change_xtrace(1, false);
673         }
674
675         if ((cp = *ap) == NULL) {
676                 rv = subst_exstat;
677                 goto Leave;
678         } else if (!tp) {
679                 if (Flag(FRESTRICTED) && vstrchr(cp, '/')) {
680                         warningf(true, "%s: %s", cp, "restricted");
681                         rv = 1;
682                         goto Leave;
683                 }
684                 tp = findcom(cp, fcflags);
685         }
686
687         switch (tp->type) {
688
689         /* shell built-in */
690         case CSHELL:
691                 rv = call_builtin(tp, (const char **)ap, null);
692                 if (!keepasn_ok && tp->val.f == c_shift) {
693                         l_expand->argc = l_assign->argc;
694                         l_expand->argv = l_assign->argv;
695                 }
696                 break;
697
698         /* function call */
699         case CFUNC: {
700                 volatile unsigned char old_xflag;
701                 volatile uint32_t old_inuse;
702                 const char * volatile old_kshname;
703
704                 if (!(tp->flag & ISSET)) {
705                         struct tbl *ftp;
706
707                         if (!tp->u.fpath) {
708                                 rv = (tp->u2.errnov == ENOENT) ? 127 : 126;
709                                 warningf(true, "%s: %s %s: %s", cp,
710                                     "can't find", "function definition file",
711                                     cstrerror(tp->u2.errnov));
712                                 break;
713                         }
714                         if (include(tp->u.fpath, 0, NULL, false) < 0) {
715                                 warningf(true, "%s: %s %s %s: %s", cp,
716                                     "can't open", "function definition file",
717                                     tp->u.fpath, cstrerror(errno));
718                                 rv = 127;
719                                 break;
720                         }
721                         if (!(ftp = findfunc(cp, hash(cp), false)) ||
722                             !(ftp->flag & ISSET)) {
723                                 warningf(true, "%s: %s %s", cp,
724                                     "function not defined by", tp->u.fpath);
725                                 rv = 127;
726                                 break;
727                         }
728                         tp = ftp;
729                 }
730
731                 /*
732                  * ksh functions set $0 to function name, POSIX
733                  * functions leave $0 unchanged.
734                  */
735                 old_kshname = kshname;
736                 if (tp->flag & FKSH)
737                         kshname = ap[0];
738                 else
739                         ap[0] = kshname;
740                 e->loc->argv = ap;
741                 for (i = 0; *ap++ != NULL; i++)
742                         ;
743                 e->loc->argc = i - 1;
744                 /*
745                  * ksh-style functions handle getopts sanely,
746                  * Bourne/POSIX functions are insane...
747                  */
748                 if (tp->flag & FKSH) {
749                         e->loc->flags |= BF_DOGETOPTS;
750                         e->loc->getopts_state = user_opt;
751                         getopts_reset(1);
752                 }
753
754                 old_xflag = Flag(FXTRACE) ? 1 : 0;
755                 change_xtrace((Flag(FXTRACEREC) ? old_xflag : 0) |
756                     ((tp->flag & TRACE) ? 1 : 0), false);
757                 old_inuse = tp->flag & FINUSE;
758                 tp->flag |= FINUSE;
759
760                 e->type = E_FUNC;
761                 if (!(i = kshsetjmp(e->jbuf))) {
762                         execute(tp->val.t, flags & XERROK, NULL);
763                         i = LRETURN;
764                 }
765
766                 kshname = old_kshname;
767                 change_xtrace(old_xflag, false);
768                 tp->flag = (tp->flag & ~FINUSE) | old_inuse;
769
770                 /*
771                  * Were we deleted while executing? If so, free the
772                  * execution tree. TODO: Unfortunately, the table entry
773                  * is never re-used until the lookup table is expanded.
774                  */
775                 if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
776                         if (tp->flag & ALLOC) {
777                                 tp->flag &= ~ALLOC;
778                                 tfree(tp->val.t, tp->areap);
779                         }
780                         tp->flag = 0;
781                 }
782                 switch (i) {
783                 case LRETURN:
784                 case LERROR:
785                         rv = exstat & 0xFF;
786                         break;
787                 case LINTR:
788                 case LEXIT:
789                 case LLEAVE:
790                 case LSHELL:
791                         quitenv(NULL);
792                         unwind(i);
793                         /* NOTREACHED */
794                 default:
795                         quitenv(NULL);
796                         internal_errorf("%s %d", "CFUNC", i);
797                 }
798                 break;
799         }
800
801         /* executable command */
802         case CEXEC:
803         /* tracked alias */
804         case CTALIAS:
805                 if (!(tp->flag&ISSET)) {
806                         if (tp->u2.errnov == ENOENT) {
807                                 rv = 127;
808                                 warningf(true, "%s: %s", cp, "not found");
809                         } else {
810                                 rv = 126;
811                                 warningf(true, "%s: %s: %s", cp, "can't execute",
812                                     cstrerror(tp->u2.errnov));
813                         }
814                         break;
815                 }
816
817                 /* set $_ to programme's full path */
818                 /* setstr() can't fail here */
819                 setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0),
820                     tp->val.s, KSH_RETURN_ERROR);
821
822                 if (flags&XEXEC) {
823                         j_exit();
824                         if (!(flags&XBGND)
825 #ifndef MKSH_UNEMPLOYED
826                             || Flag(FMONITOR)
827 #endif
828                             ) {
829                                 setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG);
830                                 setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG);
831                         }
832                 }
833
834                 /* to fork we set up a TEXEC node and call execute */
835                 texec.type = TEXEC;
836                 /* for tprint */
837                 texec.left = t;
838                 texec.str = tp->val.s;
839                 texec.args = ap;
840                 rv = exchild(&texec, flags, xerrok, -1);
841                 break;
842         }
843  Leave:
844         if (flags & XEXEC) {
845                 exstat = rv & 0xFF;
846                 unwind(LLEAVE);
847         }
848         return (rv);
849 }
850
851 static void
852 scriptexec(struct op *tp, const char **ap)
853 {
854         const char *sh;
855 #ifndef MKSH_SMALL
856         unsigned char *cp;
857         /* 64 == MAXINTERP in MirBSD <sys/param.h> */
858         char buf[64];
859         int fd;
860 #endif
861         union mksh_ccphack args, cap;
862
863         sh = str_val(global("EXECSHELL"));
864         if (sh && *sh)
865                 sh = search_path(sh, path, X_OK, NULL);
866         if (!sh || !*sh)
867                 sh = MKSH_DEFAULT_EXECSHELL;
868
869         *tp->args-- = tp->str;
870
871 #ifndef MKSH_SMALL
872         if ((fd = open(tp->str, O_RDONLY)) >= 0) {
873                 /* read first MAXINTERP octets from file */
874                 if (read(fd, buf, sizeof(buf)) <= 0)
875                         /* read error -> no good */
876                         buf[0] = '\0';
877                 close(fd);
878
879                 /* skip UTF-8 Byte Order Mark, if present */
880                 cp = (unsigned char *)buf;
881                 if ((cp[0] == 0xEF) && (cp[1] == 0xBB) && (cp[2] == 0xBF))
882                         cp += 3;
883                 /* save begin of shebang for later */
884                 fd = (char *)cp - buf;          /* either 0 or (if BOM) 3 */
885
886                 /* scan for newline (or CR) or NUL _before_ end of buffer */
887                 while ((char *)cp < (buf + sizeof(buf)))
888                         if (*cp == '\0' || *cp == '\n' || *cp == '\r') {
889                                 *cp = '\0';
890                                 break;
891                         } else
892                                 ++cp;
893                 /* if the shebang line is longer than MAXINTERP, bail out */
894                 if ((char *)cp >= (buf + sizeof(buf)))
895                         goto noshebang;
896
897                 /* restore begin of shebang position (buf+0 or buf+3) */
898                 cp = (unsigned char *)(buf + fd);
899                 /* bail out if read error (above) or no shebang */
900                 if ((cp[0] != '#') || (cp[1] != '!'))
901                         goto noshebang;
902
903                 cp += 2;
904                 /* skip whitespace before shell name */
905                 while (*cp == ' ' || *cp == '\t')
906                         ++cp;
907                 /* just whitespace on the line? */
908                 if (*cp == '\0')
909                         goto noshebang;
910                 /* no, we actually found an interpreter name */
911                 sh = (char *)cp;
912                 /* look for end of shell/interpreter name */
913                 while (*cp != ' ' && *cp != '\t' && *cp != '\0')
914                         ++cp;
915                 /* any arguments? */
916                 if (*cp) {
917                         *cp++ = '\0';
918                         /* skip spaces before arguments */
919                         while (*cp == ' ' || *cp == '\t')
920                                 ++cp;
921                         /* pass it all in ONE argument (historic reasons) */
922                         if (*cp)
923                                 *tp->args-- = (char *)cp;
924                 }
925  noshebang:
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 == 0x7F45 && buf[2] == 'L' && buf[3] == 'F') ||
935                     (fd == /* "MZ" */ 0x4D5A) ||
936                     (fd == /* gzip */ 0x1F8B))
937                         errorf("%s: not executable: magic %04X", tp->str, fd);
938         }
939 #endif
940         args.ro = tp->args;
941         *args.ro = sh;
942
943         cap.ro = ap;
944         execve(args.rw[0], args.rw, cap.rw);
945
946         /* report both the programme that was run and the bogus interpreter */
947         errorf("%s: %s: %s", tp->str, sh, cstrerror(errno));
948 }
949
950 int
951 shcomexec(const char **wp)
952 {
953         struct tbl *tp;
954
955         tp = ktsearch(&builtins, *wp, hash(*wp));
956         return (call_builtin(tp, wp, "shcomexec"));
957 }
958
959 /*
960  * Search function tables for a function. If create set, a table entry
961  * is created if none is found.
962  */
963 struct tbl *
964 findfunc(const char *name, uint32_t h, bool create)
965 {
966         struct block *l;
967         struct tbl *tp = NULL;
968
969         for (l = e->loc; l; l = l->next) {
970                 tp = ktsearch(&l->funs, name, h);
971                 if (tp)
972                         break;
973                 if (!l->next && create) {
974                         tp = ktenter(&l->funs, name, h);
975                         tp->flag = DEFINED;
976                         tp->type = CFUNC;
977                         tp->val.t = NULL;
978                         break;
979                 }
980         }
981         return (tp);
982 }
983
984 /*
985  * define function. Returns 1 if function is being undefined (t == 0) and
986  * function did not exist, returns 0 otherwise.
987  */
988 int
989 define(const char *name, struct op *t)
990 {
991         uint32_t nhash;
992         struct tbl *tp;
993         bool was_set = false;
994
995         nhash = hash(name);
996
997         if (t != NULL && !tobool(t->u.ksh_func)) {
998                 /* drop same-name aliases for POSIX functions */
999                 if ((tp = ktsearch(&aliases, name, nhash)))
1000                         ktdelete(tp);
1001         }
1002
1003         while (/* CONSTCOND */ 1) {
1004                 tp = findfunc(name, nhash, true);
1005                 /* because findfunc:create=true */
1006                 mkssert(tp != NULL);
1007
1008                 if (tp->flag & ISSET)
1009                         was_set = true;
1010                 /*
1011                  * If this function is currently being executed, we zap
1012                  * this table entry so findfunc() won't see it
1013                  */
1014                 if (tp->flag & FINUSE) {
1015                         tp->name[0] = '\0';
1016                         /* ensure it won't be found */
1017                         tp->flag &= ~DEFINED;
1018                         tp->flag |= FDELETE;
1019                 } else
1020                         break;
1021         }
1022
1023         if (tp->flag & ALLOC) {
1024                 tp->flag &= ~(ISSET|ALLOC);
1025                 tfree(tp->val.t, tp->areap);
1026         }
1027
1028         if (t == NULL) {
1029                 /* undefine */
1030                 ktdelete(tp);
1031                 return (was_set ? 0 : 1);
1032         }
1033
1034         tp->val.t = tcopy(t->left, tp->areap);
1035         tp->flag |= (ISSET|ALLOC);
1036         if (t->u.ksh_func)
1037                 tp->flag |= FKSH;
1038
1039         return (0);
1040 }
1041
1042 /*
1043  * add builtin
1044  */
1045 const char *
1046 builtin(const char *name, int (*func) (const char **))
1047 {
1048         struct tbl *tp;
1049         uint32_t flag = DEFINED;
1050
1051         /* see if any flags should be set for this builtin */
1052         while (1) {
1053                 if (*name == '=')
1054                         /* command does variable assignment */
1055                         flag |= KEEPASN;
1056                 else if (*name == '*')
1057                         /* POSIX special builtin */
1058                         flag |= SPEC_BI;
1059                 else
1060                         break;
1061                 name++;
1062         }
1063
1064         tp = ktenter(&builtins, name, hash(name));
1065         tp->flag = flag;
1066         tp->type = CSHELL;
1067         tp->val.f = func;
1068
1069         return (name);
1070 }
1071
1072 /*
1073  * find command
1074  * either function, hashed command, or built-in (in that order)
1075  */
1076 struct tbl *
1077 findcom(const char *name, int flags)
1078 {
1079         static struct tbl temp;
1080         uint32_t h = hash(name);
1081         struct tbl *tp = NULL, *tbi;
1082         /* insert if not found */
1083         unsigned char insert = Flag(FTRACKALL);
1084         /* for function autoloading */
1085         char *fpath;
1086         union mksh_cchack npath;
1087
1088         if (vstrchr(name, '/')) {
1089                 insert = 0;
1090                 /* prevent FPATH search below */
1091                 flags &= ~FC_FUNC;
1092                 goto Search;
1093         }
1094         tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
1095         /*
1096          * POSIX says special builtins first, then functions, then
1097          * regular builtins, then search path...
1098          */
1099         if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
1100                 tp = tbi;
1101         if (!tp && (flags & FC_FUNC)) {
1102                 tp = findfunc(name, h, false);
1103                 if (tp && !(tp->flag & ISSET)) {
1104                         if ((fpath = str_val(global("FPATH"))) == null) {
1105                                 tp->u.fpath = NULL;
1106                                 tp->u2.errnov = ENOENT;
1107                         } else
1108                                 tp->u.fpath = search_path(name, fpath, R_OK,
1109                                     &tp->u2.errnov);
1110                 }
1111         }
1112         if (!tp && (flags & FC_NORMBI) && tbi)
1113                 tp = tbi;
1114         if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
1115                 tp = ktsearch(&taliases, name, h);
1116                 if (tp && (tp->flag & ISSET) &&
1117                     ksh_access(tp->val.s, X_OK) != 0) {
1118                         if (tp->flag & ALLOC) {
1119                                 tp->flag &= ~ALLOC;
1120                                 afree(tp->val.s, APERM);
1121                         }
1122                         tp->flag &= ~ISSET;
1123                 }
1124         }
1125
1126  Search:
1127         if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
1128             (flags & FC_PATH)) {
1129                 if (!tp) {
1130                         if (insert && !(flags & FC_DEFPATH)) {
1131                                 tp = ktenter(&taliases, name, h);
1132                                 tp->type = CTALIAS;
1133                         } else {
1134                                 tp = &temp;
1135                                 tp->type = CEXEC;
1136                         }
1137                         /* make ~ISSET */
1138                         tp->flag = DEFINED;
1139                 }
1140                 npath.ro = search_path(name,
1141                     (flags & FC_DEFPATH) ? def_path : path,
1142                     X_OK, &tp->u2.errnov);
1143                 if (npath.ro) {
1144                         strdupx(tp->val.s, npath.ro, APERM);
1145                         if (npath.ro != name)
1146                                 afree(npath.rw, ATEMP);
1147                         tp->flag |= ISSET|ALLOC;
1148                 } else if ((flags & FC_FUNC) &&
1149                     (fpath = str_val(global("FPATH"))) != null &&
1150                     (npath.ro = search_path(name, fpath, R_OK,
1151                     &tp->u2.errnov)) != NULL) {
1152                         /*
1153                          * An undocumented feature of AT&T ksh is that
1154                          * it searches FPATH if a command is not found,
1155                          * even if the command hasn't been set up as an
1156                          * autoloaded function (ie, no typeset -uf).
1157                          */
1158                         tp = &temp;
1159                         tp->type = CFUNC;
1160                         /* make ~ISSET */
1161                         tp->flag = DEFINED;
1162                         tp->u.fpath = npath.ro;
1163                 }
1164         }
1165         return (tp);
1166 }
1167
1168 /*
1169  * flush executable commands with relative paths
1170  * (just relative or all?)
1171  */
1172 void
1173 flushcom(bool all)
1174 {
1175         struct tbl *tp;
1176         struct tstate ts;
1177
1178         for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
1179                 if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
1180                         if (tp->flag&ALLOC) {
1181                                 tp->flag &= ~(ALLOC|ISSET);
1182                                 afree(tp->val.s, APERM);
1183                         }
1184                         tp->flag &= ~ISSET;
1185                 }
1186 }
1187
1188 /* check if path is something we want to find */
1189 static int
1190 search_access(const char *fn, int mode)
1191 {
1192         struct stat sb;
1193
1194         if (stat(fn, &sb) < 0)
1195                 /* file does not exist */
1196                 return (ENOENT);
1197         /* LINTED use of access */
1198         if (access(fn, mode) < 0)
1199                 /* file exists, but we can't access it */
1200                 return (errno);
1201         if (mode == X_OK && (!S_ISREG(sb.st_mode) ||
1202             !(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
1203                 /* access(2) may say root can execute everything */
1204                 return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES);
1205         return (0);
1206 }
1207
1208 /*
1209  * search for command with PATH
1210  */
1211 const char *
1212 search_path(const char *name, const char *lpath,
1213     /* R_OK or X_OK */
1214     int mode,
1215     /* set if candidate found, but not suitable */
1216     int *errnop)
1217 {
1218         const char *sp, *p;
1219         char *xp;
1220         XString xs;
1221         size_t namelen;
1222         int ec = 0, ev;
1223
1224         if (vstrchr(name, '/')) {
1225                 if ((ec = search_access(name, mode)) == 0) {
1226  search_path_ok:
1227                         if (errnop)
1228                                 *errnop = 0;
1229                         return (name);
1230                 }
1231                 goto search_path_err;
1232         }
1233
1234         namelen = strlen(name) + 1;
1235         Xinit(xs, xp, 128, ATEMP);
1236
1237         sp = lpath;
1238         while (sp != NULL) {
1239                 xp = Xstring(xs, xp);
1240                 if (!(p = cstrchr(sp, ':')))
1241                         p = sp + strlen(sp);
1242                 if (p != sp) {
1243                         XcheckN(xs, xp, p - sp);
1244                         memcpy(xp, sp, p - sp);
1245                         xp += p - sp;
1246                         *xp++ = '/';
1247                 }
1248                 sp = p;
1249                 XcheckN(xs, xp, namelen);
1250                 memcpy(xp, name, namelen);
1251                 if ((ev = search_access(Xstring(xs, xp), mode)) == 0) {
1252                         name = Xclose(xs, xp + namelen);
1253                         goto search_path_ok;
1254                 }
1255                 /* accumulate non-ENOENT errors only */
1256                 if (ev != ENOENT && ec == 0)
1257                         ec = ev;
1258                 if (*sp++ == '\0')
1259                         sp = NULL;
1260         }
1261         Xfree(xs, xp);
1262  search_path_err:
1263         if (errnop)
1264                 *errnop = ec ? ec : ENOENT;
1265         return (NULL);
1266 }
1267
1268 static int
1269 call_builtin(struct tbl *tp, const char **wp, const char *where)
1270 {
1271         int rv;
1272
1273         if (!tp)
1274                 internal_errorf("%s: %s", where, wp[0]);
1275         builtin_argv0 = wp[0];
1276         builtin_flag = tp->flag;
1277         shf_reopen(1, SHF_WR, shl_stdout);
1278         shl_stdout_ok = true;
1279         ksh_getopt_reset(&builtin_opt, GF_ERROR);
1280         rv = (*tp->val.f)(wp);
1281         shf_flush(shl_stdout);
1282         shl_stdout_ok = false;
1283         builtin_flag = 0;
1284         builtin_argv0 = NULL;
1285         return (rv);
1286 }
1287
1288 /*
1289  * set up redirection, saving old fds in e->savefd
1290  */
1291 static int
1292 iosetup(struct ioword *iop, struct tbl *tp)
1293 {
1294         int u = -1;
1295         char *cp = iop->name;
1296         int iotype = iop->flag & IOTYPE;
1297         bool do_open = true, do_close = false;
1298         int flags = 0;
1299         struct ioword iotmp;
1300         struct stat statb;
1301
1302         if (iotype != IOHERE)
1303                 cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
1304
1305         /* Used for tracing and error messages to print expanded cp */
1306         iotmp = *iop;
1307         iotmp.name = (iotype == IOHERE) ? NULL : cp;
1308         iotmp.flag |= IONAMEXP;
1309
1310         if (Flag(FXTRACE)) {
1311                 change_xtrace(2, false);
1312                 fptreef(shl_xtrace, 0, "%R", &iotmp);
1313                 change_xtrace(1, false);
1314         }
1315
1316         switch (iotype) {
1317         case IOREAD:
1318                 flags = O_RDONLY;
1319                 break;
1320
1321         case IOCAT:
1322                 flags = O_WRONLY | O_APPEND | O_CREAT;
1323                 break;
1324
1325         case IOWRITE:
1326                 flags = O_WRONLY | O_CREAT | O_TRUNC;
1327                 /*
1328                  * The stat() is here to allow redirections to
1329                  * things like /dev/null without error.
1330                  */
1331                 if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
1332                     (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
1333                         flags |= O_EXCL;
1334                 break;
1335
1336         case IORDWR:
1337                 flags = O_RDWR | O_CREAT;
1338                 break;
1339
1340         case IOHERE:
1341                 do_open = false;
1342                 /* herein() returns -2 if error has been printed */
1343                 u = herein(iop, NULL);
1344                 /* cp may have wrong name */
1345                 break;
1346
1347         case IODUP: {
1348                 const char *emsg;
1349
1350                 do_open = false;
1351                 if (*cp == '-' && !cp[1]) {
1352                         /* prevent error return below */
1353                         u = 1009;
1354                         do_close = true;
1355                 } else if ((u = check_fd(cp,
1356                     X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
1357                     &emsg)) < 0) {
1358                         char *sp;
1359
1360                         warningf(true, "%s: %s",
1361                             (sp = snptreef(NULL, 32, "%R", &iotmp)), emsg);
1362                         afree(sp, ATEMP);
1363                         return (-1);
1364                 }
1365                 if (u == iop->unit)
1366                         /* "dup from" == "dup to" */
1367                         return (0);
1368                 break;
1369             }
1370         }
1371
1372         if (do_open) {
1373                 if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
1374                         warningf(true, "%s: %s", cp, "restricted");
1375                         return (-1);
1376                 }
1377                 u = open(cp, flags, 0666);
1378         }
1379         if (u < 0) {
1380                 /* herein() may already have printed message */
1381                 if (u == -1) {
1382                         u = errno;
1383                         warningf(true, "can't %s %s: %s",
1384                             iotype == IODUP ? "dup" :
1385                             (iotype == IOREAD || iotype == IOHERE) ?
1386                             "open" : "create", cp, cstrerror(u));
1387                 }
1388                 return (-1);
1389         }
1390         /* Do not save if it has already been redirected (i.e. "cat >x >y"). */
1391         if (e->savefd[iop->unit] == 0) {
1392                 /* If these are the same, it means unit was previously closed */
1393                 if (u == iop->unit)
1394                         e->savefd[iop->unit] = -1;
1395                 else
1396                         /*
1397                          * c_exec() assumes e->savefd[fd] set for any
1398                          * redirections. Ask savefd() not to close iop->unit;
1399                          * this allows error messages to be seen if iop->unit
1400                          * is 2; also means we can't lose the fd (eg, both
1401                          * dup2 below and dup2 in restfd() failing).
1402                          */
1403                         e->savefd[iop->unit] = savefd(iop->unit);
1404         }
1405
1406         if (do_close)
1407                 close(iop->unit);
1408         else if (u != iop->unit) {
1409                 if (ksh_dup2(u, iop->unit, true) < 0) {
1410                         int eno;
1411                         char *sp;
1412
1413                         eno = errno;
1414                         warningf(true, "%s %s %s",
1415                             "can't finish (dup) redirection",
1416                             (sp = snptreef(NULL, 32, "%R", &iotmp)),
1417                             cstrerror(eno));
1418                         afree(sp, ATEMP);
1419                         if (iotype != IODUP)
1420                                 close(u);
1421                         return (-1);
1422                 }
1423                 if (iotype != IODUP)
1424                         close(u);
1425                 /*
1426                  * Touching any co-process fd in an empty exec
1427                  * causes the shell to close its copies
1428                  */
1429                 else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
1430                         if (iop->flag & IORDUP)
1431                                 /* possible exec <&p */
1432                                 coproc_read_close(u);
1433                         else
1434                                 /* possible exec >&p */
1435                                 coproc_write_close(u);
1436                 }
1437         }
1438         if (u == 2)
1439                 /* Clear any write errors */
1440                 shf_reopen(2, SHF_WR, shl_out);
1441         return (0);
1442 }
1443
1444 /*
1445  * Process here documents by providing the content, either as
1446  * result (globally allocated) string or in a temp file; if
1447  * unquoted, the string is expanded first.
1448  */
1449 static int
1450 hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
1451 {
1452         const char * volatile ccp = content;
1453         struct source *s, *osource;
1454
1455         osource = source;
1456         newenv(E_ERRH);
1457         if (kshsetjmp(e->jbuf)) {
1458                 source = osource;
1459                 quitenv(shf);
1460                 /* special to iosetup(): don't print error */
1461                 return (-2);
1462         }
1463         if (sub) {
1464                 /* do substitutions on the content of heredoc */
1465                 s = pushs(SSTRING, ATEMP);
1466                 s->start = s->str = ccp;
1467                 source = s;
1468                 if (yylex(sub) != LWORD)
1469                         internal_errorf("%s: %s", "herein", "yylex");
1470                 source = osource;
1471                 ccp = evalstr(yylval.cp, 0);
1472         }
1473
1474         if (resbuf == NULL)
1475                 shf_puts(ccp, shf);
1476         else
1477                 strdupx(*resbuf, ccp, APERM);
1478
1479         quitenv(NULL);
1480         return (0);
1481 }
1482
1483 static int
1484 herein(struct ioword *iop, char **resbuf)
1485 {
1486         int fd = -1;
1487         struct shf *shf;
1488         struct temp *h;
1489         int i;
1490
1491         /* ksh -c 'cat << EOF' can cause this... */
1492         if (iop->heredoc == NULL) {
1493                 warningf(true, "%s missing", "here document");
1494                 /* special to iosetup(): don't print error */
1495                 return (-2);
1496         }
1497
1498         /* lexer substitution flags */
1499         i = (iop->flag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
1500
1501         /* skip all the fd setup if we just want the value */
1502         if (resbuf != NULL)
1503                 return (hereinval(iop->heredoc, i, resbuf, NULL));
1504
1505         /*
1506          * Create temp file to hold content (done before newenv
1507          * so temp doesn't get removed too soon).
1508          */
1509         h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
1510         if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) {
1511                 i = errno;
1512                 warningf(true, "can't %s temporary file %s: %s",
1513                     !shf ? "create" : "open", h->tffn, cstrerror(i));
1514                 if (shf)
1515                         shf_close(shf);
1516                 /* special to iosetup(): don't print error */
1517                 return (-2);
1518         }
1519
1520         if (hereinval(iop->heredoc, i, NULL, shf) == -2) {
1521                 close(fd);
1522                 /* special to iosetup(): don't print error */
1523                 return (-2);
1524         }
1525
1526         if (shf_close(shf) == EOF) {
1527                 i = errno;
1528                 close(fd);
1529                 warningf(true, "can't %s temporary file %s: %s",
1530                     "write", h->tffn, cstrerror(i));
1531                 /* special to iosetup(): don't print error */
1532                 return (-2);
1533         }
1534
1535         return (fd);
1536 }
1537
1538 /*
1539  *      ksh special - the select command processing section
1540  *      print the args in column form - assuming that we can
1541  */
1542 static const char *
1543 do_selectargs(const char **ap, bool print_menu)
1544 {
1545         static const char *read_args[] = {
1546                 "read", "-r", "REPLY", NULL
1547         };
1548         char *s;
1549         int i, argct;
1550
1551         for (argct = 0; ap[argct]; argct++)
1552                 ;
1553         while (/* CONSTCOND */ 1) {
1554                 /*-
1555                  * Menu is printed if
1556                  *      - this is the first time around the select loop
1557                  *      - the user enters a blank line
1558                  *      - the REPLY parameter is empty
1559                  */
1560                 if (print_menu || !*str_val(global("REPLY")))
1561                         pr_menu(ap);
1562                 shellf("%s", str_val(global("PS3")));
1563                 if (call_builtin(findcom("read", FC_BI), read_args, Tselect))
1564                         return (NULL);
1565                 s = str_val(global("REPLY"));
1566                 if (*s && getn(s, &i))
1567                         return ((i >= 1 && i <= argct) ? ap[i - 1] : null);
1568                 print_menu = true;
1569         }
1570 }
1571
1572 struct select_menu_info {
1573         const char * const *args;
1574         int num_width;
1575 };
1576
1577 /* format a single select menu item */
1578 static char *
1579 select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1580 {
1581         const struct select_menu_info *smi =
1582             (const struct select_menu_info *)arg;
1583
1584         shf_snprintf(buf, buflen, "%*u) %s",
1585             smi->num_width, i + 1, smi->args[i]);
1586         return (buf);
1587 }
1588
1589 /*
1590  *      print a select style menu
1591  */
1592 void
1593 pr_menu(const char * const *ap)
1594 {
1595         struct select_menu_info smi;
1596         const char * const *pp;
1597         size_t acols = 0, aocts = 0, i;
1598         unsigned int n;
1599
1600         /*
1601          * width/column calculations were done once and saved, but this
1602          * means select can't be used recursively so we re-calculate
1603          * each time (could save in a structure that is returned, but
1604          * it's probably not worth the bother)
1605          */
1606
1607         /*
1608          * get dimensions of the list
1609          */
1610         for (n = 0, pp = ap; *pp; n++, pp++) {
1611                 i = strlen(*pp);
1612                 if (i > aocts)
1613                         aocts = i;
1614                 i = utf_mbswidth(*pp);
1615                 if (i > acols)
1616                         acols = i;
1617         }
1618
1619         /*
1620          * we will print an index of the form "%d) " in front of
1621          * each entry, so get the maximum width of this
1622          */
1623         for (i = n, smi.num_width = 1; i >= 10; i /= 10)
1624                 smi.num_width++;
1625
1626         smi.args = ap;
1627         print_columns(shl_out, n, select_fmt_entry, (void *)&smi,
1628             smi.num_width + 2 + aocts, smi.num_width + 2 + acols,
1629             true);
1630 }
1631
1632 static char *
1633 plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1634 {
1635         strlcpy(buf, ((const char * const *)arg)[i], buflen);
1636         return (buf);
1637 }
1638
1639 void
1640 pr_list(char * const *ap)
1641 {
1642         size_t acols = 0, aocts = 0, i;
1643         unsigned int n;
1644         char * const *pp;
1645
1646         for (n = 0, pp = ap; *pp; n++, pp++) {
1647                 i = strlen(*pp);
1648                 if (i > aocts)
1649                         aocts = i;
1650                 i = utf_mbswidth(*pp);
1651                 if (i > acols)
1652                         acols = i;
1653         }
1654
1655         print_columns(shl_out, n, plain_fmt_entry, (const void *)ap,
1656             aocts, acols, false);
1657 }
1658
1659 /*
1660  *      [[ ... ]] evaluation routines
1661  */
1662
1663 /*
1664  * Test if the current token is a whatever. Accepts the current token if
1665  * it is. Returns 0 if it is not, non-zero if it is (in the case of
1666  * TM_UNOP and TM_BINOP, the returned value is a Test_op).
1667  */
1668 static Test_op
1669 dbteste_isa(Test_env *te, Test_meta meta)
1670 {
1671         Test_op ret = TO_NONOP;
1672         int uqword;
1673         const char *p;
1674
1675         if (!*te->pos.wp)
1676                 return (meta == TM_END ? TO_NONNULL : TO_NONOP);
1677
1678         /* unquoted word? */
1679         for (p = *te->pos.wp; *p == CHAR; p += 2)
1680                 ;
1681         uqword = *p == EOS;
1682
1683         if (meta == TM_UNOP || meta == TM_BINOP) {
1684                 if (uqword) {
1685                         /* longer than the longest operator */
1686                         char buf[8];
1687                         char *q = buf;
1688
1689                         p = *te->pos.wp;
1690                         while (*p++ == CHAR &&
1691                             (size_t)(q - buf) < sizeof(buf) - 1)
1692                                 *q++ = *p++;
1693                         *q = '\0';
1694                         ret = test_isop(meta, buf);
1695                 }
1696         } else if (meta == TM_END)
1697                 ret = TO_NONOP;
1698         else
1699                 ret = (uqword && !strcmp(*te->pos.wp,
1700                     dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP;
1701
1702         /* Accept the token? */
1703         if (ret != TO_NONOP)
1704                 te->pos.wp++;
1705
1706         return (ret);
1707 }
1708
1709 static const char *
1710 dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
1711 {
1712         const char *s = *te->pos.wp;
1713
1714         if (!s)
1715                 return (NULL);
1716
1717         te->pos.wp++;
1718
1719         if (!do_eval)
1720                 return (null);
1721
1722         if (op == TO_STEQL || op == TO_STNEQ)
1723                 s = evalstr(s, DOTILDE | DOPAT);
1724         else
1725                 s = evalstr(s, DOTILDE);
1726
1727         return (s);
1728 }
1729
1730 static void
1731 dbteste_error(Test_env *te, int offset, const char *msg)
1732 {
1733         te->flags |= TEF_ERROR;
1734         internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
1735 }