OSDN Git Service

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