Fix a WARNS=3 gcc warning related to longjmp clobbers, fix a possible use
[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.6 2006/06/05 15:55:13 dillon 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                                 close(prevfd);
474                                 error("Pipe call failed: %s", strerror(errno));
475                         }
476                 }
477                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
478                         INTON;
479                         if (prevfd > 0) {
480                                 close(0);
481                                 copyfd(prevfd, 0);
482                                 close(prevfd);
483                         }
484                         if (pip[1] >= 0) {
485                                 if (!(prevfd >= 0 && pip[0] == 0))
486                                         close(pip[0]);
487                                 if (pip[1] != 1) {
488                                         close(1);
489                                         copyfd(pip[1], 1);
490                                         close(pip[1]);
491                                 }
492                         }
493                         evaltree(lp->n, EV_EXIT);
494                 }
495                 if (prevfd >= 0)
496                         close(prevfd);
497                 prevfd = pip[0];
498                 close(pip[1]);
499         }
500         INTON;
501         if (n->npipe.backgnd == 0) {
502                 INTOFF;
503                 exitstatus = waitforjob(jp, (int *)NULL);
504                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
505                 INTON;
506         }
507 }
508
509
510
511 /*
512  * Execute a command inside back quotes.  If it's a builtin command, we
513  * want to save its output in a block obtained from malloc.  Otherwise
514  * we fork off a subprocess and get the output of the command via a pipe.
515  * Should be called with interrupts off.
516  */
517
518 void
519 evalbackcmd(union node *n, struct backcmd *result)
520 {
521         int pip[2];
522         struct job *jp;
523         struct stackmark smark;         /* unnecessary */
524
525         setstackmark(&smark);
526         result->fd = -1;
527         result->buf = NULL;
528         result->nleft = 0;
529         result->jp = NULL;
530         if (n == NULL) {
531                 exitstatus = 0;
532                 goto out;
533         }
534         if (n->type == NCMD) {
535                 exitstatus = oexitstatus;
536                 evalcommand(n, EV_BACKCMD, result);
537         } else {
538                 exitstatus = 0;
539                 if (pipe(pip) < 0)
540                         error("Pipe call failed: %s", strerror(errno));
541                 jp = makejob(n, 1);
542                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
543                         FORCEINTON;
544                         close(pip[0]);
545                         if (pip[1] != 1) {
546                                 close(1);
547                                 copyfd(pip[1], 1);
548                                 close(pip[1]);
549                         }
550                         evaltree(n, EV_EXIT);
551                 }
552                 close(pip[1]);
553                 result->fd = pip[0];
554                 result->jp = jp;
555         }
556 out:
557         popstackmark(&smark);
558         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
559                 result->fd, result->buf, result->nleft, result->jp));
560 }
561
562
563
564 /*
565  * Execute a simple command.
566  */
567
568 STATIC void
569 evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
570 {
571         struct stackmark smark;
572         union node *argp;
573         struct arglist arglist;
574         struct arglist varlist;
575         char **argv;
576         int argc;
577         char **envp;
578         int varflag;
579         struct strlist *sp;
580         int mode;
581         int pip[2];
582         struct cmdentry cmdentry;
583         struct job *jp;
584         struct jmploc jmploc;
585         struct jmploc *volatile savehandler;
586         const char *volatile savecmdname;
587         volatile struct shparam saveparam;
588         struct localvar *volatile savelocalvars;
589         volatile int e;
590         char *lastarg;
591         int realstatus;
592         int do_clearcmdentry;
593 #if __GNUC__
594         /* Avoid longjmp clobbering */
595         (void) &argv;
596         (void) &argc;
597         (void) &lastarg;
598         (void) &flags;
599         (void) &do_clearcmdentry;
600 #endif
601
602         /* First expand the arguments. */
603         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
604         setstackmark(&smark);
605         arglist.lastp = &arglist.list;
606         varlist.lastp = &varlist.list;
607         varflag = 1;
608         do_clearcmdentry = 0;
609         oexitstatus = exitstatus;
610         exitstatus = 0;
611         for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
612                 char *p = argp->narg.text;
613                 if (varflag && is_name(*p)) {
614                         do {
615                                 p++;
616                         } while (is_in_name(*p));
617                         if (*p == '=') {
618                                 expandarg(argp, &varlist, EXP_VARTILDE);
619                                 continue;
620                         }
621                 }
622                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
623                 varflag = 0;
624         }
625         *arglist.lastp = NULL;
626         *varlist.lastp = NULL;
627         expredir(cmd->ncmd.redirect);
628         argc = 0;
629         for (sp = arglist.list ; sp ; sp = sp->next)
630                 argc++;
631         argv = stalloc(sizeof (char *) * (argc + 1));
632
633         for (sp = arglist.list ; sp ; sp = sp->next) {
634                 TRACE(("evalcommand arg: %s\n", sp->text));
635                 *argv++ = sp->text;
636         }
637         *argv = NULL;
638         lastarg = NULL;
639         if (iflag && funcnest == 0 && argc > 0)
640                 lastarg = argv[-1];
641         argv -= argc;
642
643         /* Print the command if xflag is set. */
644         if (xflag) {
645                 outc('+', &errout);
646                 for (sp = varlist.list ; sp ; sp = sp->next) {
647                         outc(' ', &errout);
648                         out2str(sp->text);
649                 }
650                 for (sp = arglist.list ; sp ; sp = sp->next) {
651                         outc(' ', &errout);
652                         out2str(sp->text);
653                 }
654                 outc('\n', &errout);
655                 flushout(&errout);
656         }
657
658         /* Now locate the command. */
659         if (argc == 0) {
660                 cmdentry.cmdtype = CMDBUILTIN;
661                 cmdentry.u.index = BLTINCMD;
662         } else {
663                 static const char PATH[] = "PATH=";
664                 const char *path = pathval();
665
666                 /*
667                  * Modify the command lookup path, if a PATH= assignment
668                  * is present
669                  */
670                 for (sp = varlist.list ; sp ; sp = sp->next)
671                         if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
672                                 path = sp->text + sizeof(PATH) - 1;
673                                 /* 
674                                  * On `PATH=... command`, we need to make
675                                  * sure that the command isn't using the
676                                  * non-updated hash table of the outer PATH
677                                  * setting and we need to make sure that 
678                                  * the hash table isn't filled with items
679                                  * from the temporary setting.
680                                  *
681                                  * It would be better to forbit using and 
682                                  * updating the table while this command
683                                  * runs, by the command finding mechanism
684                                  * is heavily integrated with hash handling,
685                                  * so we just delete the hash before and after
686                                  * the command runs. Partly deleting like
687                                  * changepatch() does doesn't seem worth the
688                                  * bookinging effort, since most such runs add
689                                  * diretories in front of the new PATH.
690                                  */
691                                 clearcmdentry(0);
692                                 do_clearcmdentry = 1;
693                         }
694
695                 find_command(argv[0], &cmdentry, 1, path);
696                 if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
697                         exitstatus = 127;
698                         flushout(&errout);
699                         return;
700                 }
701                 /* implement the bltin builtin here */
702                 if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
703                         for (;;) {
704                                 argv++;
705                                 if (--argc == 0)
706                                         break;
707                                 if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
708                                         outfmt(&errout, "%s: not found\n", *argv);
709                                         exitstatus = 127;
710                                         flushout(&errout);
711                                         return;
712                                 }
713                                 if (cmdentry.u.index != BLTINCMD)
714                                         break;
715                         }
716                 }
717         }
718
719         /* Fork off a child process if necessary. */
720         if (cmd->ncmd.backgnd
721          || (cmdentry.cmdtype == CMDNORMAL
722             && ((flags & EV_EXIT) == 0 || Tflag))
723          || ((flags & EV_BACKCMD) != 0
724             && (cmdentry.cmdtype != CMDBUILTIN
725                  || cmdentry.u.index == CDCMD
726                  || cmdentry.u.index == DOTCMD
727                  || cmdentry.u.index == EVALCMD))
728          || (cmdentry.cmdtype == CMDBUILTIN &&
729             cmdentry.u.index == COMMANDCMD)) {
730                 jp = makejob(cmd, 1);
731                 mode = cmd->ncmd.backgnd;
732                 if (flags & EV_BACKCMD) {
733                         mode = FORK_NOJOB;
734                         if (pipe(pip) < 0)
735                                 error("Pipe call failed: %s", strerror(errno));
736                 }
737                 if (forkshell(jp, cmd, mode) != 0)
738                         goto parent;    /* at end of routine */
739                 if (flags & EV_BACKCMD) {
740                         FORCEINTON;
741                         close(pip[0]);
742                         if (pip[1] != 1) {
743                                 close(1);
744                                 copyfd(pip[1], 1);
745                                 close(pip[1]);
746                         }
747                 }
748                 flags |= EV_EXIT;
749         }
750
751         /* This is the child process if a fork occurred. */
752         /* Execute the command. */
753         if (cmdentry.cmdtype == CMDFUNCTION) {
754 #ifdef DEBUG
755                 trputs("Shell function:  ");  trargs(argv);
756 #endif
757                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
758                 saveparam = shellparam;
759                 shellparam.malloc = 0;
760                 shellparam.reset = 1;
761                 shellparam.nparam = argc - 1;
762                 shellparam.p = argv + 1;
763                 shellparam.optnext = NULL;
764                 INTOFF;
765                 savelocalvars = localvars;
766                 localvars = NULL;
767                 INTON;
768                 if (setjmp(jmploc.loc)) {
769                         if (exception == EXSHELLPROC)
770                                 freeparam((struct shparam *)&saveparam);
771                         else {
772                                 freeparam(&shellparam);
773                                 shellparam = saveparam;
774                         }
775                         poplocalvars();
776                         localvars = savelocalvars;
777                         handler = savehandler;
778                         longjmp(handler->loc, 1);
779                 }
780                 savehandler = handler;
781                 handler = &jmploc;
782                 for (sp = varlist.list ; sp ; sp = sp->next)
783                         mklocal(sp->text);
784                 funcnest++;
785                 if (flags & EV_TESTED)
786                         evaltree(cmdentry.u.func, EV_TESTED);
787                 else
788                         evaltree(cmdentry.u.func, 0);
789                 funcnest--;
790                 INTOFF;
791                 poplocalvars();
792                 localvars = savelocalvars;
793                 freeparam(&shellparam);
794                 shellparam = saveparam;
795                 handler = savehandler;
796                 popredir();
797                 INTON;
798                 if (evalskip == SKIPFUNC) {
799                         evalskip = 0;
800                         skipcount = 0;
801                 }
802                 if (flags & EV_EXIT)
803                         exitshell(exitstatus);
804         } else if (cmdentry.cmdtype == CMDBUILTIN) {
805 #ifdef DEBUG
806                 trputs("builtin command:  ");  trargs(argv);
807 #endif
808                 mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
809                 if (flags == EV_BACKCMD) {
810                         memout.nleft = 0;
811                         memout.nextc = memout.buf;
812                         memout.bufsize = 64;
813                         mode |= REDIR_BACKQ;
814                 }
815                 redirect(cmd->ncmd.redirect, mode);
816                 savecmdname = commandname;
817                 cmdenviron = varlist.list;
818                 e = -1;
819                 if (setjmp(jmploc.loc)) {
820                         e = exception;
821                         exitstatus = (e == EXINT)? SIGINT+128 : 2;
822                         goto cmddone;
823                 }
824                 savehandler = handler;
825                 handler = &jmploc;
826                 commandname = argv[0];
827                 argptr = argv + 1;
828                 optptr = NULL;                  /* initialize nextopt */
829                 exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
830                 flushall();
831 cmddone:
832                 cmdenviron = NULL;
833                 out1 = &output;
834                 out2 = &errout;
835                 freestdout();
836                 if (e != EXSHELLPROC) {
837                         commandname = savecmdname;
838                         if (flags & EV_EXIT) {
839                                 exitshell(exitstatus);
840                         }
841                 }
842                 handler = savehandler;
843                 if (e != -1) {
844                         if ((e != EXERROR && e != EXEXEC)
845                            || cmdentry.u.index == BLTINCMD
846                            || cmdentry.u.index == DOTCMD
847                            || cmdentry.u.index == EVALCMD
848 #ifndef NO_HISTORY
849                            || cmdentry.u.index == HISTCMD
850 #endif
851                            || cmdentry.u.index == EXECCMD
852                            || cmdentry.u.index == COMMANDCMD)
853                                 exraise(e);
854                         FORCEINTON;
855                 }
856                 if (cmdentry.u.index != EXECCMD)
857                         popredir();
858                 if (flags == EV_BACKCMD) {
859                         backcmd->buf = memout.buf;
860                         backcmd->nleft = memout.nextc - memout.buf;
861                         memout.buf = NULL;
862                 }
863         } else {
864 #ifdef DEBUG
865                 trputs("normal command:  ");  trargs(argv);
866 #endif
867                 clearredir();
868                 redirect(cmd->ncmd.redirect, 0);
869                 for (sp = varlist.list ; sp ; sp = sp->next)
870                         setvareq(sp->text, VEXPORT|VSTACK);
871                 envp = environment();
872                 shellexec(argv, envp, pathval(), cmdentry.u.index);
873                 /*NOTREACHED*/
874         }
875         goto out;
876
877 parent: /* parent process gets here (if we forked) */
878         if (mode == 0) {        /* argument to fork */
879                 INTOFF;
880                 exitstatus = waitforjob(jp, &realstatus);
881                 INTON;
882                 if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) {
883                         evalskip = SKIPBREAK;
884                         skipcount = loopnest;
885                 }
886         } else if (mode == 2) {
887                 backcmd->fd = pip[0];
888                 close(pip[1]);
889                 backcmd->jp = jp;
890         }
891
892 out:
893         if (lastarg)
894                 setvar("_", lastarg, 0);
895         if (do_clearcmdentry)
896                 clearcmdentry(0);
897         popstackmark(&smark);
898 }
899
900
901
902 /*
903  * Search for a command.  This is called before we fork so that the
904  * location of the command will be available in the parent as well as
905  * the child.  The check for "goodname" is an overly conservative
906  * check that the name will not be subject to expansion.
907  */
908
909 STATIC void
910 prehash(union node *n)
911 {
912         struct cmdentry entry;
913
914         if (n->type == NCMD && n->ncmd.args)
915                 if (goodname(n->ncmd.args->narg.text))
916                         find_command(n->ncmd.args->narg.text, &entry, 0,
917                                      pathval());
918 }
919
920
921
922 /*
923  * Builtin commands.  Builtin commands whose functions are closely
924  * tied to evaluation are implemented here.
925  */
926
927 /*
928  * No command given, or a bltin command with no arguments.  Set the
929  * specified variables.
930  */
931
932 int
933 bltincmd(int argc __unused, char **argv __unused)
934 {
935         listsetvar(cmdenviron);
936         /*
937          * Preserve exitstatus of a previous possible redirection
938          * as POSIX mandates
939          */
940         return exitstatus;
941 }
942
943
944 /*
945  * Handle break and continue commands.  Break, continue, and return are
946  * all handled by setting the evalskip flag.  The evaluation routines
947  * above all check this flag, and if it is set they start skipping
948  * commands rather than executing them.  The variable skipcount is
949  * the number of loops to break/continue, or the number of function
950  * levels to return.  (The latter is always 1.)  It should probably
951  * be an error to break out of more loops than exist, but it isn't
952  * in the standard shell so we don't make it one here.
953  */
954
955 int
956 breakcmd(int argc, char **argv)
957 {
958         int n = argc > 1 ? number(argv[1]) : 1;
959
960         if (n > loopnest)
961                 n = loopnest;
962         if (n > 0) {
963                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
964                 skipcount = n;
965         }
966         return 0;
967 }
968
969 /*
970  * The `command' command.
971  */
972 int
973 commandcmd(int argc, char **argv)
974 {
975         static char stdpath[] = _PATH_STDPATH;
976         struct jmploc loc, *old;
977         struct strlist *sp;
978         const char *path;
979         int ch;
980
981 #ifdef __GNUC__
982         /* Avoid longjmp clobbering */
983         (void) &path;
984         (void) &argc;
985         (void) &argv;
986 #endif
987
988         for (sp = cmdenviron; sp ; sp = sp->next)
989                 setvareq(sp->text, VEXPORT|VSTACK);
990         path = pathval();
991
992         optind = optreset = 1;
993         opterr = 0;
994         while ((ch = getopt(argc, argv, "p")) != -1) {
995                 switch (ch) {
996                 case 'p':
997                         path = stdpath;
998                         break;
999                 case '?':
1000                 default:
1001                         error("unknown option: -%c", optopt);
1002                 }
1003         }
1004         argc -= optind;
1005         argv += optind;
1006
1007         if (argc != 0) {
1008                 old = handler;
1009                 handler = &loc;
1010                 if (setjmp(handler->loc) == 0)
1011                         shellexec(argv, environment(), path, 0);
1012                 handler = old;
1013                 if (exception == EXEXEC)
1014                         exit(exerrno);
1015                 exraise(exception);
1016         }
1017
1018         /*
1019          * Do nothing successfully if no command was specified;
1020          * ksh also does this.
1021          */
1022         exit(0);
1023 }
1024
1025
1026 /*
1027  * The return command.
1028  */
1029
1030 int
1031 returncmd(int argc, char **argv)
1032 {
1033         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
1034
1035         if (funcnest) {
1036                 evalskip = SKIPFUNC;
1037                 skipcount = 1;
1038         } else {
1039                 /* skip the rest of the file */
1040                 evalskip = SKIPFILE;
1041                 skipcount = 1;
1042         }
1043         return ret;
1044 }
1045
1046
1047 int
1048 falsecmd(int argc __unused, char **argv __unused)
1049 {
1050         return 1;
1051 }
1052
1053
1054 int
1055 truecmd(int argc __unused, char **argv __unused)
1056 {
1057         return 0;
1058 }
1059
1060
1061 int
1062 execcmd(int argc, char **argv)
1063 {
1064         if (argc > 1) {
1065                 struct strlist *sp;
1066
1067                 iflag = 0;              /* exit on error */
1068                 mflag = 0;
1069                 optschanged();
1070                 for (sp = cmdenviron; sp ; sp = sp->next)
1071                         setvareq(sp->text, VEXPORT|VSTACK);
1072                 shellexec(argv + 1, environment(), pathval(), 0);
1073
1074         }
1075         return 0;
1076 }