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