OSDN Git Service

Upgrade to mksh R40.
[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.186 2016/11/11 23:31:34 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(t->left, XERROK, NULL) == 0 ?
380                     execute(t->right->left, flags & XERROK, xerrok) :
381                     execute(t->right->right, flags & XERROK, xerrok);
382                 break;
383
384         case TCASE:
385                 i = 0;
386                 ccp = evalstr(t->str, DOTILDE | DOSCALAR);
387                 for (t = t->left; t != NULL && t->type == TPAT; t = t->right) {
388                         for (ap = (const char **)t->vars; *ap; ap++) {
389                                 if (i || ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
390                                     gmatchx(ccp, s, false))) {
391                                         record_match(ccp);
392                                         rv = execute(t->left, flags & XERROK,
393                                             xerrok);
394                                         i = 0;
395                                         switch (t->u.charflag) {
396                                         case '&':
397                                                 i = 1;
398                                                 /* FALLTHROUGH */
399                                         case '|':
400                                                 goto TCASE_next;
401                                         }
402                                         goto TCASE_out;
403                                 }
404                         }
405                         i = 0;
406  TCASE_next:
407                         /* empty */;
408                 }
409  TCASE_out:
410                 break;
411
412         case TBRACE:
413                 rv = execute(t->left, flags & XERROK, xerrok);
414                 break;
415
416         case TFUNCT:
417                 rv = define(t->str, t);
418                 break;
419
420         case TTIME:
421                 /*
422                  * Clear XEXEC so nested execute() call doesn't exit
423                  * (allows "ls -l | time grep foo").
424                  */
425                 rv = timex(t, flags & ~XEXEC, xerrok);
426                 break;
427
428         case TEXEC:
429                 /* an eval'd TCOM */
430                 up = makenv();
431                 restoresigs();
432                 cleanup_proc_env();
433                 {
434                         union mksh_ccphack cargs;
435
436                         cargs.ro = t->args;
437                         execve(t->str, cargs.rw, up);
438                         rv = errno;
439                 }
440                 if (rv == ENOEXEC)
441                         scriptexec(t, (const char **)up);
442                 else
443                         errorf(Tf_sD_s, t->str, cstrerror(rv));
444         }
445  Break:
446         exstat = rv & 0xFF;
447         if (vp_pipest->flag & INT_L) {
448                 unset(vp_pipest, 1);
449                 vp_pipest->flag = DEFINED | ISSET | INTEGER | RDONLY |
450                     ARRAY | INT_U | INT_L;
451                 vp_pipest->val.i = rv;
452         }
453
454         /* restores IO */
455         quitenv(NULL);
456         if ((flags&XEXEC))
457                 /* exit child */
458                 unwind(LEXIT);
459         if (rv != 0 && !(flags & XERROK) &&
460             (xerrok == NULL || !*xerrok)) {
461                 if (Flag(FERREXIT) & 0x80) {
462                         /* inside eval */
463                         Flag(FERREXIT) = 0;
464                 } else {
465                         trapsig(ksh_SIGERR);
466                         if (Flag(FERREXIT))
467                                 unwind(LERROR);
468                 }
469         }
470         return (rv);
471 }
472
473 /*
474  * execute simple command
475  */
476
477 static int
478 comexec(struct op *t, struct tbl * volatile tp, const char **ap,
479     volatile int flags, volatile int *xerrok)
480 {
481         int i;
482         volatile int rv = 0;
483         const char *cp;
484         const char **lastp;
485         /* Must be static (XXX but why?) */
486         static struct op texec;
487         int type_flags;
488         bool resetspec;
489         int fcflags = FC_BI|FC_FUNC|FC_PATH;
490         struct block *l_expand, *l_assign;
491         int optc;
492         const char *exec_argv0 = NULL;
493         bool exec_clrenv = false;
494
495         /* snag the last argument for $_ */
496         if (Flag(FTALKING) && *(lastp = ap)) {
497                 /*
498                  * XXX not the same as AT&T ksh, which only seems to set $_
499                  * after a newline (but not in functions/dot scripts, but in
500                  * interactive and script) - perhaps save last arg here and
501                  * set it in shell()?.
502                  */
503                 while (*++lastp)
504                         ;
505                 /* setstr() can't fail here */
506                 setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp,
507                     KSH_RETURN_ERROR);
508         }
509
510         /**
511          * Deal with the shell builtins builtin, exec and command since
512          * they can be followed by other commands. This must be done before
513          * we know if we should create a local block which must be done
514          * before we can do a path search (in case the assignments change
515          * PATH).
516          * Odd cases:
517          *      FOO=bar exec >/dev/null         FOO is kept but not exported
518          *      FOO=bar exec foobar             FOO is exported
519          *      FOO=bar command exec >/dev/null FOO is neither kept nor exported
520          *      FOO=bar command                 FOO is neither kept nor exported
521          *      PATH=... foobar                 use new PATH in foobar search
522          */
523         resetspec = false;
524         while (tp && tp->type == CSHELL) {
525                 /* undo effects of command */
526                 fcflags = FC_BI|FC_FUNC|FC_PATH;
527                 if (tp->val.f == c_builtin) {
528                         if ((cp = *++ap) == NULL ||
529                             (!strcmp(cp, "--") && (cp = *++ap) == NULL)) {
530                                 tp = NULL;
531                                 break;
532                         }
533                         if ((tp = findcom(cp, FC_BI)) == NULL)
534                                 errorf(Tf_sD_sD_s, Tbuiltin, cp, Tnot_found);
535                         if (tp->type == CSHELL && (tp->flag & LOW_BI))
536                                 break;
537                         continue;
538                 } else if (tp->val.f == c_exec) {
539                         if (ap[1] == NULL)
540                                 break;
541                         ksh_getopt_reset(&builtin_opt, GF_ERROR);
542                         while ((optc = ksh_getopt(ap, &builtin_opt, "a:c")) != -1)
543                                 switch (optc) {
544                                 case 'a':
545                                         exec_argv0 = builtin_opt.optarg;
546                                         break;
547                                 case 'c':
548                                         exec_clrenv = true;
549                                         /* ensure we can actually do this */
550                                         resetspec = true;
551                                         break;
552                                 default:
553                                         rv = 2;
554                                         goto Leave;
555                                 }
556                         ap += builtin_opt.optind;
557                         flags |= XEXEC;
558                 } else if (tp->val.f == c_command) {
559                         bool saw_p = false;
560
561                         /*
562                          * Ugly dealing with options in two places (here
563                          * and in c_command(), but such is life)
564                          */
565                         ksh_getopt_reset(&builtin_opt, 0);
566                         while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
567                                 saw_p = true;
568                         if (optc != -1)
569                                 /* command -vV or something */
570                                 break;
571                         /* don't look for functions */
572                         fcflags = FC_BI|FC_PATH;
573                         if (saw_p) {
574                                 if (Flag(FRESTRICTED)) {
575                                         warningf(true, Tf_sD_s,
576                                             "command -p", "restricted");
577                                         rv = 1;
578                                         goto Leave;
579                                 }
580                                 fcflags |= FC_DEFPATH;
581                         }
582                         ap += builtin_opt.optind;
583                         /*
584                          * POSIX says special builtins lose their status
585                          * if accessed using command.
586                          */
587                         resetspec = true;
588                         if (!ap[0]) {
589                                 /* ensure command with no args exits with 0 */
590                                 subst_exstat = 0;
591                                 break;
592                         }
593                 } else if (tp->flag & LOW_BI) {
594                         /* if we have any flags, do not use the builtin */
595                         if ((ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
596                             /* argument, begins with -, is not - or -- */
597                             (ap[1][1] != '-' || ap[1][2] != '\0')) ||
598                             /* always prefer the external utility */
599                             (tp->flag & LOWER_BI)) {
600                                 struct tbl *ext_cmd;
601
602                                 ext_cmd = findcom(tp->name, FC_PATH | FC_FUNC);
603                                 if (ext_cmd && (ext_cmd->type != CTALIAS ||
604                                     (ext_cmd->flag & ISSET)))
605                                         tp = ext_cmd;
606                         }
607                         break;
608                 } else if (tp->val.f == c_trap) {
609                         t->u.evalflags &= ~DOTCOMEXEC;
610                         break;
611                 } else
612                         break;
613                 tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));
614         }
615         if (t->u.evalflags & DOTCOMEXEC)
616                 flags |= XEXEC;
617         l_expand = e->loc;
618         if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN))))
619                 type_flags = 0;
620         else {
621                 /* create new variable/function block */
622                 newblock();
623                 /* ksh functions don't keep assignments, POSIX functions do. */
624                 if (!resetspec && tp && tp->type == CFUNC &&
625                     !(tp->flag & FKSH))
626                         type_flags = EXPORT;
627                 else
628                         type_flags = LOCAL|LOCAL_COPY|EXPORT;
629         }
630         l_assign = e->loc;
631         if (exec_clrenv)
632                 l_assign->flags |= BF_STOPENV;
633         if (Flag(FEXPORT))
634                 type_flags |= EXPORT;
635         if (Flag(FXTRACE))
636                 change_xtrace(2, false);
637         for (i = 0; t->vars[i]; i++) {
638                 /* do NOT lookup in the new var/fn block just created */
639                 e->loc = l_expand;
640                 cp = evalstr(t->vars[i], DOASNTILDE | DOSCALAR);
641                 e->loc = l_assign;
642                 if (Flag(FXTRACE)) {
643                         const char *ccp;
644
645                         ccp = skip_varname(cp, true);
646                         if (*ccp == '+')
647                                 ++ccp;
648                         if (*ccp == '=')
649                                 ++ccp;
650                         shf_write(cp, ccp - cp, shl_xtrace);
651                         print_value_quoted(shl_xtrace, ccp);
652                         shf_putc(' ', shl_xtrace);
653                 }
654                 /* but assign in there as usual */
655                 typeset(cp, type_flags, 0, 0, 0);
656         }
657
658         if (Flag(FXTRACE)) {
659                 change_xtrace(2, false);
660                 if (ap[rv = 0]) {
661  xtrace_ap_loop:
662                         print_value_quoted(shl_xtrace, ap[rv]);
663                         if (ap[++rv]) {
664                                 shf_putc(' ', shl_xtrace);
665                                 goto xtrace_ap_loop;
666                         }
667                 }
668                 change_xtrace(1, false);
669         }
670
671         if ((cp = *ap) == NULL) {
672                 rv = subst_exstat;
673                 goto Leave;
674         } else if (!tp) {
675                 if (Flag(FRESTRICTED) && mksh_vdirsep(cp)) {
676                         warningf(true, Tf_sD_s, cp, "restricted");
677                         rv = 1;
678                         goto Leave;
679                 }
680                 tp = findcom(cp, fcflags);
681         }
682
683         switch (tp->type) {
684
685         /* shell built-in */
686         case CSHELL:
687  do_call_builtin:
688                 rv = call_builtin(tp, (const char **)ap, null, resetspec);
689                 if (resetspec && tp->val.f == c_shift) {
690                         l_expand->argc = l_assign->argc;
691                         l_expand->argv = l_assign->argv;
692                 }
693                 break;
694
695         /* function call */
696         case CFUNC: {
697                 volatile uint32_t old_inuse;
698                 const char * volatile old_kshname;
699                 volatile uint8_t old_flags[FNFLAGS];
700
701                 if (!(tp->flag & ISSET)) {
702                         struct tbl *ftp;
703
704                         if (!tp->u.fpath) {
705  fpath_error:
706                                 rv = (tp->u2.errnov == ENOENT) ? 127 : 126;
707                                 warningf(true, Tf_sD_s_sD_s, cp,
708                                     Tcant_find, Tfile_fd,
709                                     cstrerror(tp->u2.errnov));
710                                 break;
711                         }
712                         errno = 0;
713                         if (include(tp->u.fpath, 0, NULL, false) < 0 ||
714                             !(ftp = findfunc(cp, hash(cp), false)) ||
715                             !(ftp->flag & ISSET)) {
716                                 rv = errno;
717                                 if ((ftp = findcom(cp, FC_BI)) &&
718                                     (ftp->type == CSHELL) &&
719                                     (ftp->flag & LOW_BI)) {
720                                         tp = ftp;
721                                         goto do_call_builtin;
722                                 }
723                                 if (rv) {
724                                         tp->u2.errnov = rv;
725                                         cp = tp->u.fpath;
726                                         goto fpath_error;
727                                 }
728                                 warningf(true, Tf_sD_s_s, cp,
729                                     "function not defined by", tp->u.fpath);
730                                 rv = 127;
731                                 break;
732                         }
733                         tp = ftp;
734                 }
735
736                 /*
737                  * ksh functions set $0 to function name, POSIX
738                  * functions leave $0 unchanged.
739                  */
740                 old_kshname = kshname;
741                 if (tp->flag & FKSH)
742                         kshname = ap[0];
743                 else
744                         ap[0] = kshname;
745                 e->loc->argv = ap;
746                 for (i = 0; *ap++ != NULL; i++)
747                         ;
748                 e->loc->argc = i - 1;
749                 /*
750                  * ksh-style functions handle getopts sanely,
751                  * Bourne/POSIX functions are insane...
752                  */
753                 if (tp->flag & FKSH) {
754                         e->loc->flags |= BF_DOGETOPTS;
755                         e->loc->getopts_state = user_opt;
756                         getopts_reset(1);
757                 }
758
759                 for (type_flags = 0; type_flags < FNFLAGS; ++type_flags)
760                         old_flags[type_flags] = shell_flags[type_flags];
761                 change_xtrace((Flag(FXTRACEREC) ? Flag(FXTRACE) : 0) |
762                     ((tp->flag & TRACE) ? 1 : 0), false);
763                 old_inuse = tp->flag & FINUSE;
764                 tp->flag |= FINUSE;
765
766                 e->type = E_FUNC;
767                 if (!(i = kshsetjmp(e->jbuf))) {
768                         execute(tp->val.t, flags & XERROK, NULL);
769                         i = LRETURN;
770                 }
771
772                 kshname = old_kshname;
773                 change_xtrace(old_flags[(int)FXTRACE], false);
774 #ifndef MKSH_LEGACY_MODE
775                 if (tp->flag & FKSH) {
776                         /* Korn style functions restore Flags on return */
777                         old_flags[(int)FXTRACE] = Flag(FXTRACE);
778                         for (type_flags = 0; type_flags < FNFLAGS; ++type_flags)
779                                 shell_flags[type_flags] = old_flags[type_flags];
780                 }
781 #endif
782                 tp->flag = (tp->flag & ~FINUSE) | old_inuse;
783
784                 /*
785                  * Were we deleted while executing? If so, free the
786                  * execution tree.
787                  */
788                 if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
789                         if (tp->flag & ALLOC) {
790                                 tp->flag &= ~ALLOC;
791                                 tfree(tp->val.t, tp->areap);
792                         }
793                         tp->flag = 0;
794                 }
795                 switch (i) {
796                 case LRETURN:
797                 case LERROR:
798                         rv = exstat & 0xFF;
799                         break;
800                 case LINTR:
801                 case LEXIT:
802                 case LLEAVE:
803                 case LSHELL:
804                         quitenv(NULL);
805                         unwind(i);
806                         /* NOTREACHED */
807                 default:
808                         quitenv(NULL);
809                         internal_errorf(Tf_sd, "CFUNC", i);
810                 }
811                 break;
812         }
813
814         /* executable command */
815         case CEXEC:
816         /* tracked alias */
817         case CTALIAS:
818                 if (!(tp->flag&ISSET)) {
819                         if (tp->u2.errnov == ENOENT) {
820                                 rv = 127;
821                                 warningf(true, Tf_sD_s, cp, Tnot_found);
822                         } else {
823                                 rv = 126;
824                                 warningf(true, Tf_sD_sD_s, cp, "can't execute",
825                                     cstrerror(tp->u2.errnov));
826                         }
827                         break;
828                 }
829
830                 /* set $_ to program's full path */
831                 /* setstr() can't fail here */
832                 setstr(typeset("_", LOCAL | EXPORT, 0, INTEGER, 0),
833                     tp->val.s, KSH_RETURN_ERROR);
834
835                 /* to fork, we set up a TEXEC node and call execute */
836                 texec.type = TEXEC;
837                 /* for vistree/dumptree */
838                 texec.left = t;
839                 texec.str = tp->val.s;
840                 texec.args = ap;
841
842                 /* in this case we do not fork, of course */
843                 if (flags & XEXEC) {
844                         if (exec_argv0)
845                                 texec.args[0] = exec_argv0;
846                         j_exit();
847                         if (!(flags & XBGND)
848 #ifndef MKSH_UNEMPLOYED
849                             || Flag(FMONITOR)
850 #endif
851                             ) {
852                                 setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG);
853                                 setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG);
854                         }
855                 }
856
857                 rv = exchild(&texec, flags, xerrok, -1);
858                 break;
859         }
860  Leave:
861         if (flags & XEXEC) {
862                 exstat = rv & 0xFF;
863                 unwind(LLEAVE);
864         }
865         return (rv);
866 }
867
868 static void
869 scriptexec(struct op *tp, const char **ap)
870 {
871         const char *sh;
872 #ifndef MKSH_SMALL
873         int fd;
874         unsigned char buf[68];
875 #endif
876         union mksh_ccphack args, cap;
877
878         sh = str_val(global(TEXECSHELL));
879         if (sh && *sh)
880                 sh = search_path(sh, path, X_OK, NULL);
881         if (!sh || !*sh)
882                 sh = MKSH_DEFAULT_EXECSHELL;
883
884         *tp->args-- = tp->str;
885
886 #ifndef MKSH_SMALL
887         if ((fd = binopen2(tp->str, O_RDONLY)) >= 0) {
888                 unsigned char *cp;
889                 unsigned short m;
890                 ssize_t n;
891
892                 /* read first couple of octets from file */
893                 n = read(fd, buf, sizeof(buf) - 1);
894                 close(fd);
895                 /* read error or short read? */
896                 if (n < 5)
897                         goto nomagic;
898                 /* terminate buffer */
899                 buf[n] = '\0';
900
901                 /* skip UTF-8 Byte Order Mark, if present */
902                 cp = buf + (n = ((buf[0] == 0xEF) && (buf[1] == 0xBB) &&
903                     (buf[2] == 0xBF)) ? 3 : 0);
904
905                 /* scan for newline or NUL (end of buffer) */
906                 while (*cp && *cp != '\n')
907                         ++cp;
908                 /* if the shebang line is longer than MAXINTERP, bail out */
909                 if (!*cp)
910                         goto noshebang;
911                 /* replace newline by NUL */
912                 *cp = '\0';
913
914                 /* restore start of shebang position (buf+0 or buf+3) */
915                 cp = buf + n;
916                 /* bail out if no shebang magic found */
917                 if (cp[0] == '#' && cp[1] == '!')
918                         cp += 2;
919 #ifdef __OS2__
920                 else if (!strncmp(cp, Textproc, 7) &&
921                     (cp[7] == ' ' || cp[7] == '\t'))
922                         cp += 8;
923 #endif
924                 else
925                         goto noshebang;
926                 /* skip whitespace before shell name */
927                 while (*cp == ' ' || *cp == '\t')
928                         ++cp;
929                 /* just whitespace on the line? */
930                 if (*cp == '\0')
931                         goto noshebang;
932                 /* no, we actually found an interpreter name */
933                 sh = (char *)cp;
934                 /* look for end of shell/interpreter name */
935                 while (*cp != ' ' && *cp != '\t' && *cp != '\0')
936                         ++cp;
937                 /* any arguments? */
938                 if (*cp) {
939                         *cp++ = '\0';
940                         /* skip spaces before arguments */
941                         while (*cp == ' ' || *cp == '\t')
942                                 ++cp;
943                         /* pass it all in ONE argument (historic reasons) */
944                         if (*cp)
945                                 *tp->args-- = (char *)cp;
946                 }
947                 goto nomagic;
948  noshebang:
949                 m = buf[0] << 8 | buf[1];
950                 if (m == 0x7F45 && buf[2] == 'L' && buf[3] == 'F')
951                         errorf("%s: not executable: %d-bit ELF file", tp->str,
952                             32 * buf[4]);
953                 if ((m == /* OMAGIC */ 0407) ||
954                     (m == /* NMAGIC */ 0410) ||
955                     (m == /* ZMAGIC */ 0413) ||
956                     (m == /* QMAGIC */ 0314) ||
957                     (m == /* ECOFF_I386 */ 0x4C01) ||
958                     (m == /* ECOFF_M68K */ 0x0150 || m == 0x5001) ||
959                     (m == /* ECOFF_SH */   0x0500 || m == 0x0005) ||
960                     (m == /* bzip */ 0x425A) || (m == /* "MZ" */ 0x4D5A) ||
961                     (m == /* "NE" */ 0x4E45) || (m == /* "LX" */ 0x4C58) ||
962                     (m == /* ksh93 */ 0x0B13) || (m == /* LZIP */ 0x4C5A) ||
963                     (m == /* xz */ 0xFD37 && buf[2] == 'z' && buf[3] == 'X' &&
964                     buf[4] == 'Z') || (m == /* 7zip */ 0x377A) ||
965                     (m == /* gzip */ 0x1F8B) || (m == /* .Z */ 0x1F9D))
966                         errorf("%s: not executable: magic %04X", tp->str, m);
967  nomagic:
968                 ;
969         }
970 #endif
971         args.ro = tp->args;
972         *args.ro = sh;
973
974         cap.ro = ap;
975         execve(args.rw[0], args.rw, cap.rw);
976
977         /* report both the programme that was run and the bogus interpreter */
978         errorf(Tf_sD_sD_s, tp->str, sh, cstrerror(errno));
979 }
980
981 int
982 shcomexec(const char **wp)
983 {
984         struct tbl *tp;
985
986         tp = ktsearch(&builtins, *wp, hash(*wp));
987         return (call_builtin(tp, wp, "shcomexec", false));
988 }
989
990 /*
991  * Search function tables for a function. If create set, a table entry
992  * is created if none is found.
993  */
994 struct tbl *
995 findfunc(const char *name, uint32_t h, bool create)
996 {
997         struct block *l;
998         struct tbl *tp = NULL;
999
1000         for (l = e->loc; l; l = l->next) {
1001                 tp = ktsearch(&l->funs, name, h);
1002                 if (tp)
1003                         break;
1004                 if (!l->next && create) {
1005                         tp = ktenter(&l->funs, name, h);
1006                         tp->flag = DEFINED;
1007                         tp->type = CFUNC;
1008                         tp->val.t = NULL;
1009                         break;
1010                 }
1011         }
1012         return (tp);
1013 }
1014
1015 /*
1016  * define function. Returns 1 if function is being undefined (t == 0) and
1017  * function did not exist, returns 0 otherwise.
1018  */
1019 int
1020 define(const char *name, struct op *t)
1021 {
1022         uint32_t nhash;
1023         struct tbl *tp;
1024         bool was_set = false;
1025
1026         nhash = hash(name);
1027
1028         while (/* CONSTCOND */ 1) {
1029                 tp = findfunc(name, nhash, true);
1030
1031                 if (tp->flag & ISSET)
1032                         was_set = true;
1033                 /*
1034                  * If this function is currently being executed, we zap
1035                  * this table entry so findfunc() won't see it
1036                  */
1037                 if (tp->flag & FINUSE) {
1038                         tp->name[0] = '\0';
1039                         /* ensure it won't be found */
1040                         tp->flag &= ~DEFINED;
1041                         tp->flag |= FDELETE;
1042                 } else
1043                         break;
1044         }
1045
1046         if (tp->flag & ALLOC) {
1047                 tp->flag &= ~(ISSET|ALLOC|FKSH);
1048                 tfree(tp->val.t, tp->areap);
1049         }
1050
1051         if (t == NULL) {
1052                 /* undefine */
1053                 ktdelete(tp);
1054                 return (was_set ? 0 : 1);
1055         }
1056
1057         tp->val.t = tcopy(t->left, tp->areap);
1058         tp->flag |= (ISSET|ALLOC);
1059         if (t->u.ksh_func)
1060                 tp->flag |= FKSH;
1061
1062         return (0);
1063 }
1064
1065 /*
1066  * add builtin
1067  */
1068 const char *
1069 builtin(const char *name, int (*func) (const char **))
1070 {
1071         struct tbl *tp;
1072         uint32_t flag = DEFINED;
1073
1074         /* see if any flags should be set for this builtin */
1075  flags_loop:
1076         switch (*name) {
1077         case '=':
1078                 /* command does variable assignment */
1079                 flag |= KEEPASN;
1080                 break;
1081         case '*':
1082                 /* POSIX special builtin */
1083                 flag |= SPEC_BI;
1084                 break;
1085         case '~':
1086                 /* external utility overrides built-in utility, always */
1087                 flag |= LOWER_BI;
1088                 /* FALLTHROUGH */
1089         case '!':
1090                 /* external utility overrides built-in utility, with flags */
1091                 flag |= LOW_BI;
1092                 break;
1093         default:
1094                 goto flags_seen;
1095         }
1096         ++name;
1097         goto flags_loop;
1098  flags_seen:
1099
1100         /* enter into the builtins hash table */
1101         tp = ktenter(&builtins, name, hash(name));
1102         tp->flag = flag;
1103         tp->type = CSHELL;
1104         tp->val.f = func;
1105
1106         /* return name, for direct builtin call check in main.c */
1107         return (name);
1108 }
1109
1110 /*
1111  * find command
1112  * either function, hashed command, or built-in (in that order)
1113  */
1114 struct tbl *
1115 findcom(const char *name, int flags)
1116 {
1117         static struct tbl temp;
1118         uint32_t h = hash(name);
1119         struct tbl *tp = NULL, *tbi;
1120         /* insert if not found */
1121         unsigned char insert = Flag(FTRACKALL);
1122         /* for function autoloading */
1123         char *fpath;
1124         union mksh_cchack npath;
1125
1126         if (mksh_vdirsep(name)) {
1127                 insert = 0;
1128                 /* prevent FPATH search below */
1129                 flags &= ~FC_FUNC;
1130                 goto Search;
1131         }
1132         tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
1133         /*
1134          * POSIX says special builtins first, then functions, then
1135          * regular builtins, then search path...
1136          */
1137         if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
1138                 tp = tbi;
1139         if (!tp && (flags & FC_FUNC)) {
1140                 tp = findfunc(name, h, false);
1141                 if (tp && !(tp->flag & ISSET)) {
1142                         if ((fpath = str_val(global(TFPATH))) == null) {
1143                                 tp->u.fpath = NULL;
1144                                 tp->u2.errnov = ENOENT;
1145                         } else
1146                                 tp->u.fpath = search_path(name, fpath, R_OK,
1147                                     &tp->u2.errnov);
1148                 }
1149         }
1150         if (!tp && (flags & FC_NORMBI) && tbi)
1151                 tp = tbi;
1152         if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
1153                 tp = ktsearch(&taliases, name, h);
1154                 if (tp && (tp->flag & ISSET) &&
1155                     ksh_access(tp->val.s, X_OK) != 0) {
1156                         if (tp->flag & ALLOC) {
1157                                 tp->flag &= ~ALLOC;
1158                                 afree(tp->val.s, APERM);
1159                         }
1160                         tp->flag &= ~ISSET;
1161                 }
1162         }
1163
1164  Search:
1165         if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) &&
1166             (flags & FC_PATH)) {
1167                 if (!tp) {
1168                         if (insert && !(flags & FC_DEFPATH)) {
1169                                 tp = ktenter(&taliases, name, h);
1170                                 tp->type = CTALIAS;
1171                         } else {
1172                                 tp = &temp;
1173                                 tp->type = CEXEC;
1174                         }
1175                         /* make ~ISSET */
1176                         tp->flag = DEFINED;
1177                 }
1178                 npath.ro = search_path(name,
1179                     (flags & FC_DEFPATH) ? def_path : path,
1180                     X_OK, &tp->u2.errnov);
1181                 if (npath.ro) {
1182                         strdupx(tp->val.s, npath.ro, APERM);
1183                         if (npath.ro != name)
1184                                 afree(npath.rw, ATEMP);
1185                         tp->flag |= ISSET|ALLOC;
1186                 } else if ((flags & FC_FUNC) &&
1187                     (fpath = str_val(global(TFPATH))) != null &&
1188                     (npath.ro = search_path(name, fpath, R_OK,
1189                     &tp->u2.errnov)) != NULL) {
1190                         /*
1191                          * An undocumented feature of AT&T ksh is that
1192                          * it searches FPATH if a command is not found,
1193                          * even if the command hasn't been set up as an
1194                          * autoloaded function (ie, no typeset -uf).
1195                          */
1196                         tp = &temp;
1197                         tp->type = CFUNC;
1198                         /* make ~ISSET */
1199                         tp->flag = DEFINED;
1200                         tp->u.fpath = npath.ro;
1201                 }
1202         }
1203         return (tp);
1204 }
1205
1206 /*
1207  * flush executable commands with relative paths
1208  * (just relative or all?)
1209  */
1210 void
1211 flushcom(bool all)
1212 {
1213         struct tbl *tp;
1214         struct tstate ts;
1215
1216         for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
1217                 if ((tp->flag&ISSET) && (all || !mksh_abspath(tp->val.s))) {
1218                         if (tp->flag&ALLOC) {
1219                                 tp->flag &= ~(ALLOC|ISSET);
1220                                 afree(tp->val.s, APERM);
1221                         }
1222                         tp->flag &= ~ISSET;
1223                 }
1224 }
1225
1226 /* check if path is something we want to find */
1227 int
1228 search_access(const char *fn, int mode)
1229 {
1230         struct stat sb;
1231
1232         if (stat(fn, &sb) < 0)
1233                 /* file does not exist */
1234                 return (ENOENT);
1235         /* LINTED use of access */
1236         if (access(fn, mode) < 0) {
1237                 /* file exists, but we can't access it */
1238                 int eno;
1239
1240                 eno = errno;
1241                 return (eno ? eno : EACCES);
1242         }
1243 #ifdef __OS2__
1244         /* treat all files as executable on OS/2 */
1245         sb.st_mode &= S_IXUSR | S_IXGRP | S_IXOTH;
1246 #endif
1247         if (mode == X_OK && (!S_ISREG(sb.st_mode) ||
1248             !(sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
1249                 /* access(2) may say root can execute everything */
1250                 return (S_ISDIR(sb.st_mode) ? EISDIR : EACCES);
1251         return (0);
1252 }
1253
1254 /*
1255  * search for command with PATH
1256  */
1257 const char *
1258 search_path(const char *name, const char *lpath,
1259     /* R_OK or X_OK */
1260     int mode,
1261     /* set if candidate found, but not suitable */
1262     int *errnop)
1263 {
1264         const char *sp, *p;
1265         char *xp;
1266         XString xs;
1267         size_t namelen;
1268         int ec = 0, ev;
1269
1270         if (mksh_vdirsep(name)) {
1271                 if ((ec = search_access(name, mode)) == 0) {
1272  search_path_ok:
1273                         if (errnop)
1274                                 *errnop = 0;
1275                         return (name);
1276                 }
1277                 goto search_path_err;
1278         }
1279
1280         namelen = strlen(name) + 1;
1281         Xinit(xs, xp, 128, ATEMP);
1282
1283         sp = lpath;
1284         while (sp != NULL) {
1285                 xp = Xstring(xs, xp);
1286                 if (!(p = cstrchr(sp, MKSH_PATHSEPC)))
1287                         p = sp + strlen(sp);
1288                 if (p != sp) {
1289                         XcheckN(xs, xp, p - sp);
1290                         memcpy(xp, sp, p - sp);
1291                         xp += p - sp;
1292                         *xp++ = '/';
1293                 }
1294                 sp = p;
1295                 XcheckN(xs, xp, namelen);
1296                 memcpy(xp, name, namelen);
1297                 if ((ev = search_access(Xstring(xs, xp), mode)) == 0) {
1298                         name = Xclose(xs, xp + namelen);
1299                         goto search_path_ok;
1300                 }
1301                 /* accumulate non-ENOENT errors only */
1302                 if (ev != ENOENT && ec == 0)
1303                         ec = ev;
1304                 if (*sp++ == '\0')
1305                         sp = NULL;
1306         }
1307         Xfree(xs, xp);
1308  search_path_err:
1309         if (errnop)
1310                 *errnop = ec ? ec : ENOENT;
1311         return (NULL);
1312 }
1313
1314 static int
1315 call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec)
1316 {
1317         int rv;
1318
1319         if (!tp)
1320                 internal_errorf(Tf_sD_s, where, wp[0]);
1321         builtin_argv0 = wp[0];
1322         builtin_spec = tobool(!resetspec &&
1323             /*XXX odd use of KEEPASN */
1324             ((tp->flag & SPEC_BI) || (Flag(FPOSIX) && (tp->flag & KEEPASN))));
1325         shf_reopen(1, SHF_WR, shl_stdout);
1326         shl_stdout_ok = true;
1327         ksh_getopt_reset(&builtin_opt, GF_ERROR);
1328         rv = (*tp->val.f)(wp);
1329         shf_flush(shl_stdout);
1330         shl_stdout_ok = false;
1331         builtin_argv0 = NULL;
1332         builtin_spec = false;
1333         return (rv);
1334 }
1335
1336 /*
1337  * set up redirection, saving old fds in e->savefd
1338  */
1339 static int
1340 iosetup(struct ioword *iop, struct tbl *tp)
1341 {
1342         int u = -1;
1343         char *cp = iop->ioname;
1344         int iotype = iop->ioflag & IOTYPE;
1345         bool do_open = true, do_close = false, do_fstat = false;
1346         int flags = 0;
1347         struct ioword iotmp;
1348         struct stat statb;
1349
1350         if (iotype != IOHERE)
1351                 cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
1352
1353         /* Used for tracing and error messages to print expanded cp */
1354         iotmp = *iop;
1355         iotmp.ioname = (iotype == IOHERE) ? NULL : cp;
1356         iotmp.ioflag |= IONAMEXP;
1357
1358         if (Flag(FXTRACE)) {
1359                 change_xtrace(2, false);
1360                 fptreef(shl_xtrace, 0, Tft_R, &iotmp);
1361                 change_xtrace(1, false);
1362         }
1363
1364         switch (iotype) {
1365         case IOREAD:
1366                 flags = O_RDONLY;
1367                 break;
1368
1369         case IOCAT:
1370                 flags = O_WRONLY | O_APPEND | O_CREAT;
1371                 break;
1372
1373         case IOWRITE:
1374                 if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB)) {
1375                         /* >file under set -C */
1376                         if (stat(cp, &statb)) {
1377                                 /* nonexistent file */
1378                                 flags = O_WRONLY | O_CREAT | O_EXCL;
1379                         } else if (S_ISREG(statb.st_mode)) {
1380                                 /* regular file, refuse clobbering */
1381                                 goto clobber_refused;
1382                         } else {
1383                                 /*
1384                                  * allow redirections to things
1385                                  * like /dev/null without error
1386                                  */
1387                                 flags = O_WRONLY;
1388                                 /* but check again after opening */
1389                                 do_fstat = true;
1390                         }
1391                 } else {
1392                         /* >|file or set +C */
1393                         flags = O_WRONLY | O_CREAT | O_TRUNC;
1394                 }
1395                 break;
1396
1397         case IORDWR:
1398                 flags = O_RDWR | O_CREAT;
1399                 break;
1400
1401         case IOHERE:
1402                 do_open = false;
1403                 /* herein() returns -2 if error has been printed */
1404                 u = herein(iop, NULL);
1405                 /* cp may have wrong name */
1406                 break;
1407
1408         case IODUP: {
1409                 const char *emsg;
1410
1411                 do_open = false;
1412                 if (ksh_isdash(cp)) {
1413                         /* prevent error return below */
1414                         u = 1009;
1415                         do_close = true;
1416                 } else if ((u = check_fd(cp,
1417                     X_OK | ((iop->ioflag & IORDUP) ? R_OK : W_OK),
1418                     &emsg)) < 0) {
1419                         char *sp;
1420
1421                         warningf(true, Tf_sD_s,
1422                             (sp = snptreef(NULL, 32, Tft_R, &iotmp)), emsg);
1423                         afree(sp, ATEMP);
1424                         return (-1);
1425                 }
1426                 if (u == (int)iop->unit)
1427                         /* "dup from" == "dup to" */
1428                         return (0);
1429                 break;
1430             }
1431         }
1432
1433         if (do_open) {
1434                 if (Flag(FRESTRICTED) && (flags & O_CREAT)) {
1435                         warningf(true, Tf_sD_s, cp, "restricted");
1436                         return (-1);
1437                 }
1438                 u = binopen3(cp, flags, 0666);
1439                 if (do_fstat && u >= 0) {
1440                         /* prevent race conditions */
1441                         if (fstat(u, &statb) || S_ISREG(statb.st_mode)) {
1442                                 close(u);
1443  clobber_refused:
1444                                 u = -1;
1445                                 errno = EEXIST;
1446                         }
1447                 }
1448         }
1449         if (u < 0) {
1450                 /* herein() may already have printed message */
1451                 if (u == -1) {
1452                         u = errno;
1453                         warningf(true, Tf_cant,
1454                             iotype == IODUP ? "dup" :
1455                             (iotype == IOREAD || iotype == IOHERE) ?
1456                             Topen : Tcreate, cp, cstrerror(u));
1457                 }
1458                 return (-1);
1459         }
1460         /* Do not save if it has already been redirected (i.e. "cat >x >y"). */
1461         if (e->savefd[iop->unit] == 0) {
1462                 /* If these are the same, it means unit was previously closed */
1463                 if (u == (int)iop->unit)
1464                         e->savefd[iop->unit] = -1;
1465                 else
1466                         /*
1467                          * c_exec() assumes e->savefd[fd] set for any
1468                          * redirections. Ask savefd() not to close iop->unit;
1469                          * this allows error messages to be seen if iop->unit
1470                          * is 2; also means we can't lose the fd (eg, both
1471                          * dup2 below and dup2 in restfd() failing).
1472                          */
1473                         e->savefd[iop->unit] = savefd(iop->unit);
1474         }
1475
1476         if (do_close)
1477                 close(iop->unit);
1478         else if (u != (int)iop->unit) {
1479                 if (ksh_dup2(u, iop->unit, true) < 0) {
1480                         int eno;
1481                         char *sp;
1482
1483                         eno = errno;
1484                         warningf(true, Tf_s_sD_s, Tredirection_dup,
1485                             (sp = snptreef(NULL, 32, Tft_R, &iotmp)),
1486                             cstrerror(eno));
1487                         afree(sp, ATEMP);
1488                         if (iotype != IODUP)
1489                                 close(u);
1490                         return (-1);
1491                 }
1492                 if (iotype != IODUP)
1493                         close(u);
1494                 /*
1495                  * Touching any co-process fd in an empty exec
1496                  * causes the shell to close its copies
1497                  */
1498                 else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
1499                         if (iop->ioflag & IORDUP)
1500                                 /* possible exec <&p */
1501                                 coproc_read_close(u);
1502                         else
1503                                 /* possible exec >&p */
1504                                 coproc_write_close(u);
1505                 }
1506         }
1507         if (u == 2)
1508                 /* Clear any write errors */
1509                 shf_reopen(2, SHF_WR, shl_out);
1510         return (0);
1511 }
1512
1513 /*
1514  * Process here documents by providing the content, either as
1515  * result (globally allocated) string or in a temp file; if
1516  * unquoted, the string is expanded first.
1517  */
1518 static int
1519 hereinval(struct ioword *iop, int sub, char **resbuf, struct shf *shf)
1520 {
1521         const char * volatile ccp = iop->heredoc;
1522         struct source *s, *osource;
1523
1524         osource = source;
1525         newenv(E_ERRH);
1526         if (kshsetjmp(e->jbuf)) {
1527                 source = osource;
1528                 quitenv(shf);
1529                 /* special to iosetup(): don't print error */
1530                 return (-2);
1531         }
1532         if (iop->ioflag & IOHERESTR) {
1533                 ccp = evalstr(iop->delim, DOHERESTR | DOSCALAR | DOHEREDOC);
1534         } else if (sub) {
1535                 /* do substitutions on the content of heredoc */
1536                 s = pushs(SSTRING, ATEMP);
1537                 s->start = s->str = ccp;
1538                 source = s;
1539                 if (yylex(sub) != LWORD)
1540                         internal_errorf("herein: yylex");
1541                 source = osource;
1542                 ccp = evalstr(yylval.cp, DOSCALAR | DOHEREDOC);
1543         }
1544
1545         if (resbuf == NULL)
1546                 shf_puts(ccp, shf);
1547         else
1548                 strdupx(*resbuf, ccp, APERM);
1549
1550         quitenv(NULL);
1551         return (0);
1552 }
1553
1554 int
1555 herein(struct ioword *iop, char **resbuf)
1556 {
1557         int fd = -1;
1558         struct shf *shf;
1559         struct temp *h;
1560         int i;
1561
1562         /* lexer substitution flags */
1563         i = (iop->ioflag & IOEVAL) ? (ONEWORD | HEREDOC) : 0;
1564
1565         /* skip all the fd setup if we just want the value */
1566         if (resbuf != NULL)
1567                 return (hereinval(iop, i, resbuf, NULL));
1568
1569         /*
1570          * Create temp file to hold content (done before newenv
1571          * so temp doesn't get removed too soon).
1572          */
1573         h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
1574         if (!(shf = h->shf) || (fd = binopen3(h->tffn, O_RDONLY, 0)) < 0) {
1575                 i = errno;
1576                 warningf(true, Tf_temp,
1577                     !shf ? Tcreate : Topen, h->tffn, cstrerror(i));
1578                 if (shf)
1579                         shf_close(shf);
1580                 /* special to iosetup(): don't print error */
1581                 return (-2);
1582         }
1583
1584         if (hereinval(iop, i, NULL, shf) == -2) {
1585                 close(fd);
1586                 /* special to iosetup(): don't print error */
1587                 return (-2);
1588         }
1589
1590         if (shf_close(shf) == -1) {
1591                 i = errno;
1592                 close(fd);
1593                 warningf(true, Tf_temp,
1594                     Twrite, h->tffn, cstrerror(i));
1595                 /* special to iosetup(): don't print error */
1596                 return (-2);
1597         }
1598
1599         return (fd);
1600 }
1601
1602 /*
1603  *      ksh special - the select command processing section
1604  *      print the args in column form - assuming that we can
1605  */
1606 static const char *
1607 do_selectargs(const char **ap, bool print_menu)
1608 {
1609         static const char *read_args[] = {
1610                 Tread, "-r", "REPLY", NULL
1611         };
1612         char *s;
1613         int i, argct;
1614
1615         for (argct = 0; ap[argct]; argct++)
1616                 ;
1617         while (/* CONSTCOND */ 1) {
1618                 /*-
1619                  * Menu is printed if
1620                  *      - this is the first time around the select loop
1621                  *      - the user enters a blank line
1622                  *      - the REPLY parameter is empty
1623                  */
1624                 if (print_menu || !*str_val(global("REPLY")))
1625                         pr_menu(ap);
1626                 shellf(Tf_s, str_val(global("PS3")));
1627                 if (call_builtin(findcom(Tread, FC_BI), read_args, Tselect,
1628                     false))
1629                         return (NULL);
1630                 if (*(s = str_val(global("REPLY"))))
1631                         return ((getn(s, &i) && i >= 1 && i <= argct) ?
1632                             ap[i - 1] : null);
1633                 print_menu = true;
1634         }
1635 }
1636
1637 struct select_menu_info {
1638         const char * const *args;
1639         int num_width;
1640 };
1641
1642 /* format a single select menu item */
1643 static void
1644 select_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1645 {
1646         const struct select_menu_info *smi =
1647             (const struct select_menu_info *)arg;
1648
1649         shf_snprintf(buf, buflen, "%*u) %s",
1650             smi->num_width, i + 1, smi->args[i]);
1651 }
1652
1653 /*
1654  *      print a select style menu
1655  */
1656 void
1657 pr_menu(const char * const *ap)
1658 {
1659         struct select_menu_info smi;
1660         const char * const *pp;
1661         size_t acols = 0, aocts = 0, i;
1662         unsigned int n;
1663         struct columnise_opts co;
1664
1665         /*
1666          * width/column calculations were done once and saved, but this
1667          * means select can't be used recursively so we re-calculate
1668          * each time (could save in a structure that is returned, but
1669          * it's probably not worth the bother)
1670          */
1671
1672         /*
1673          * get dimensions of the list
1674          */
1675         for (n = 0, pp = ap; *pp; n++, pp++) {
1676                 i = strlen(*pp);
1677                 if (i > aocts)
1678                         aocts = i;
1679                 i = utf_mbswidth(*pp);
1680                 if (i > acols)
1681                         acols = i;
1682         }
1683
1684         /*
1685          * we will print an index of the form "%d) " in front of
1686          * each entry, so get the maximum width of this
1687          */
1688         for (i = n, smi.num_width = 1; i >= 10; i /= 10)
1689                 smi.num_width++;
1690
1691         smi.args = ap;
1692         co.shf = shl_out;
1693         co.linesep = '\n';
1694         co.prefcol = co.do_last = true;
1695         print_columns(&co, n, select_fmt_entry, (void *)&smi,
1696             smi.num_width + 2 + aocts, smi.num_width + 2 + acols);
1697 }
1698
1699 static void
1700 plain_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg)
1701 {
1702         strlcpy(buf, ((const char * const *)arg)[i], buflen);
1703 }
1704
1705 void
1706 pr_list(struct columnise_opts *cop, char * const *ap)
1707 {
1708         size_t acols = 0, aocts = 0, i;
1709         unsigned int n;
1710         char * const *pp;
1711
1712         for (n = 0, pp = ap; *pp; n++, pp++) {
1713                 i = strlen(*pp);
1714                 if (i > aocts)
1715                         aocts = i;
1716                 i = utf_mbswidth(*pp);
1717                 if (i > acols)
1718                         acols = i;
1719         }
1720
1721         print_columns(cop, n, plain_fmt_entry, (const void *)ap,
1722             aocts, acols);
1723 }
1724
1725 /*
1726  *      [[ ... ]] evaluation routines
1727  */
1728
1729 /*
1730  * Test if the current token is a whatever. Accepts the current token if
1731  * it is. Returns 0 if it is not, non-zero if it is (in the case of
1732  * TM_UNOP and TM_BINOP, the returned value is a Test_op).
1733  */
1734 static Test_op
1735 dbteste_isa(Test_env *te, Test_meta meta)
1736 {
1737         Test_op ret = TO_NONOP;
1738         bool uqword;
1739         const char *p;
1740
1741         if (!*te->pos.wp)
1742                 return (meta == TM_END ? TO_NONNULL : TO_NONOP);
1743
1744         /* unquoted word? */
1745         for (p = *te->pos.wp; *p == CHAR; p += 2)
1746                 ;
1747         uqword = *p == EOS;
1748
1749         if (meta == TM_UNOP || meta == TM_BINOP) {
1750                 if (uqword) {
1751                         /* longer than the longest operator */
1752                         char buf[8];
1753                         char *q = buf;
1754
1755                         p = *te->pos.wp;
1756                         while (*p++ == CHAR &&
1757                             (size_t)(q - buf) < sizeof(buf) - 1)
1758                                 *q++ = *p++;
1759                         *q = '\0';
1760                         ret = test_isop(meta, buf);
1761                 }
1762         } else if (meta == TM_END)
1763                 ret = TO_NONOP;
1764         else
1765                 ret = (uqword && !strcmp(*te->pos.wp,
1766                     dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP;
1767
1768         /* Accept the token? */
1769         if (ret != TO_NONOP)
1770                 te->pos.wp++;
1771
1772         return (ret);
1773 }
1774
1775 static const char *
1776 dbteste_getopnd(Test_env *te, Test_op op, bool do_eval)
1777 {
1778         const char *s = *te->pos.wp;
1779         int flags = DOTILDE | DOSCALAR;
1780
1781         if (!s)
1782                 return (NULL);
1783
1784         te->pos.wp++;
1785
1786         if (!do_eval)
1787                 return (null);
1788
1789         if (op == TO_STEQL || op == TO_STNEQ)
1790                 flags |= DOPAT;
1791
1792         return (evalstr(s, flags));
1793 }
1794
1795 static void
1796 dbteste_error(Test_env *te, int offset, const char *msg)
1797 {
1798         te->flags |= TEF_ERROR;
1799         internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
1800 }