Merge from vendor branch ATHEROS:
[dragonfly.git] / bin / sh / eval.c
1 /*-
2  * Copyright (c) 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)eval.c   8.9 (Berkeley) 6/8/95
37  * $FreeBSD: src/bin/sh/eval.c,v 1.27.2.5 2002/08/27 01:36:28 tjr Exp $
38  * $DragonFly: src/bin/sh/eval.c,v 1.7 2006/06/19 12:05:43 corecode Exp $
39  */
40
41 #include <sys/wait.h> /* For WIFSIGNALED(status) */
42
43 #include <errno.h>
44 #include <paths.h>
45 #include <signal.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48
49 /*
50  * Evaluate a command.
51  */
52
53 #include "shell.h"
54 #include "nodes.h"
55 #include "syntax.h"
56 #include "expand.h"
57 #include "parser.h"
58 #include "jobs.h"
59 #include "eval.h"
60 #include "builtins.h"
61 #include "options.h"
62 #include "exec.h"
63 #include "redir.h"
64 #include "input.h"
65 #include "output.h"
66 #include "trap.h"
67 #include "var.h"
68 #include "memalloc.h"
69 #include "error.h"
70 #include "show.h"
71 #include "mystring.h"
72 #ifndef NO_HISTORY
73 #include "myhistedit.h"
74 #endif
75
76
77 /* flags in argument to evaltree */
78 #define EV_EXIT 01              /* exit after evaluating tree */
79 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
80 #define EV_BACKCMD 04           /* command executing within back quotes */
81
82 MKINIT int evalskip;            /* set if we are skipping commands */
83 STATIC int skipcount;           /* number of levels to skip */
84 MKINIT int loopnest;            /* current loop nesting level */
85 int funcnest;                   /* depth of function calls */
86
87
88 const char *commandname;
89 struct strlist *cmdenviron;
90 int exitstatus;                 /* exit status of last command */
91 int oexitstatus;                /* saved exit status */
92
93
94 STATIC void evalloop(union node *);
95 STATIC void evalfor(union node *);
96 STATIC void evalcase(union node *, int);
97 STATIC void evalsubshell(union node *, int);
98 STATIC void expredir(union node *);
99 STATIC void evalpipe(union node *);
100 STATIC void evalcommand(union node *, int, struct backcmd *);
101 STATIC void prehash(union node *);
102
103
104 /*
105  * Called to reset things after an exception.
106  */
107
108 #ifdef mkinit
109 INCLUDE "eval.h"
110
111 RESET {
112         evalskip = 0;
113         loopnest = 0;
114         funcnest = 0;
115 }
116
117 SHELLPROC {
118         exitstatus = 0;
119 }
120 #endif
121
122
123
124 /*
125  * The eval command.
126  */
127
128 int
129 evalcmd(int argc, char **argv)
130 {
131         char *p;
132         char *concat;
133         char **ap;
134
135         if (argc > 1) {
136                 p = argv[1];
137                 if (argc > 2) {
138                         STARTSTACKSTR(concat);
139                         ap = argv + 2;
140                         for (;;) {
141                                 while (*p)
142                                         STPUTC(*p++, concat);
143                                 if ((p = *ap++) == NULL)
144                                         break;
145                                 STPUTC(' ', concat);
146                         }
147                         STPUTC('\0', concat);
148                         p = grabstackstr(concat);
149                 }
150                 evalstring(p);
151         }
152         return exitstatus;
153 }
154
155
156 /*
157  * Execute a command or commands contained in a string.
158  */
159
160 void
161 evalstring(char *s)
162 {
163         union node *n;
164         struct stackmark smark;
165
166         setstackmark(&smark);
167         setinputstring(s, 1);
168         while ((n = parsecmd(0)) != NEOF) {
169                 evaltree(n, 0);
170                 popstackmark(&smark);
171         }
172         popfile();
173         popstackmark(&smark);
174 }
175
176
177
178 /*
179  * Evaluate a parse tree.  The value is left in the global variable
180  * exitstatus.
181  */
182
183 void
184 evaltree(union node *n, int flags)
185 {
186         if (n == NULL) {
187                 TRACE(("evaltree(NULL) called\n"));
188                 exitstatus = 0;
189                 goto out;
190         }
191 #ifndef NO_HISTORY
192         displayhist = 1;        /* show history substitutions done with fc */
193 #endif
194         TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
195         switch (n->type) {
196         case NSEMI:
197                 evaltree(n->nbinary.ch1, 0);
198                 if (evalskip)
199                         goto out;
200                 evaltree(n->nbinary.ch2, flags);
201                 break;
202         case NAND:
203                 evaltree(n->nbinary.ch1, EV_TESTED);
204                 if (evalskip || exitstatus != 0) {
205                         goto out;
206                 }
207                 evaltree(n->nbinary.ch2, flags);
208                 break;
209         case NOR:
210                 evaltree(n->nbinary.ch1, EV_TESTED);
211                 if (evalskip || exitstatus == 0)
212                         goto out;
213                 evaltree(n->nbinary.ch2, flags);
214                 break;
215         case NREDIR:
216                 expredir(n->nredir.redirect);
217                 redirect(n->nredir.redirect, REDIR_PUSH);
218                 evaltree(n->nredir.n, flags);
219                 popredir();
220                 break;
221         case NSUBSHELL:
222                 evalsubshell(n, flags);
223                 break;
224         case NBACKGND:
225                 evalsubshell(n, flags);
226                 break;
227         case NIF: {
228                 evaltree(n->nif.test, EV_TESTED);
229                 if (evalskip)
230                         goto out;
231                 if (exitstatus == 0)
232                         evaltree(n->nif.ifpart, flags);
233                 else if (n->nif.elsepart)
234                         evaltree(n->nif.elsepart, flags);
235                 else
236                         exitstatus = 0;
237                 break;
238         }
239         case NWHILE:
240         case NUNTIL:
241                 evalloop(n);
242                 break;
243         case NFOR:
244                 evalfor(n);
245                 break;
246         case NCASE:
247                 evalcase(n, flags);
248                 break;
249         case NDEFUN:
250                 defun(n->narg.text, n->narg.next);
251                 exitstatus = 0;
252                 break;
253         case NNOT:
254                 evaltree(n->nnot.com, EV_TESTED);
255                 exitstatus = !exitstatus;
256                 break;
257
258         case NPIPE:
259                 evalpipe(n);
260                 break;
261         case NCMD:
262                 evalcommand(n, flags, (struct backcmd *)NULL);
263                 break;
264         default:
265                 out1fmt("Node type = %d\n", n->type);
266                 flushout(&output);
267                 break;
268         }
269 out:
270         if (pendingsigs)
271                 dotrap();
272         if ((flags & EV_EXIT) || (eflag && exitstatus 
273             && !(flags & EV_TESTED) && (n->type == NCMD ||
274             n->type == NSUBSHELL)))
275                 exitshell(exitstatus);
276 }
277
278
279 STATIC void
280 evalloop(union node *n)
281 {
282         int status;
283
284         loopnest++;
285         status = 0;
286         for (;;) {
287                 evaltree(n->nbinary.ch1, EV_TESTED);
288                 if (evalskip) {
289 skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
290                                 evalskip = 0;
291                                 continue;
292                         }
293                         if (evalskip == SKIPBREAK && --skipcount <= 0)
294                                 evalskip = 0;
295                         break;
296                 }
297                 if (n->type == NWHILE) {
298                         if (exitstatus != 0)
299                                 break;
300                 } else {
301                         if (exitstatus == 0)
302                                 break;
303                 }
304                 evaltree(n->nbinary.ch2, 0);
305                 status = exitstatus;
306                 if (evalskip)
307                         goto skipping;
308         }
309         loopnest--;
310         exitstatus = status;
311 }
312
313
314
315 STATIC void
316 evalfor(union node *n)
317 {
318         struct arglist arglist;
319         union node *argp;
320         struct strlist *sp;
321         struct stackmark smark;
322
323         setstackmark(&smark);
324         arglist.lastp = &arglist.list;
325         for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
326                 oexitstatus = exitstatus;
327                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
328                 if (evalskip)
329                         goto out;
330         }
331         *arglist.lastp = NULL;
332
333         exitstatus = 0;
334         loopnest++;
335         for (sp = arglist.list ; sp ; sp = sp->next) {
336                 setvar(n->nfor.var, sp->text, 0);
337                 evaltree(n->nfor.body, 0);
338                 if (evalskip) {
339                         if (evalskip == SKIPCONT && --skipcount <= 0) {
340                                 evalskip = 0;
341                                 continue;
342                         }
343                         if (evalskip == SKIPBREAK && --skipcount <= 0)
344                                 evalskip = 0;
345                         break;
346                 }
347         }
348         loopnest--;
349 out:
350         popstackmark(&smark);
351 }
352
353
354
355 STATIC void
356 evalcase(union node *n, int flags)
357 {
358         union node *cp;
359         union node *patp;
360         struct arglist arglist;
361         struct stackmark smark;
362
363         setstackmark(&smark);
364         arglist.lastp = &arglist.list;
365         oexitstatus = exitstatus;
366         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
367         for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
368                 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
369                         if (casematch(patp, arglist.list->text)) {
370                                 if (evalskip == 0) {
371                                         evaltree(cp->nclist.body, flags);
372                                 }
373                                 goto out;
374                         }
375                 }
376         }
377 out:
378         popstackmark(&smark);
379 }
380
381
382
383 /*
384  * Kick off a subshell to evaluate a tree.
385  */
386
387 STATIC void
388 evalsubshell(union node *n, int flags)
389 {
390         struct job *jp;
391         int backgnd = (n->type == NBACKGND);
392
393         expredir(n->nredir.redirect);
394         jp = makejob(n, 1);
395         if (forkshell(jp, n, backgnd) == 0) {
396                 if (backgnd)
397                         flags &=~ EV_TESTED;
398                 redirect(n->nredir.redirect, 0);
399                 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
400         }
401         if (! backgnd) {
402                 INTOFF;
403                 exitstatus = waitforjob(jp, (int *)NULL);
404                 INTON;
405         }
406 }
407
408
409
410 /*
411  * Compute the names of the files in a redirection list.
412  */
413
414 STATIC void
415 expredir(union node *n)
416 {
417         union node *redir;
418
419         for (redir = n ; redir ; redir = redir->nfile.next) {
420                 struct arglist fn;
421                 fn.lastp = &fn.list;
422                 oexitstatus = exitstatus;
423                 switch (redir->type) {
424                 case NFROM:
425                 case NTO:
426                 case NFROMTO:
427                 case NAPPEND:
428                 case NCLOBBER:
429                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
430                         redir->nfile.expfname = fn.list->text;
431                         break;
432                 case NFROMFD:
433                 case NTOFD:
434                         if (redir->ndup.vname) {
435                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
436                                 fixredir(redir, fn.list->text, 1);
437                         }
438                         break;
439                 }
440         }
441 }
442
443
444
445 /*
446  * Evaluate a pipeline.  All the processes in the pipeline are children
447  * of the process creating the pipeline.  (This differs from some versions
448  * of the shell, which make the last process in a pipeline the parent
449  * of all the rest.)
450  */
451
452 STATIC void
453 evalpipe(union node *n)
454 {
455         struct job *jp;
456         struct nodelist *lp;
457         int pipelen;
458         int prevfd;
459         int pip[2];
460
461         TRACE(("evalpipe(0x%lx) called\n", (long)n));
462         pipelen = 0;
463         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
464                 pipelen++;
465         INTOFF;
466         jp = makejob(n, pipelen);
467         prevfd = -1;
468         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
469                 prehash(lp->n);
470                 pip[1] = -1;
471                 if (lp->next) {
472                         if (pipe(pip) < 0) {
473                                 if (prevfd >= 0)
474                                         close(prevfd);
475                                 error("Pipe call failed: %s", strerror(errno));
476                         }
477                 }
478                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
479                         INTON;
480                         if (prevfd > 0) {
481                                 close(0);
482                                 copyfd(prevfd, 0);
483                                 close(prevfd);
484                         }
485                         if (pip[1] >= 0) {
486                                 if (!(prevfd >= 0 && pip[0] == 0))
487                                         close(pip[0]);
488                                 if (pip[1] != 1) {
489                                         close(1);
490                                         copyfd(pip[1], 1);
491                                         close(pip[1]);
492                                 }
493                         }
494                         evaltree(lp->n, EV_EXIT);
495                 }
496                 if (prevfd >= 0)
497                         close(prevfd);
498                 prevfd = pip[0];
499                 close(pip[1]);
500         }
501         INTON;
502         if (n->npipe.backgnd == 0) {
503                 INTOFF;
504                 exitstatus = waitforjob(jp, (int *)NULL);
505                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
506                 INTON;
507         }
508 }
509
510
511
512 /*
513  * Execute a command inside back quotes.  If it's a builtin command, we
514  * want to save its output in a block obtained from malloc.  Otherwise
515  * we fork off a subprocess and get the output of the command via a pipe.
516  * Should be called with interrupts off.
517  */
518
519 void
520 evalbackcmd(union node *n, struct backcmd *result)
521 {
522         int pip[2];
523         struct job *jp;
524         struct stackmark smark;         /* unnecessary */
525
526         setstackmark(&smark);
527         result->fd = -1;
528         result->buf = NULL;
529         result->nleft = 0;
530         result->jp = NULL;
531         if (n == NULL) {
532                 exitstatus = 0;
533                 goto out;
534         }
535         if (n->type == NCMD) {
536                 exitstatus = oexitstatus;
537                 evalcommand(n, EV_BACKCMD, result);
538         } else {
539                 exitstatus = 0;
540                 if (pipe(pip) < 0)
541                         error("Pipe call failed: %s", strerror(errno));
542                 jp = makejob(n, 1);
543                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
544                         FORCEINTON;
545                         close(pip[0]);
546                         if (pip[1] != 1) {
547                                 close(1);
548                                 copyfd(pip[1], 1);
549                                 close(pip[1]);
550                         }
551                         evaltree(n, EV_EXIT);
552                 }
553                 close(pip[1]);
554                 result->fd = pip[0];
555                 result->jp = jp;
556         }
557 out:
558         popstackmark(&smark);
559         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
560                 result->fd, result->buf, result->nleft, result->jp));
561 }
562
563
564
565 /*
566  * Execute a simple command.
567  */
568
569 STATIC void
570 evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
571 {
572         struct stackmark smark;
573         union node *argp;
574         struct arglist arglist;
575         struct arglist varlist;
576         char **argv;
577         int argc;
578         char **envp;
579         int varflag;
580         struct strlist *sp;
581         int mode;
582         int pip[2];
583         struct cmdentry cmdentry;
584         struct job *jp;
585         struct jmploc jmploc;
586         struct jmploc *volatile savehandler = NULL;
587         const char *volatile savecmdname;
588         volatile struct shparam saveparam;
589         struct localvar *volatile savelocalvars;
590         volatile int e;
591         char *lastarg;
592         int realstatus;
593         int do_clearcmdentry;
594 #if __GNUC__
595         /* Avoid longjmp clobbering */
596         (void) &argv;
597         (void) &argc;
598         (void) &lastarg;
599         (void) &flags;
600         (void) &do_clearcmdentry;
601 #endif
602
603         /* First expand the arguments. */
604         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
605         setstackmark(&smark);
606         arglist.lastp = &arglist.list;
607         varlist.lastp = &varlist.list;
608         varflag = 1;
609         do_clearcmdentry = 0;
610         oexitstatus = exitstatus;
611         exitstatus = 0;
612         for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
613                 char *p = argp->narg.text;
614                 if (varflag && is_name(*p)) {
615                         do {
616                                 p++;
617                         } while (is_in_name(*p));
618                         if (*p == '=') {
619                                 expandarg(argp, &varlist, EXP_VARTILDE);
620                                 continue;
621                         }
622                 }
623                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
624                 varflag = 0;
625         }
626         *arglist.lastp = NULL;
627         *varlist.lastp = NULL;
628         expredir(cmd->ncmd.redirect);
629         argc = 0;
630         for (sp = arglist.list ; sp ; sp = sp->next)
631                 argc++;
632         argv = stalloc(sizeof (char *) * (argc + 1));
633
634         for (sp = arglist.list ; sp ; sp = sp->next) {
635                 TRACE(("evalcommand arg: %s\n", sp->text));
636                 *argv++ = sp->text;
637         }
638         *argv = NULL;
639         lastarg = NULL;
640         if (iflag && funcnest == 0 && argc > 0)
641                 lastarg = argv[-1];
642         argv -= argc;
643
644         /* Print the command if xflag is set. */
645         if (xflag) {
646                 outc('+', &errout);
647                 for (sp = varlist.list ; sp ; sp = sp->next) {
648                         outc(' ', &errout);
649                         out2str(sp->text);
650                 }
651                 for (sp = arglist.list ; sp ; sp = sp->next) {
652                         outc(' ', &errout);
653                         out2str(sp->text);
654                 }
655                 outc('\n', &errout);
656                 flushout(&errout);
657         }
658
659         /* Now locate the command. */
660         if (argc == 0) {
661                 cmdentry.cmdtype = CMDBUILTIN;
662                 cmdentry.u.index = BLTINCMD;
663         } else {
664                 static const char PATH[] = "PATH=";
665                 const char *path = pathval();
666
667                 /*
668                  * Modify the command lookup path, if a PATH= assignment
669                  * is present
670                  */
671                 for (sp = varlist.list ; sp ; sp = sp->next)
672                         if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
673                                 path = sp->text + sizeof(PATH) - 1;
674                                 /* 
675                                  * On `PATH=... command`, we need to make
676                                  * sure that the command isn't using the
677                                  * non-updated hash table of the outer PATH
678                                  * setting and we need to make sure that 
679                                  * the hash table isn't filled with items
680                                  * from the temporary setting.
681                                  *
682                                  * It would be better to forbit using and 
683                                  * updating the table while this command
684                                  * runs, by the command finding mechanism
685                                  * is heavily integrated with hash handling,
686                                  * so we just delete the hash before and after
687                                  * the command runs. Partly deleting like
688                                  * changepatch() does doesn't seem worth the
689                                  * bookinging effort, since most such runs add
690                                  * diretories in front of the new PATH.
691                                  */
692                                 clearcmdentry(0);
693                                 do_clearcmdentry = 1;
694                         }
695
696                 find_command(argv[0], &cmdentry, 1, path);
697                 if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
698                         exitstatus = 127;
699                         flushout(&errout);
700                         return;
701                 }
702                 /* implement the bltin builtin here */
703                 if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
704                         for (;;) {
705                                 argv++;
706                                 if (--argc == 0)
707                                         break;
708                                 if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
709                                         outfmt(&errout, "%s: not found\n", *argv);
710                                         exitstatus = 127;
711                                         flushout(&errout);
712                                         return;
713                                 }
714                                 if (cmdentry.u.index != BLTINCMD)
715                                         break;
716                         }
717                 }
718         }
719
720         /* Fork off a child process if necessary. */
721         if (cmd->ncmd.backgnd
722          || (cmdentry.cmdtype == CMDNORMAL
723             && ((flags & EV_EXIT) == 0 || Tflag))
724          || ((flags & EV_BACKCMD) != 0
725             && (cmdentry.cmdtype != CMDBUILTIN
726                  || cmdentry.u.index == CDCMD
727                  || cmdentry.u.index == DOTCMD
728                  || cmdentry.u.index == EVALCMD))
729          || (cmdentry.cmdtype == CMDBUILTIN &&
730             cmdentry.u.index == COMMANDCMD)) {
731                 jp = makejob(cmd, 1);
732                 mode = cmd->ncmd.backgnd;
733                 if (flags & EV_BACKCMD) {
734                         mode = FORK_NOJOB;
735                         if (pipe(pip) < 0)
736                                 error("Pipe call failed: %s", strerror(errno));
737                 }
738                 if (forkshell(jp, cmd, mode) != 0)
739                         goto parent;    /* at end of routine */
740                 if (flags & EV_BACKCMD) {
741                         FORCEINTON;
742                         close(pip[0]);
743                         if (pip[1] != 1) {
744                                 close(1);
745                                 copyfd(pip[1], 1);
746                                 close(pip[1]);
747                         }
748                 }
749                 flags |= EV_EXIT;
750         }
751
752         /* This is the child process if a fork occurred. */
753         /* Execute the command. */
754         if (cmdentry.cmdtype == CMDFUNCTION) {
755 #ifdef DEBUG
756                 trputs("Shell function:  ");  trargs(argv);
757 #endif
758                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
759                 saveparam = shellparam;
760                 shellparam.malloc = 0;
761                 shellparam.reset = 1;
762                 shellparam.nparam = argc - 1;
763                 shellparam.p = argv + 1;
764                 shellparam.optnext = NULL;
765                 INTOFF;
766                 savelocalvars = localvars;
767                 localvars = NULL;
768                 INTON;
769                 if (setjmp(jmploc.loc)) {
770                         if (exception == EXSHELLPROC)
771                                 freeparam((struct shparam *)&saveparam);
772                         else {
773                                 freeparam(&shellparam);
774                                 shellparam = saveparam;
775                         }
776                         poplocalvars();
777                         localvars = savelocalvars;
778                         handler = savehandler;
779                         longjmp(handler->loc, 1);
780                 }
781                 savehandler = handler;
782                 handler = &jmploc;
783                 for (sp = varlist.list ; sp ; sp = sp->next)
784                         mklocal(sp->text);
785                 funcnest++;
786                 if (flags & EV_TESTED)
787                         evaltree(cmdentry.u.func, EV_TESTED);
788                 else
789                         evaltree(cmdentry.u.func, 0);
790                 funcnest--;
791                 INTOFF;
792                 poplocalvars();
793                 localvars = savelocalvars;
794                 freeparam(&shellparam);
795                 shellparam = saveparam;
796                 handler = savehandler;
797                 popredir();
798                 INTON;
799                 if (evalskip == SKIPFUNC) {
800                         evalskip = 0;
801                         skipcount = 0;
802                 }
803                 if (flags & EV_EXIT)
804                         exitshell(exitstatus);
805         } else if (cmdentry.cmdtype == CMDBUILTIN) {
806 #ifdef DEBUG
807                 trputs("builtin command:  ");  trargs(argv);
808 #endif
809                 mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
810                 if (flags == EV_BACKCMD) {
811                         memout.nleft = 0;
812                         memout.nextc = memout.buf;
813                         memout.bufsize = 64;
814                         mode |= REDIR_BACKQ;
815                 }
816                 redirect(cmd->ncmd.redirect, mode);
817                 savecmdname = commandname;
818                 cmdenviron = varlist.list;
819                 e = -1;
820                 if (setjmp(jmploc.loc)) {
821                         e = exception;
822                         exitstatus = (e == EXINT)? SIGINT+128 : 2;
823                         goto cmddone;
824                 }
825                 savehandler = handler;
826                 handler = &jmploc;
827                 commandname = argv[0];
828                 argptr = argv + 1;
829                 optptr = NULL;                  /* initialize nextopt */
830                 exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
831                 flushall();
832 cmddone:
833                 cmdenviron = NULL;
834                 out1 = &output;
835                 out2 = &errout;
836                 freestdout();
837                 if (e != EXSHELLPROC) {
838                         commandname = savecmdname;
839                         if (flags & EV_EXIT) {
840                                 exitshell(exitstatus);
841                         }
842                 }
843                 handler = savehandler;
844                 if (e != -1) {
845                         if ((e != EXERROR && e != EXEXEC)
846                            || cmdentry.u.index == BLTINCMD
847                            || cmdentry.u.index == DOTCMD
848                            || cmdentry.u.index == EVALCMD
849 #ifndef NO_HISTORY
850                            || cmdentry.u.index == HISTCMD
851 #endif
852                            || cmdentry.u.index == EXECCMD
853                            || cmdentry.u.index == COMMANDCMD)
854                                 exraise(e);
855                         FORCEINTON;
856                 }
857                 if (cmdentry.u.index != EXECCMD)
858                         popredir();
859                 if (flags == EV_BACKCMD) {
860                         backcmd->buf = memout.buf;
861                         backcmd->nleft = memout.nextc - memout.buf;
862                         memout.buf = NULL;
863                 }
864         } else {
865 #ifdef DEBUG
866                 trputs("normal command:  ");  trargs(argv);
867 #endif
868                 clearredir();
869                 redirect(cmd->ncmd.redirect, 0);
870                 for (sp = varlist.list ; sp ; sp = sp->next)
871                         setvareq(sp->text, VEXPORT|VSTACK);
872                 envp = environment();
873                 shellexec(argv, envp, pathval(), cmdentry.u.index);
874                 /*NOTREACHED*/
875         }
876         goto out;
877
878 parent: /* parent process gets here (if we forked) */
879         if (mode == 0) {        /* argument to fork */
880                 INTOFF;
881                 exitstatus = waitforjob(jp, &realstatus);
882                 INTON;
883                 if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
884                         evalskip = SKIPBREAK;
885                         skipcount = loopnest;
886                 }
887         } else if (mode == 2) {
888                 backcmd->fd = pip[0];
889                 close(pip[1]);
890                 backcmd->jp = jp;
891         }
892
893 out:
894         if (lastarg)
895                 setvar("_", lastarg, 0);
896         if (do_clearcmdentry)
897                 clearcmdentry(0);
898         popstackmark(&smark);
899 }
900
901
902
903 /*
904  * Search for a command.  This is called before we fork so that the
905  * location of the command will be available in the parent as well as
906  * the child.  The check for "goodname" is an overly conservative
907  * check that the name will not be subject to expansion.
908  */
909
910 STATIC void
911 prehash(union node *n)
912 {
913         struct cmdentry entry;
914
915         if (n->type == NCMD && n->ncmd.args)
916                 if (goodname(n->ncmd.args->narg.text))
917                         find_command(n->ncmd.args->narg.text, &entry, 0,
918                                      pathval());
919 }
920
921
922
923 /*
924  * Builtin commands.  Builtin commands whose functions are closely
925  * tied to evaluation are implemented here.
926  */
927
928 /*
929  * No command given, or a bltin command with no arguments.  Set the
930  * specified variables.
931  */
932
933 int
934 bltincmd(int argc __unused, char **argv __unused)
935 {
936         listsetvar(cmdenviron);
937         /*
938          * Preserve exitstatus of a previous possible redirection
939          * as POSIX mandates
940          */
941         return exitstatus;
942 }
943
944
945 /*
946  * Handle break and continue commands.  Break, continue, and return are
947  * all handled by setting the evalskip flag.  The evaluation routines
948  * above all check this flag, and if it is set they start skipping
949  * commands rather than executing them.  The variable skipcount is
950  * the number of loops to break/continue, or the number of function
951  * levels to return.  (The latter is always 1.)  It should probably
952  * be an error to break out of more loops than exist, but it isn't
953  * in the standard shell so we don't make it one here.
954  */
955
956 int
957 breakcmd(int argc, char **argv)
958 {
959         int n = argc > 1 ? number(argv[1]) : 1;
960
961         if (n > loopnest)
962                 n = loopnest;
963         if (n > 0) {
964                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
965                 skipcount = n;
966         }
967         return 0;
968 }
969
970 /*
971  * The `command' command.
972  */
973 int
974 commandcmd(int argc, char **argv)
975 {
976         static char stdpath[] = _PATH_STDPATH;
977         struct jmploc loc, *old;
978         struct strlist *sp;
979         const char *path;
980         int ch;
981
982 #ifdef __GNUC__
983         /* Avoid longjmp clobbering */
984         (void) &path;
985         (void) &argc;
986         (void) &argv;
987 #endif
988
989         for (sp = cmdenviron; sp ; sp = sp->next)
990                 setvareq(sp->text, VEXPORT|VSTACK);
991         path = pathval();
992
993         optind = optreset = 1;
994         opterr = 0;
995         while ((ch = getopt(argc, argv, "p")) != -1) {
996                 switch (ch) {
997                 case 'p':
998                         path = stdpath;
999                         break;
1000                 case '?':
1001                 default:
1002                         error("unknown option: -%c", optopt);
1003                 }
1004         }
1005         argc -= optind;
1006         argv += optind;
1007
1008         if (argc != 0) {
1009                 old = handler;
1010                 handler = &loc;
1011                 if (setjmp(handler->loc) == 0)
1012                         shellexec(argv, environment(), path, 0);
1013                 handler = old;
1014                 if (exception == EXEXEC)
1015                         exit(exerrno);
1016                 exraise(exception);
1017         }
1018
1019         /*
1020          * Do nothing successfully if no command was specified;
1021          * ksh also does this.
1022          */
1023         exit(0);
1024 }
1025
1026
1027 /*
1028  * The return command.
1029  */
1030
1031 int
1032 returncmd(int argc, char **argv)
1033 {
1034         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
1035
1036         if (funcnest) {
1037                 evalskip = SKIPFUNC;
1038                 skipcount = 1;
1039         } else {
1040                 /* skip the rest of the file */
1041                 evalskip = SKIPFILE;
1042                 skipcount = 1;
1043         }
1044         return ret;
1045 }
1046
1047
1048 int
1049 falsecmd(int argc __unused, char **argv __unused)
1050 {
1051         return 1;
1052 }
1053
1054
1055 int
1056 truecmd(int argc __unused, char **argv __unused)
1057 {
1058         return 0;
1059 }
1060
1061
1062 int
1063 execcmd(int argc, char **argv)
1064 {
1065         if (argc > 1) {
1066                 struct strlist *sp;
1067
1068                 iflag = 0;              /* exit on error */
1069                 mflag = 0;
1070                 optschanged();
1071                 for (sp = cmdenviron; sp ; sp = sp->next)
1072                         setvareq(sp->text, VEXPORT|VSTACK);
1073                 shellexec(argv + 1, environment(), pathval(), 0);
1074
1075         }
1076         return 0;
1077 }