OSDN Git Service

Upgrade to mksh R53a.
[android-x86/external-mksh.git] / src / 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
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.179 2016/08/01 21:38:02 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, xerrok);
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                         /* TSELECT */
343                         for (;;) {
344                                 if (!(ccp = do_selectargs(ap, is_first))) {
345                                         rv = 1;
346                                         break;
347                                 }
348                                 is_first = false;
349                                 setstr(global(t->str), ccp, KSH_UNWIND_ERROR);
350                                 execute(t->left, flags & XERROK, xerrok);
351                         }
352                 }
353                 break;
354         }
355
356         case TWHILE:
357         case TUNTIL:
358                 e->type = E_LOOP;
359                 while ((i = kshsetjmp(e->jbuf))) {
360                         if ((e->flags&EF_BRKCONT_PASS) ||
361                             (i != LBREAK && i != LCONTIN)) {
362                                 quitenv(NULL);
363                                 unwind(i);
364                         } else if (i == LBREAK) {
365                                 rv = 0;
366                                 goto Break;
367                         }
368                 }
369                 /* in case of a continue */
370                 rv = 0;
371                 while ((execute(t->left, XERROK, NULL) == 0) ==
372                     (t->type == TWHILE))
373                         rv = execute(t->right, flags & XERROK, xerrok);
374                 break;
375
376         case TIF:
377         case TELIF:
378                 if (t->right == NULL)
379                         /* should be error */
380                         break;
381                 rv = execute(t->left, XERROK, NULL) == 0 ?
382                     execute(t->right->left, flags & XERROK, xerrok) :
383                     execute(t->right->right, flags & XERROK, xerrok);
384                 break;
385
386         case TCASE:
387                 i = 0;
388                 ccp = evalstr(t->str, DOTILDE | DOSCALAR);
389                 for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
390                         for (ap = (const char **)t->vars; *ap; ap++) {
391                                 if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
392                                     gmatchx(ccp, s, false))) {
393                                         record_match(ccp);
394                                         rv = execute(t->left, flags & XERROK,
395                                             xerrok);
396                                         i = 0;
397                                         switch (t->u.charflag) {
398                                         case '&':
399                                                 i = 1;
400                                                 /* FALLTHROUGH */
401                                         case '|':
402                                                 goto TCASE_next;
403                                         }
404                                         goto TCASE_out;
405                                 }
406                         }
407                         i = 0;
408  TCASE_next:
409                         /* empty */;
410                 }
411  TCASE_out:
412                 break;
413
414         case TBRACE:
415                 rv = execute(t->left, flags & XERROK, xerrok);
416                 break;
417
418         case TFUNCT:
419                 rv = define(t->str, t);
420                 break;
421
422         case TTIME:
423                 /*
424                  * Clear XEXEC so nested execute() call doesn't exit
425                  * (allows "ls -l | time grep foo").
426                  */
427                 rv = timex(t, flags & ~XEXEC, xerrok);
428                 break;
429
430         case TEXEC:
431                 /* an eval'd TCOM */
432                 up = makenv();
433                 restoresigs();
434                 cleanup_proc_env();
435                 {
436                         union mksh_ccphack cargs;
437
438                         cargs.ro = t->args;
439                         execve(t->str, cargs.rw, up);
440                         rv = errno;
441                 }
442                 if (rv == ENOEXEC)
443                         scriptexec(t, (const char **)up);
444                 else
445                         errorf(Tf_sD_s, t->str, cstrerror(rv));
446         }
447  Break:
448         exstat = rv & 0xFF;
449         if (vp_pipest->flag & INT_L) {
450                 unset(vp_pipest, 1);
451                 vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
452                     ARRAY | INT_U | INT_L;
453                 vp_pipest->val.i = rv;
454         }
455
456         /* restores IO */
457         quitenv(NULL);
458         if ((flags&XEXEC))
459                 /* exit child */
460                 unwind(LEXIT);
461         if (rv != 0 && !(flags & XERROK) &&
462             (xerrok == NULL || !*xerrok)) {
463                 if (Flag(FERREXIT) & 0x80) {
464                         /* inside eval */
465                         Flag(FERREXIT) = 0;
466                 } else {
467                         trapsig(ksh_SIGERR);
468                         if (Flag(FERREXIT))
469                                 unwind(LERROR);
470                 }
471         }
472         return (rv);
473 }
474
475 /*
476  * execute simple command
477  */
478
479 static int
480 comexec(struct op *t, struct tbl * volatile tp, const char **ap,
481     volatile int flags, volatile int *xerrok)
482 {
483         int i;
484         volatile int rv = 0;
485         const char *cp;
486         const char **lastp;
487         /* Must be static (XXX but why?) */
488         static struct op texec;
489         int type_flags;
490         bool resetspec;
491         int fcflags = FC_BI|FC_FUNC|FC_PATH;
492         struct block *l_expand, *l_assign;
493         int optc;
494         const char *exec_argv0 = NULL;
495         bool exec_clrenv = false;
496
497         /* snag the last argument for $_ */
498         if (Flag(FTALKING) && *(lastp = ap)) {
499                 /*
500                  * XXX not the same as AT&T ksh, which only seems to set $_
501                  * after a newline (but not in functions/dot scripts, but in
502                  * interactive and script) - perhaps save last arg here and
503                  * set it in shell()?.
504                  */
505                 while (*++lastp)
506                         ;
507                 /* setstr() can't fail here */
508                 setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp,
509                     KSH_RETURN_ERROR);
510         }
511
512         /**
513          * Deal with the shell builtins builtin, exec and command since
514          * they can be followed by other commands. This must be done before
515          * we know if we should create a local block which must be done
516          * before we can do a path search (in case the assignments change
517          * PATH).
518          * Odd cases:
519          *      FOO=bar exec >/dev/null         FOO is kept but not exported
520          *      FOO=bar exec foobar             FOO is exported
521          *      FOO=bar command exec >/dev/null FOO is neither kept nor exported
522          *      FOO=bar command                 FOO is neither kept nor exported
523          *      PATH=... foobar                 use new PATH in foobar search
524          */
525         resetspec = false;
526         while (tp && tp->type == CSHELL) {
527                 /* undo effects of command */
528                 fcflags = FC_BI|FC_FUNC|FC_PATH;
529                 if (tp->val.f == c_builtin) {
530                         if ((cp = *++ap) == NULL ||
531                             (!strcmp(cp, "--") && (cp = *++ap) == NULL)) {
532                                 tp = NULL;
533                                 break;
534                         }
535                         if ((tp = findcom(cp, FC_BI)) == NULL)
536                                 errorf(Tf_sD_sD_s, Tbuiltin, cp, Tnot_found);
537                         if (tp->type == CSHELL && (tp->flag & LOW_BI))
538                                 break;
539                         continue;
540                 } else if (tp->val.f == c_exec) {
541                         if (ap[1] == NULL)
542                                 break;
543                         ksh_getopt_reset(&builtin_opt, GF_ERROR);
544                         while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1)
545                                 switch (optc) {
546                                 case 'a':
547                                         exec_argv0 = builtin_opt.optarg;
548                                         break;
549                                 case 'c':
550                                         exec_clrenv = true;
551                                         /* ensure we can actually do this */
552                                         resetspec = true;
553                                         break;
554                                 default:
555                                         rv = 2;
556                                         goto Leave;
557                                 }
558                         ap += builtin_opt.optind;
559                         flags |= XEXEC;
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) && vstrchr(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(Tf_sd, "CFUNC", 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                 unsigned short m;
892                 ssize_t n;
893
894                 /* read first couple of octets from file */
895                 n = read(fd, buf, sizeof(buf) - 1);
896                 close(fd);
897                 /* read error or short read? */
898                 if (n < 5)
899                         goto nomagic;
900                 /* terminate buffer */
901                 buf[n] = '\0';
902
903                 /* skip UTF-8 Byte Order Mark, if present */
904                 cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
905                     (buf[2] == 0xBF)) ? 3 : 0);
906
907                 /* scan for newline or NUL (end of buffer) */
908                 while (*cp && *cp != '\n')
909                         ++cp;
910                 /* if the shebang line is longer than MAXINTERP, bail out */
911                 if (!*cp)
912                         goto noshebang;
913                 /* replace newline by NUL */
914                 *cp = '\0';
915
916                 /* restore begin of shebang position (buf+0 or buf+3) */
917                 cp = buf + n;
918                 /* bail out if no shebang magic found */
919                 if (cp[0] == '#' && cp[1] == '!')
920                         cp += 2;
921 #ifdef __OS2__
922                 else if (!strncmp(cp, Textproc, 7) &&
923                     (cp[7] == ' ' || cp[7] == '\t'))
924                         cp += 8;
925 #endif
926                 else
927                         goto noshebang;
928                 /* skip whitespace before shell name */
929                 while (*cp == ' ' || *cp == '\t')
930                         ++cp;
931                 /* just whitespace on the line? */
932                 if (*cp == '\0')
933                         goto noshebang;
934                 /* no, we actually found an interpreter name */
935                 sh = (char *)cp;
936                 /* look for end of shell/interpreter name */
937                 while (*cp != ' ' && *cp != '\t' && *cp != '\0')
938                         ++cp;
939                 /* any arguments? */
940                 if (*cp) {
941                         *cp++ = '\0';
942                         /* skip spaces before arguments */
943                         while (*cp == ' ' || *cp == '\t')
944                                 ++cp;
945                         /* pass it all in ONE argument (historic reasons) */
946                         if (*cp)
947                                 *tp->args-- = (char *)cp;
948                 }
949                 goto nomagic;
950  noshebang:
951                 m = buf[0] << 8 | buf[1];
952                 if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
953                         errorf("%s: not executable: %d-bit ELF file", tp->str,
954                             32 * buf[4]);
955                 if ((m == /* OMAGIC */ 0407) ||
956                     (m == /* NMAGIC */ 0410) ||
957                     (m == /* ZMAGIC */ 0413) ||
958                     (m == /* QMAGIC */ 0314) ||
959                     (m == /* ECOFF_I386 */ 0x4C01) ||
960                     (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
961                     (m == /* ECOFF_SH */   0x0500 || m == 0x0005) ||
962                     (m == /* bzip */ 0x425A) || (m == /* "MZ" */ 0x4D5A) ||
963                     (m == /* "NE" */ 0x4E45) || (m == /* "LX" */ 0x4C58) ||
964                     (m == /* ksh93 */ 0x0B13) || (m == /* LZIP */ 0x4C5A) ||
965                     (m == /* xz */ 0xFD37 && buf[2] == 'z' && buf[3] == 'X' &&
966                     buf[4] == 'Z') || (m == /* 7zip */ 0x377A) ||
967                     (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
968                         errorf("%s: not executable: magic %04X", tp->str, m);
969  nomagic:
970                 ;
971         }
972 #endif
973         args.ro = tp->args;
974         *args.ro = sh;
975
976         cap.ro = ap;
977         execve(args.rw[0], args.rw, cap.rw);
978
979         /* report both the programme that was run and the bogus interpreter */
980         errorf(Tf_sD_sD_s, tp->str, sh, cstrerror(errno));
981 }
982
983 int
984 shcomexec(const char **wp)
985 {
986         struct tbl *tp;
987
988         tp = ktsearch(&builtins, *wp, hash(*wp));
989         return (call_builtin(tp, wp, "shcomexec", false));
990 }
991
992 /*
993  * Search function tables for a function. If create set, a table entry
994  * is created if none is found.
995  */
996 struct tbl *
997 findfunc(const char *name, uint32_t h, bool create)
998 {
999         struct block *l;
1000         struct tbl *tp = NULL;
1001
1002         for (l = e->loc; l; l = l->next) {
1003                 tp = ktsearch(&l->funs, name, h);
1004                 if (tp)
1005                         break;
1006                 if (!l->next && create) {
1007                         tp = ktenter(&l->funs, name, h);
1008                         tp->flag = DEFINED;
1009                         tp->type = CFUNC;
1010                         tp->val.t = NULL;
1011                         break;
1012                 }
1013         }
1014         return (tp);
1015 }
1016
1017 /*
1018  * define function. Returns 1 if function is being undefined (t == 0) and
1019  * function did not exist, returns 0 otherwise.
1020  */
1021 int
1022 define(const char *name, struct op *t)
1023 {
1024         uint32_t nhash;
1025         struct tbl *tp;
1026         bool was_set = false;
1027
1028         nhash = hash(name);
1029
1030         while (/* CONSTCOND */ 1) {
1031                 tp = findfunc(name, nhash, true);
1032
1033                 if (tp->flag & ISSET)
1034                         was_set = true;
1035                 /*
1036                  * If this function is currently being executed, we zap
1037                  * this table entry so findfunc() won't see it
1038                  */
1039                 if (tp->flag & FINUSE) {
1040                         tp->name[0] = '\0';
1041                         /* ensure it won't be found */
1042                         tp->flag &= ~DEFINED;
1043                         tp->flag |= FDELETE;
1044                 } else
1045                         break;
1046         }
1047
1048         if (tp->flag & ALLOC) {
1049                 tp->flag &= ~(ISSET|ALLOC|FKSH);
1050                 tfree(tp->val.t, tp->areap);
1051         }
1052
1053         if (t == NULL) {
1054                 /* undefine */
1055                 ktdelete(tp);
1056                 return (was_set ? 0 : 1);
1057         }
1058
1059         tp->val.t = tcopy(t->left, tp->areap);
1060         tp->flag |= (ISSET|ALLOC);
1061         if (t->u.ksh_func)
1062                 tp->flag |= FKSH;
1063
1064         return (0);
1065 }
1066
1067 /*
1068  * add builtin
1069  */
1070 const char *
1071 builtin(const char *name, int (*func) (const char **))
1072 {
1073         struct tbl *tp;
1074         uint32_t flag = DEFINED;
1075
1076         /* see if any flags should be set for this builtin */
1077  flags_loop:
1078         switch (*name) {
1079         case '=':
1080                 /* command does variable assignment */
1081                 flag |= KEEPASN;
1082                 break;
1083         case '*':
1084                 /* POSIX special builtin */
1085                 flag |= SPEC_BI;
1086                 break;
1087         case '~':
1088                 /* external utility overrides built-in utility, always */
1089                 flag |= LOWER_BI;
1090                 /* FALLTHROUGH */
1091         case '!':
1092                 /* external utility overrides built-in utility, with flags */
1093                 flag |= LOW_BI;
1094                 break;
1095         default:
1096                 goto flags_seen;
1097         }
1098         ++name;
1099         goto flags_loop;
1100  flags_seen:
1101
1102         /* enter into the builtins hash table */
1103         tp = ktenter(&builtins, name, hash(name));
1104         tp->flag = flag;
1105         tp->type = CSHELL;
1106         tp->val.f = func;
1107
1108         /* return name, for direct builtin call check in main.c */
1109         return (name);
1110 }
1111
1112 /*
1113  * find command
1114  * either function, hashed command, or built-in (in that order)
1115  */
1116 struct tbl *
1117 findcom(const char *name, int flags)
1118 {
1119         static struct tbl temp;
1120         uint32_t h = hash(name);
1121         struct tbl *tp = NULL, *tbi;
1122         /* insert if not found */
1123         unsigned char insert = Flag(FTRACKALL);
1124         /* for function autoloading */
1125         char *fpath;
1126         union mksh_cchack npath;
1127
1128         if (vstrchr(name, '/')) {
1129                 insert = 0;
1130                 /* prevent FPATH search below */
1131                 flags &= ~FC_FUNC;
1132                 goto Search;
1133         }
1134         tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
1135         /*
1136          * POSIX says special builtins first, then functions, then
1137          * regular builtins, then search path...
1138          */
1139         if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
1140                 tp = tbi;
1141         if (!tp && (flags & FC_FUNC)) {
1142                 tp = findfunc(name, h, false);
1143                 if (tp && !(tp->flag & ISSET)) {
1144                         if ((fpath = str_val(global(TFPATH))) == null) {
1145                                 tp->u.fpath = NULL;
1146                                 tp->u2.errnov = ENOENT;
1147                         } else
1148                                 tp->u.fpath = search_path(name, fpath, R_OK,
1149                                     &tp->u2.errnov);
1150                 }
1151         }
1152         if (!tp && (flags & FC_NORMBI) && tbi)
1153                 tp = tbi;
1154         if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
1155                 tp = ktsearch(&taliases, name, h);
1156                 if (tp && (tp->flag & ISSET) &&
1157                     ksh_access(tp->val.s, X_OK) != 0) {
1158                         if (tp->flag & ALLOC) {
1159                                 tp->flag &= ~ALLOC;
1160                                 afree(tp->val.s, APERM);
1161                         }
1162                         tp->flag &= ~ISSET;
1163                 }
1164         }
1165
1166  Search:
1167         if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
1168             (flags & FC_PATH)) {
1169                 if (!tp) {
1170                         if (insert && !(flags & FC_DEFPATH)) {
1171                                 tp = ktenter(&taliases, name, h);
1172                                 tp->type = CTALIAS;
1173                         } else {
1174                                 tp = &temp;
1175                                 tp->type = CEXEC;
1176                         }
1177                         /* make ~ISSET */
1178                         tp->flag = DEFINED;
1179                 }
1180                 npath.ro = search_path(name,
1181                     (flags & FC_DEFPATH) ? def_path : path,
1182                     X_OK, &tp->u2.errnov);
1183                 if (npath.ro) {
1184                         strdupx(tp->val.s, npath.ro, APERM);
1185                         if (npath.ro != name)
1186                                 afree(npath.rw, ATEMP);
1187                         tp->flag |= ISSET|ALLOC;
1188                 } else if ((flags & FC_FUNC) &&
1189                     (fpath = str_val(global(TFPATH))) != null &&
1190                     (npath.ro = search_path(name, fpath, R_OK,
1191                     &tp->u2.errnov)) != NULL) {
1192                         /*
1193                          * An undocumented feature of AT&T ksh is that
1194                          * it searches FPATH if a command is not found,
1195                          * even if the command hasn't been set up as an
1196                          * autoloaded function (ie, no typeset -uf).
1197                          */
1198                         tp = &temp;
1199                         tp->type = CFUNC;
1200                         /* make ~ISSET */
1201                         tp->flag = DEFINED;
1202                         tp->u.fpath = npath.ro;
1203                 }
1204         }
1205         return (tp);
1206 }
1207
1208 /*
1209  * flush executable commands with relative paths
1210  * (just relative or all?)
1211  */
1212 void
1213 flushcom(bool all)
1214 {
1215         struct tbl *tp;
1216         struct tstate ts;
1217
1218         for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
1219                 if ((tp->flag&ISSET) && (all || !mksh_abspath(tp->val.s))) {
1220                         if (tp->flag&ALLOC) {
1221                                 tp->flag &= ~(ALLOC|ISSET);
1222                                 afree(tp->val.s, APERM);
1223                         }
1224                         tp->flag &= ~ISSET;
1225                 }
1226 }
1227
1228 /* check if path is something we want to find */
1229 int
1230 search_access(const char *fn, int mode)
1231 {
1232         struct stat sb;
1233
1234         if (stat(fn, &sb) < 0)
1235                 /* file does not exist */
1236                 return (ENOENT);
1237         /* LINTED use of access */
1238         if (access(fn, mode) < 0) {
1239                 /* file exists, but we can't access it */
1240                 int eno;
1241
1242                 eno = errno;
1243                 return (eno ? eno : EACCES);
1244         }
1245         if (mode == X_OK && (!S_ISREG(sb.st_mode) ||
1246             !(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
1247                 /* access(2) may say root can execute everything */
1248                 return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES);
1249         return (0);
1250 }
1251
1252 /*
1253  * search for command with PATH
1254  */
1255 const char *
1256 search_path(const char *name, const char *lpath,
1257     /* R_OK or X_OK */
1258     int mode,
1259     /* set if candidate found, but not suitable */
1260     int *errnop)
1261 {
1262         const char *sp, *p;
1263         char *xp;
1264         XString xs;
1265         size_t namelen;
1266         int ec = 0, ev;
1267
1268         if (vstrchr(name, '/')) {
1269                 if ((ec = search_access(name, mode)) == 0) {
1270  search_path_ok:
1271                         if (errnop)
1272                                 *errnop = 0;
1273                         return (name);
1274                 }
1275                 goto search_path_err;
1276         }
1277
1278         namelen = strlen(name) + 1;
1279         Xinit(xs, xp, 128, ATEMP);
1280
1281         sp = lpath;
1282         while (sp != NULL) {
1283                 xp = Xstring(xs, xp);
1284                 if (!(p = cstrchr(sp, MKSH_PATHSEPC)))
1285                         p = sp + strlen(sp);
1286                 if (p != sp) {
1287                         XcheckN(xs, xp, p - sp);
1288                         memcpy(xp, sp, p - sp);
1289                         xp += p - sp;
1290                         *xp++ = '/';
1291                 }
1292                 sp = p;
1293                 XcheckN(xs, xp, namelen);
1294                 memcpy(xp, name, namelen);
1295                 if ((ev = search_access(Xstring(xs, xp), mode)) == 0) {
1296                         name = Xclose(xs, xp + namelen);
1297                         goto search_path_ok;
1298                 }
1299                 /* accumulate non-ENOENT errors only */
1300                 if (ev != ENOENT && ec == 0)
1301                         ec = ev;
1302                 if (*sp++ == '\0')
1303                         sp = NULL;
1304         }
1305         Xfree(xs, xp);
1306  search_path_err:
1307         if (errnop)
1308                 *errnop = ec ? ec : ENOENT;
1309         return (NULL);
1310 }
1311
1312 static int
1313 call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
1314 {
1315         int rv;
1316
1317         if (!tp)
1318                 internal_errorf(Tf_sD_s, where, wp[0]);
1319         builtin_argv0 = wp[0];
1320         builtin_spec = tobool(!resetspec &&
1321             /*XXX odd use of KEEPASN */
1322             ((tp->flag & SPEC_BI) || (Flag(FPOSIX) && (tp->flag & KEEPASN))));
1323         shf_reopen(1, SHF_WR, shl_stdout);
1324         shl_stdout_ok = true;
1325         ksh_getopt_reset(&builtin_opt, GF_ERROR);
1326         rv = (*tp->val.f)(wp);
1327         shf_flush(shl_stdout);
1328         shl_stdout_ok = false;
1329         builtin_argv0 = NULL;
1330         builtin_spec = false;
1331         return (rv);
1332 }
1333
1334 /*
1335  * set up redirection, saving old fds in e->savefd
1336  */
1337 static int
1338 iosetup(struct ioword *iop, struct tbl *tp)
1339 {
1340         int u = -1;
1341         char *cp = iop->ioname;
1342         int iotype = iop->ioflag & IOTYPE;
1343         bool do_open = true, do_close = false, do_fstat = false;
1344         int flags = 0;
1345         struct ioword iotmp;
1346         struct stat statb;
1347
1348         if (iotype != IOHERE)
1349                 cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
1350
1351         /* Used for tracing and error messages to print expanded cp */
1352         iotmp = *iop;
1353         iotmp.ioname = (iotype == IOHERE) ? NULL : cp;
1354         iotmp.ioflag |= IONAMEXP;
1355
1356         if (Flag(FXTRACE)) {
1357                 change_xtrace(2, false);
1358                 fptreef(shl_xtrace, 0, Tft_R, &iotmp);
1359                 change_xtrace(1, false);
1360         }
1361
1362         switch (iotype) {
1363         case IOREAD:
1364                 flags = O_RDONLY;
1365                 break;
1366
1367         case IOCAT:
1368                 flags = O_WRONLY | O_APPEND | O_CREAT;
1369                 break;
1370
1371         case IOWRITE:
1372                 if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB)) {
1373                         /* >file under set -C */
1374                         if (stat(cp, &statb)) {
1375                                 /* nonexistent file */
1376                                 flags = O_WRONLY | O_CREAT | O_EXCL;
1377                         } else if (S_ISREG(statb.st_mode)) {
1378                                 /* regular file, refuse clobbering */
1379                                 goto clobber_refused;
1380                         } else {
1381                                 /*
1382                                  * allow redirections to things
1383                                  * like /dev/null without error
1384                                  */
1385                                 flags = O_WRONLY;
1386                                 /* but check again after opening */
1387                                 do_fstat = true;
1388                         }
1389                 } else {
1390                         /* >|file or set +C */
1391                         flags = O_WRONLY | O_CREAT | O_TRUNC;
1392                 }
1393                 break;
1394
1395         case IORDWR:
1396                 flags = O_RDWR | O_CREAT;
1397                 break;
1398
1399         case IOHERE:
1400                 do_open = false;
1401                 /* herein() returns -2 if error has been printed */
1402                 u = herein(iop, NULL);
1403                 /* cp may have wrong name */
1404                 break;
1405
1406         case IODUP: {
1407                 const char *emsg;
1408
1409                 do_open = false;
1410                 if (ksh_isdash(cp)) {
1411                         /* prevent error return below */
1412                         u = 1009;
1413                         do_close = true;
1414                 } else if ((u = check_fd(cp,
1415                     X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
1416                     &emsg)) < 0) {
1417                         char *sp;
1418
1419                         warningf(true, Tf_sD_s,
1420                             (sp = snptreef(NULL, 32, Tft_R, &iotmp)), emsg);
1421                         afree(sp, ATEMP);
1422                         return (-1);
1423                 }
1424                 if (u == (int)iop->unit)
1425                         /* "dup from" == "dup to" */
1426                         return (0);
1427                 break;
1428             }
1429         }
1430
1431         if (do_open) {
1432                 if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
1433                         warningf(true, Tf_sD_s, cp, "restricted");
1434                         return (-1);
1435                 }
1436                 u = binopen3(cp, flags, 0666);
1437                 if (do_fstat && u >= 0) {
1438                         /* prevent race conditions */
1439                         if (fstat(u, &statb) || S_ISREG(statb.st_mode)) {
1440                                 close(u);
1441  clobber_refused:
1442                                 u = -1;
1443                                 errno = EEXIST;
1444                         }
1445                 }
1446         }
1447         if (u < 0) {
1448                 /* herein() may already have printed message */
1449                 if (u == -1) {
1450                         u = errno;
1451                         warningf(true, Tf_cant,
1452                             iotype == IODUP ? "dup" :
1453                             (iotype == IOREAD || iotype == IOHERE) ?
1454                             Topen : Tcreate, cp, cstrerror(u));
1455                 }
1456                 return (-1);
1457         }
1458         /* Do not save if it has already been redirected (i.e. "cat >x >y"). */
1459         if (e->savefd[iop->unit] == 0) {
1460                 /* If these are the same, it means unit was previously closed */
1461                 if (u == (int)iop->unit)
1462                         e->savefd[iop->unit] = -1;
1463                 else
1464                         /*
1465                          * c_exec() assumes e->savefd[fd] set for any
1466                          * redirections. Ask savefd() not to close iop->unit;
1467                          * this allows error messages to be seen if iop->unit
1468                          * is 2; also means we can't lose the fd (eg, both
1469                          * dup2 below and dup2 in restfd() failing).
1470                          */
1471                         e->savefd[iop->unit] = savefd(iop->unit);
1472         }
1473
1474         if (do_close)
1475                 close(iop->unit);
1476         else if (u != (int)iop->unit) {
1477                 if (ksh_dup2(u, iop->unit, true) < 0) {
1478                         int eno;
1479                         char *sp;
1480
1481                         eno = errno;
1482                         warningf(true, Tf_s_sD_s, Tredirection_dup,
1483                             (sp = snptreef(NULL, 32, Tft_R, &iotmp)),
1484                             cstrerror(eno));
1485                         afree(sp, ATEMP);
1486                         if (iotype != IODUP)
1487                                 close(u);
1488                         return (-1);
1489                 }
1490                 if (iotype != IODUP)
1491                         close(u);
1492                 /*
1493                  * Touching any co-process fd in an empty exec
1494                  * causes the shell to close its copies
1495                  */
1496                 else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
1497                         if (iop->ioflag & IORDUP)
1498                                 /* possible exec <&p */
1499                                 coproc_read_close(u);
1500                         else
1501                                 /* possible exec >&p */
1502                                 coproc_write_close(u);
1503                 }
1504         }
1505         if (u == 2)
1506                 /* Clear any write errors */
1507                 shf_reopen(2, SHF_WR, shl_out);
1508         return (0);
1509 }
1510
1511 /*
1512  * Process here documents by providing the content, either as
1513  * result (globally allocated) string or in a temp file; if
1514  * unquoted, the string is expanded first.
1515  */
1516 static int
1517 hereinval(struct ioword *iop, int sub, char **resbuf, struct shf *shf)
1518 {
1519         const char * volatile ccp = iop->heredoc;
1520         struct source *s, *osource;
1521
1522         osource = source;
1523         newenv(E_ERRH);
1524         if (kshsetjmp(e->jbuf)) {
1525                 source = osource;
1526                 quitenv(shf);
1527                 /* special to iosetup(): don't print error */
1528                 return (-2);
1529         }
1530         if (iop->ioflag & IOHERESTR) {
1531                 ccp = evalstr(iop->delim, DOHERESTR | DOSCALAR | DOHEREDOC);
1532         } else if (sub) {
1533                 /* do substitutions on the content of heredoc */
1534                 s = pushs(SSTRING, ATEMP);
1535                 s->start = s->str = ccp;
1536                 source = s;
1537                 if (yylex(sub) != LWORD)
1538                         internal_errorf("herein: yylex");
1539                 source = osource;
1540                 ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
1541         }
1542
1543         if (resbuf == NULL)
1544                 shf_puts(ccp, shf);
1545         else
1546                 strdupx(*resbuf, ccp, APERM);
1547
1548         quitenv(NULL);
1549         return (0);
1550 }
1551
1552 int
1553 herein(struct ioword *iop, char **resbuf)
1554 {
1555         int fd = -1;
1556         struct shf *shf;
1557         struct temp *h;
1558         int i;
1559
1560         /* lexer substitution flags */
1561         i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
1562
1563         /* skip all the fd setup if we just want the value */
1564         if (resbuf != NULL)
1565                 return (hereinval(iop, i, resbuf, NULL));
1566
1567         /*
1568          * Create temp file to hold content (done before newenv
1569          * so temp doesn't get removed too soon).
1570          */
1571         h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
1572         if (!(shf = h->shf) || (fd = binopen3(h->tffn, O_RDONLY, 0)) < 0) {
1573                 i = errno;
1574                 warningf(true, Tf_temp,
1575                     !shf ? Tcreate : Topen, h->tffn, cstrerror(i));
1576                 if (shf)
1577                         shf_close(shf);
1578                 /* special to iosetup(): don't print error */
1579                 return (-2);
1580         }
1581
1582         if (hereinval(iop, i, NULL, shf) == -2) {
1583                 close(fd);
1584                 /* special to iosetup(): don't print error */
1585                 return (-2);
1586         }
1587
1588         if (shf_close(shf) == -1) {
1589                 i = errno;
1590                 close(fd);
1591                 warningf(true, Tf_temp,
1592                     Twrite, h->tffn, cstrerror(i));
1593                 /* special to iosetup(): don't print error */
1594                 return (-2);
1595         }
1596
1597         return (fd);
1598 }
1599
1600 /*
1601  *      ksh special - the select command processing section
1602  *      print the args in column form - assuming that we can
1603  */
1604 static const char *
1605 do_selectargs(const char **ap, bool print_menu)
1606 {
1607         static const char *read_args[] = {
1608                 Tread, "-r", "REPLY", NULL
1609         };
1610         char *s;
1611         int i, argct;
1612
1613         for (argct = 0; ap[argct]; argct++)
1614                 ;
1615         while (/* CONSTCOND */ 1) {
1616                 /*-
1617                  * Menu is printed if
1618                  *      - this is the first time around the select loop
1619                  *      - the user enters a blank line
1620                  *      - the REPLY parameter is empty
1621                  */
1622                 if (print_menu || !*str_val(global("REPLY")))
1623                         pr_menu(ap);
1624                 shellf(Tf_s, str_val(global("PS3")));
1625                 if (call_builtin(findcom(Tread, FC_BI), read_args, Tselect,
1626                     false))
1627                         return (NULL);
1628                 if (*(s = str_val(global("REPLY"))))
1629                         return ((getn(s, &i) && i >= 1 && i <= argct) ?
1630                             ap[i - 1] : null);
1631                 print_menu = true;
1632         }
1633 }
1634
1635 struct select_menu_info {
1636         const char * const *args;
1637         int num_width;
1638 };
1639
1640 /* format a single select menu item */
1641 static void
1642 select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1643 {
1644         const struct select_menu_info *smi =
1645             (const struct select_menu_info *)arg;
1646
1647         shf_snprintf(buf, buflen, "%*u) %s",
1648             smi->num_width, i + 1, smi->args[i]);
1649 }
1650
1651 /*
1652  *      print a select style menu
1653  */
1654 void
1655 pr_menu(const char * const *ap)
1656 {
1657         struct select_menu_info smi;
1658         const char * const *pp;
1659         size_t acols = 0, aocts = 0, i;
1660         unsigned int n;
1661
1662         /*
1663          * width/column calculations were done once and saved, but this
1664          * means select can't be used recursively so we re-calculate
1665          * each time (could save in a structure that is returned, but
1666          * it's probably not worth the bother)
1667          */
1668
1669         /*
1670          * get dimensions of the list
1671          */
1672         for (n = 0, pp = ap; *pp; n++, pp++) {
1673                 i = strlen(*pp);
1674                 if (i > aocts)
1675                         aocts = i;
1676                 i = utf_mbswidth(*pp);
1677                 if (i > acols)
1678                         acols = i;
1679         }
1680
1681         /*
1682          * we will print an index of the form "%d) " in front of
1683          * each entry, so get the maximum width of this
1684          */
1685         for (i = n, smi.num_width = 1; i >= 10; i /= 10)
1686                 smi.num_width++;
1687
1688         smi.args = ap;
1689         print_columns(shl_out, n, select_fmt_entry, (void *)&smi,
1690             smi.num_width + 2 + aocts, smi.num_width + 2 + acols,
1691             true);
1692 }
1693
1694 static void
1695 plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1696 {
1697         strlcpy(buf, ((const char * const *)arg)[i], buflen);
1698 }
1699
1700 void
1701 pr_list(char * const *ap)
1702 {
1703         size_t acols = 0, aocts = 0, i;
1704         unsigned int n;
1705         char * const *pp;
1706
1707         for (n = 0, pp = ap; *pp; n++, pp++) {
1708                 i = strlen(*pp);
1709                 if (i > aocts)
1710                         aocts = i;
1711                 i = utf_mbswidth(*pp);
1712                 if (i > acols)
1713                         acols = i;
1714         }
1715
1716         print_columns(shl_out, n, plain_fmt_entry, (const void *)ap,
1717             aocts, acols, false);
1718 }
1719
1720 /*
1721  *      [[ ... ]] evaluation routines
1722  */
1723
1724 /*
1725  * Test if the current token is a whatever. Accepts the current token if
1726  * it is. Returns 0 if it is not, non-zero if it is (in the case of
1727  * TM_UNOP and TM_BINOP, the returned value is a Test_op).
1728  */
1729 static Test_op
1730 dbteste_isa(Test_env *te, Test_meta meta)
1731 {
1732         Test_op ret = TO_NONOP;
1733         bool uqword;
1734         const char *p;
1735
1736         if (!*te->pos.wp)
1737                 return (meta == TM_END ? TO_NONNULL : TO_NONOP);
1738
1739         /* unquoted word? */
1740         for (p = *te->pos.wp; *p == CHAR; p += 2)
1741                 ;
1742         uqword = *p == EOS;
1743
1744         if (meta == TM_UNOP || meta == TM_BINOP) {
1745                 if (uqword) {
1746                         /* longer than the longest operator */
1747                         char buf[8];
1748                         char *q = buf;
1749
1750                         p = *te->pos.wp;
1751                         while (*p++ == CHAR &&
1752                             (size_t)(q - buf) < sizeof(buf) - 1)
1753                                 *q++ = *p++;
1754                         *q = '\0';
1755                         ret = test_isop(meta, buf);
1756                 }
1757         } else if (meta == TM_END)
1758                 ret = TO_NONOP;
1759         else
1760                 ret = (uqword && !strcmp(*te->pos.wp,
1761                     dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP;
1762
1763         /* Accept the token? */
1764         if (ret != TO_NONOP)
1765                 te->pos.wp++;
1766
1767         return (ret);
1768 }
1769
1770 static const char *
1771 dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
1772 {
1773         const char *s = *te->pos.wp;
1774         int flags = DOTILDE | DOSCALAR;
1775
1776         if (!s)
1777                 return (NULL);
1778
1779         te->pos.wp++;
1780
1781         if (!do_eval)
1782                 return (null);
1783
1784         if (op == TO_STEQL || op == TO_STNEQ)
1785                 flags |= DOPAT;
1786
1787         return (evalstr(s, flags));
1788 }
1789
1790 static void
1791 dbteste_error(Test_env *te, int offset, const char *msg)
1792 {
1793         te->flags |= TEF_ERROR;
1794         internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
1795 }