OSDN Git Service

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