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