eval.c revision 1.112 1 /* $NetBSD: eval.c,v 1.112 2016/02/22 20:03:48 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1993
5 * The Regents of the University of California. 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 <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
39 #else
40 __RCSID("$NetBSD: eval.c,v 1.112 2016/02/22 20:03:48 christos Exp $");
41 #endif
42 #endif /* not lint */
43
44 #include <stdbool.h>
45 #include <stdlib.h>
46 #include <signal.h>
47 #include <stdio.h>
48 #include <errno.h>
49 #include <limits.h>
50 #include <unistd.h>
51 #include <sys/fcntl.h>
52 #include <sys/times.h>
53 #include <sys/param.h>
54 #include <sys/types.h>
55 #include <sys/wait.h>
56 #include <sys/sysctl.h>
57
58 /*
59 * Evaluate a command.
60 */
61
62 #include "shell.h"
63 #include "nodes.h"
64 #include "syntax.h"
65 #include "expand.h"
66 #include "parser.h"
67 #include "jobs.h"
68 #include "eval.h"
69 #include "builtins.h"
70 #include "options.h"
71 #include "exec.h"
72 #include "redir.h"
73 #include "input.h"
74 #include "output.h"
75 #include "trap.h"
76 #include "var.h"
77 #include "memalloc.h"
78 #include "error.h"
79 #include "show.h"
80 #include "mystring.h"
81 #include "main.h"
82 #ifndef SMALL
83 #include "myhistedit.h"
84 #endif
85
86
87 /* flags in argument to evaltree */
88 #define EV_EXIT 01 /* exit after evaluating tree */
89 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
90 #define EV_BACKCMD 04 /* command executing within back quotes */
91
92 STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */
93 STATIC int skipcount; /* number of levels to skip */
94 STATIC int loopnest; /* current loop nesting level */
95 STATIC int funcnest; /* depth of function calls */
96 STATIC int builtin_flags; /* evalcommand flags for builtins */
97 /*
98 * Base function nesting level inside a dot command. Set to 0 initially
99 * and to (funcnest + 1) before every dot command to enable
100 * 1) detection of being in a file sourced by a dot command and
101 * 2) counting of function nesting in that file for the implementation
102 * of the return command.
103 * The value is reset to its previous value after the dot command.
104 */
105 STATIC int dot_funcnest;
106
107
108 const char *commandname;
109 struct strlist *cmdenviron;
110 int exitstatus; /* exit status of last command */
111 int back_exitstatus; /* exit status of backquoted command */
112
113
114 STATIC void evalloop(union node *, int);
115 STATIC void evalfor(union node *, int);
116 STATIC void evalcase(union node *, int);
117 STATIC void evalsubshell(union node *, int);
118 STATIC void expredir(union node *);
119 STATIC void evalpipe(union node *);
120 STATIC void evalcommand(union node *, int, struct backcmd *);
121 STATIC void prehash(union node *);
122
123 STATIC char *find_dot_file(char *);
124
125 /*
126 * Called to reset things after an exception.
127 */
128
129 #ifdef mkinit
130 INCLUDE "eval.h"
131
132 RESET {
133 reset_eval();
134 }
135
136 SHELLPROC {
137 exitstatus = 0;
138 }
139 #endif
140
141 void
142 reset_eval(void)
143 {
144 evalskip = SKIPNONE;
145 dot_funcnest = 0;
146 loopnest = 0;
147 funcnest = 0;
148 }
149
150 static int
151 sh_pipe(int fds[2])
152 {
153 int nfd;
154
155 if (pipe(fds))
156 return -1;
157
158 if (fds[0] < 3) {
159 nfd = fcntl(fds[0], F_DUPFD, 3);
160 if (nfd != -1) {
161 close(fds[0]);
162 fds[0] = nfd;
163 }
164 }
165
166 if (fds[1] < 3) {
167 nfd = fcntl(fds[1], F_DUPFD, 3);
168 if (nfd != -1) {
169 close(fds[1]);
170 fds[1] = nfd;
171 }
172 }
173 return 0;
174 }
175
176
177 /*
178 * The eval commmand.
179 */
180
181 int
182 evalcmd(int argc, char **argv)
183 {
184 char *p;
185 char *concat;
186 char **ap;
187
188 if (argc > 1) {
189 p = argv[1];
190 if (argc > 2) {
191 STARTSTACKSTR(concat);
192 ap = argv + 2;
193 for (;;) {
194 while (*p)
195 STPUTC(*p++, concat);
196 if ((p = *ap++) == NULL)
197 break;
198 STPUTC(' ', concat);
199 }
200 STPUTC('\0', concat);
201 p = grabstackstr(concat);
202 }
203 evalstring(p, builtin_flags & EV_TESTED);
204 }
205 return exitstatus;
206 }
207
208
209 /*
210 * Execute a command or commands contained in a string.
211 */
212
213 void
214 evalstring(char *s, int flag)
215 {
216 union node *n;
217 struct stackmark smark;
218
219 setstackmark(&smark);
220 setinputstring(s, 1);
221
222 while ((n = parsecmd(0)) != NEOF) {
223 if (nflag == 0)
224 evaltree(n, flag);
225 popstackmark(&smark);
226 }
227 popfile();
228 popstackmark(&smark);
229 }
230
231
232
233 /*
234 * Evaluate a parse tree. The value is left in the global variable
235 * exitstatus.
236 */
237
238 void
239 evaltree(union node *n, int flags)
240 {
241 bool do_etest;
242
243 do_etest = false;
244 if (n == NULL) {
245 TRACE(("evaltree(NULL) called\n"));
246 exitstatus = 0;
247 goto out;
248 }
249 #ifndef SMALL
250 displayhist = 1; /* show history substitutions done with fc */
251 #endif
252 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
253 getpid(), n, n->type, flags));
254 switch (n->type) {
255 case NSEMI:
256 evaltree(n->nbinary.ch1, flags & EV_TESTED);
257 if (evalskip)
258 goto out;
259 evaltree(n->nbinary.ch2, flags);
260 break;
261 case NAND:
262 evaltree(n->nbinary.ch1, EV_TESTED);
263 if (evalskip || exitstatus != 0)
264 goto out;
265 evaltree(n->nbinary.ch2, flags);
266 break;
267 case NOR:
268 evaltree(n->nbinary.ch1, EV_TESTED);
269 if (evalskip || exitstatus == 0)
270 goto out;
271 evaltree(n->nbinary.ch2, flags);
272 break;
273 case NREDIR:
274 expredir(n->nredir.redirect);
275 redirect(n->nredir.redirect, REDIR_PUSH);
276 evaltree(n->nredir.n, flags);
277 popredir();
278 break;
279 case NSUBSHELL:
280 evalsubshell(n, flags);
281 do_etest = !(flags & EV_TESTED);
282 break;
283 case NBACKGND:
284 evalsubshell(n, flags);
285 break;
286 case NIF: {
287 evaltree(n->nif.test, EV_TESTED);
288 if (evalskip)
289 goto out;
290 if (exitstatus == 0)
291 evaltree(n->nif.ifpart, flags);
292 else if (n->nif.elsepart)
293 evaltree(n->nif.elsepart, flags);
294 else
295 exitstatus = 0;
296 break;
297 }
298 case NWHILE:
299 case NUNTIL:
300 evalloop(n, flags);
301 break;
302 case NFOR:
303 evalfor(n, flags);
304 break;
305 case NCASE:
306 evalcase(n, flags);
307 break;
308 case NDEFUN:
309 defun(n->narg.text, n->narg.next);
310 exitstatus = 0;
311 break;
312 case NNOT:
313 evaltree(n->nnot.com, EV_TESTED);
314 exitstatus = !exitstatus;
315 break;
316 case NPIPE:
317 evalpipe(n);
318 do_etest = !(flags & EV_TESTED);
319 break;
320 case NCMD:
321 evalcommand(n, flags, NULL);
322 do_etest = !(flags & EV_TESTED);
323 break;
324 default:
325 out1fmt("Node type = %d\n", n->type);
326 flushout(&output);
327 break;
328 }
329 out:
330 if (pendingsigs)
331 dotrap();
332 if ((flags & EV_EXIT) != 0 || (eflag && exitstatus != 0 && do_etest))
333 exitshell(exitstatus);
334 }
335
336
337 STATIC void
338 evalloop(union node *n, int flags)
339 {
340 int status;
341
342 loopnest++;
343 status = 0;
344 for (;;) {
345 evaltree(n->nbinary.ch1, EV_TESTED);
346 if (evalskip) {
347 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
348 evalskip = SKIPNONE;
349 continue;
350 }
351 if (evalskip == SKIPBREAK && --skipcount <= 0)
352 evalskip = SKIPNONE;
353 break;
354 }
355 if (n->type == NWHILE) {
356 if (exitstatus != 0)
357 break;
358 } else {
359 if (exitstatus == 0)
360 break;
361 }
362 evaltree(n->nbinary.ch2, flags & EV_TESTED);
363 status = exitstatus;
364 if (evalskip)
365 goto skipping;
366 }
367 loopnest--;
368 exitstatus = status;
369 }
370
371
372
373 STATIC void
374 evalfor(union node *n, int flags)
375 {
376 struct arglist arglist;
377 union node *argp;
378 struct strlist *sp;
379 struct stackmark smark;
380 int status = 0;
381
382 setstackmark(&smark);
383 arglist.lastp = &arglist.list;
384 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
385 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
386 if (evalskip)
387 goto out;
388 }
389 *arglist.lastp = NULL;
390
391 loopnest++;
392 for (sp = arglist.list ; sp ; sp = sp->next) {
393 setvar(n->nfor.var, sp->text, 0);
394 evaltree(n->nfor.body, flags & EV_TESTED);
395 status = exitstatus;
396 if (evalskip) {
397 if (evalskip == SKIPCONT && --skipcount <= 0) {
398 evalskip = SKIPNONE;
399 continue;
400 }
401 if (evalskip == SKIPBREAK && --skipcount <= 0)
402 evalskip = SKIPNONE;
403 break;
404 }
405 }
406 loopnest--;
407 exitstatus = status;
408 out:
409 popstackmark(&smark);
410 }
411
412
413
414 STATIC void
415 evalcase(union node *n, int flags)
416 {
417 union node *cp;
418 union node *patp;
419 struct arglist arglist;
420 struct stackmark smark;
421 int status = 0;
422
423 setstackmark(&smark);
424 arglist.lastp = &arglist.list;
425 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
426 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
427 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
428 if (casematch(patp, arglist.list->text)) {
429 if (evalskip == 0) {
430 evaltree(cp->nclist.body, flags);
431 status = exitstatus;
432 }
433 goto out;
434 }
435 }
436 }
437 out:
438 exitstatus = status;
439 popstackmark(&smark);
440 }
441
442
443
444 /*
445 * Kick off a subshell to evaluate a tree.
446 */
447
448 STATIC void
449 evalsubshell(union node *n, int flags)
450 {
451 struct job *jp;
452 int backgnd = (n->type == NBACKGND);
453
454 expredir(n->nredir.redirect);
455 INTOFF;
456 jp = makejob(n, 1);
457 if (forkshell(jp, n, backgnd ? FORK_BG : FORK_FG) == 0) {
458 INTON;
459 if (backgnd)
460 flags &=~ EV_TESTED;
461 redirect(n->nredir.redirect, 0);
462 /* never returns */
463 evaltree(n->nredir.n, flags | EV_EXIT);
464 }
465 if (! backgnd)
466 exitstatus = waitforjob(jp);
467 INTON;
468 }
469
470
471
472 /*
473 * Compute the names of the files in a redirection list.
474 */
475
476 STATIC void
477 expredir(union node *n)
478 {
479 union node *redir;
480
481 for (redir = n ; redir ; redir = redir->nfile.next) {
482 struct arglist fn;
483 fn.lastp = &fn.list;
484 switch (redir->type) {
485 case NFROMTO:
486 case NFROM:
487 case NTO:
488 case NCLOBBER:
489 case NAPPEND:
490 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
491 redir->nfile.expfname = fn.list->text;
492 break;
493 case NFROMFD:
494 case NTOFD:
495 if (redir->ndup.vname) {
496 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
497 fixredir(redir, fn.list->text, 1);
498 }
499 break;
500 }
501 }
502 }
503
504
505
506 /*
507 * Evaluate a pipeline. All the processes in the pipeline are children
508 * of the process creating the pipeline. (This differs from some versions
509 * of the shell, which make the last process in a pipeline the parent
510 * of all the rest.)
511 */
512
513 STATIC void
514 evalpipe(union node *n)
515 {
516 struct job *jp;
517 struct nodelist *lp;
518 int pipelen;
519 int prevfd;
520 int pip[2];
521
522 TRACE(("evalpipe(0x%lx) called\n", (long)n));
523 pipelen = 0;
524 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
525 pipelen++;
526 INTOFF;
527 jp = makejob(n, pipelen);
528 prevfd = -1;
529 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
530 prehash(lp->n);
531 pip[1] = -1;
532 if (lp->next) {
533 if (sh_pipe(pip) < 0) {
534 if (prevfd >= 0)
535 close(prevfd);
536 error("Pipe call failed");
537 }
538 }
539 if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
540 INTON;
541 if (prevfd > 0) {
542 close(0);
543 copyfd(prevfd, 0, 1, 0);
544 close(prevfd);
545 }
546 if (pip[1] >= 0) {
547 close(pip[0]);
548 if (pip[1] != 1) {
549 close(1);
550 copyfd(pip[1], 1, 1, 0);
551 close(pip[1]);
552 }
553 }
554 evaltree(lp->n, EV_EXIT);
555 }
556 if (prevfd >= 0)
557 close(prevfd);
558 prevfd = pip[0];
559 close(pip[1]);
560 }
561 if (n->npipe.backgnd == 0) {
562 exitstatus = waitforjob(jp);
563 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
564 }
565 INTON;
566 }
567
568
569
570 /*
571 * Execute a command inside back quotes. If it's a builtin command, we
572 * want to save its output in a block obtained from malloc. Otherwise
573 * we fork off a subprocess and get the output of the command via a pipe.
574 * Should be called with interrupts off.
575 */
576
577 void
578 evalbackcmd(union node *n, struct backcmd *result)
579 {
580 int pip[2];
581 struct job *jp;
582 struct stackmark smark; /* unnecessary */
583
584 setstackmark(&smark);
585 result->fd = -1;
586 result->buf = NULL;
587 result->nleft = 0;
588 result->jp = NULL;
589 if (n == NULL) {
590 goto out;
591 }
592 #ifdef notyet
593 /*
594 * For now we disable executing builtins in the same
595 * context as the shell, because we are not keeping
596 * enough state to recover from changes that are
597 * supposed only to affect subshells. eg. echo "`cd /`"
598 */
599 if (n->type == NCMD) {
600 exitstatus = oexitstatus;
601 evalcommand(n, EV_BACKCMD, result);
602 } else
603 #endif
604 {
605 INTOFF;
606 if (sh_pipe(pip) < 0)
607 error("Pipe call failed");
608 jp = makejob(n, 1);
609 if (forkshell(jp, n, FORK_NOJOB) == 0) {
610 FORCEINTON;
611 close(pip[0]);
612 if (pip[1] != 1) {
613 close(1);
614 copyfd(pip[1], 1, 1, 0);
615 close(pip[1]);
616 }
617 eflag = 0;
618 evaltree(n, EV_EXIT);
619 /* NOTREACHED */
620 }
621 close(pip[1]);
622 result->fd = pip[0];
623 result->jp = jp;
624 INTON;
625 }
626 out:
627 popstackmark(&smark);
628 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
629 result->fd, result->buf, result->nleft, result->jp));
630 }
631
632 static const char *
633 syspath(void)
634 {
635 static char *sys_path = NULL;
636 static int mib[] = {CTL_USER, USER_CS_PATH};
637 static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";
638 size_t len;
639
640 if (sys_path == NULL) {
641 if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&
642 (sys_path = ckmalloc(len + 5)) != NULL &&
643 sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {
644 memcpy(sys_path, "PATH=", 5);
645 } else {
646 ckfree(sys_path);
647 /* something to keep things happy */
648 sys_path = def_path;
649 }
650 }
651 return sys_path;
652 }
653
654 static int
655 parse_command_args(int argc, char **argv, int *use_syspath)
656 {
657 int sv_argc = argc;
658 char *cp, c;
659
660 *use_syspath = 0;
661
662 for (;;) {
663 argv++;
664 if (--argc == 0)
665 break;
666 cp = *argv;
667 if (*cp++ != '-')
668 break;
669 if (*cp == '-' && cp[1] == 0) {
670 argv++;
671 argc--;
672 break;
673 }
674 while ((c = *cp++)) {
675 switch (c) {
676 case 'p':
677 *use_syspath = 1;
678 break;
679 default:
680 /* run 'typecmd' for other options */
681 return 0;
682 }
683 }
684 }
685 return sv_argc - argc;
686 }
687
688 int vforked = 0;
689 extern char *trap[];
690
691 /*
692 * Execute a simple command.
693 */
694
695 STATIC void
696 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
697 {
698 struct stackmark smark;
699 union node *argp;
700 struct arglist arglist;
701 struct arglist varlist;
702 volatile int flags = flgs;
703 char ** volatile argv;
704 volatile int argc;
705 char **envp;
706 int varflag;
707 struct strlist *sp;
708 volatile int mode;
709 int pip[2];
710 struct cmdentry cmdentry;
711 struct job * volatile jp;
712 struct jmploc jmploc;
713 struct jmploc *volatile savehandler = NULL;
714 const char *volatile savecmdname;
715 volatile struct shparam saveparam;
716 struct localvar *volatile savelocalvars;
717 volatile int e;
718 char * volatile lastarg;
719 const char * volatile path = pathval();
720 volatile int temp_path;
721
722 vforked = 0;
723 /* First expand the arguments. */
724 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
725 setstackmark(&smark);
726 back_exitstatus = 0;
727
728 arglist.lastp = &arglist.list;
729 varflag = 1;
730 /* Expand arguments, ignoring the initial 'name=value' ones */
731 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
732 char *p = argp->narg.text;
733 if (varflag && is_name(*p)) {
734 do {
735 p++;
736 } while (is_in_name(*p));
737 if (*p == '=')
738 continue;
739 }
740 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
741 varflag = 0;
742 }
743 *arglist.lastp = NULL;
744
745 expredir(cmd->ncmd.redirect);
746
747 /* Now do the initial 'name=value' ones we skipped above */
748 varlist.lastp = &varlist.list;
749 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
750 char *p = argp->narg.text;
751 if (!is_name(*p))
752 break;
753 do
754 p++;
755 while (is_in_name(*p));
756 if (*p != '=')
757 break;
758 expandarg(argp, &varlist, EXP_VARTILDE);
759 }
760 *varlist.lastp = NULL;
761
762 argc = 0;
763 for (sp = arglist.list ; sp ; sp = sp->next)
764 argc++;
765 argv = stalloc(sizeof (char *) * (argc + 1));
766
767 for (sp = arglist.list ; sp ; sp = sp->next) {
768 TRACE(("evalcommand arg: %s\n", sp->text));
769 *argv++ = sp->text;
770 }
771 *argv = NULL;
772 lastarg = NULL;
773 if (iflag && funcnest == 0 && argc > 0)
774 lastarg = argv[-1];
775 argv -= argc;
776
777 /* Print the command if xflag is set. */
778 if (xflag) {
779 char sep = 0;
780 out2str(ps4val());
781 for (sp = varlist.list ; sp ; sp = sp->next) {
782 if (sep != 0)
783 outc(sep, &errout);
784 out2shstr(sp->text);
785 sep = ' ';
786 }
787 for (sp = arglist.list ; sp ; sp = sp->next) {
788 if (sep != 0)
789 outc(sep, &errout);
790 out2shstr(sp->text);
791 sep = ' ';
792 }
793 outc('\n', &errout);
794 flushout(&errout);
795 }
796
797 /* Now locate the command. */
798 if (argc == 0) {
799 cmdentry.cmdtype = CMDSPLBLTIN;
800 cmdentry.u.bltin = bltincmd;
801 } else {
802 static const char PATH[] = "PATH=";
803 int cmd_flags = DO_ERR;
804
805 /*
806 * Modify the command lookup path, if a PATH= assignment
807 * is present
808 */
809 for (sp = varlist.list; sp; sp = sp->next)
810 if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
811 path = sp->text + sizeof(PATH) - 1;
812
813 do {
814 int argsused, use_syspath;
815 find_command(argv[0], &cmdentry, cmd_flags, path);
816 if (cmdentry.cmdtype == CMDUNKNOWN) {
817 exitstatus = 127;
818 flushout(&errout);
819 goto out;
820 }
821
822 /* implement the 'command' builtin here */
823 if (cmdentry.cmdtype != CMDBUILTIN ||
824 cmdentry.u.bltin != bltincmd)
825 break;
826 cmd_flags |= DO_NOFUNC;
827 argsused = parse_command_args(argc, argv, &use_syspath);
828 if (argsused == 0) {
829 /* use 'type' builting to display info */
830 cmdentry.u.bltin = typecmd;
831 break;
832 }
833 argc -= argsused;
834 argv += argsused;
835 if (use_syspath)
836 path = syspath() + 5;
837 } while (argc != 0);
838 if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
839 /* posix mandates that 'command <splbltin>' act as if
840 <splbltin> was a normal builtin */
841 cmdentry.cmdtype = CMDBUILTIN;
842 }
843
844 /* Fork off a child process if necessary. */
845 if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0)
846 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
847 || ((flags & EV_BACKCMD) != 0
848 && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
849 || cmdentry.u.bltin == dotcmd
850 || cmdentry.u.bltin == evalcmd))) {
851 INTOFF;
852 jp = makejob(cmd, 1);
853 mode = cmd->ncmd.backgnd;
854 if (flags & EV_BACKCMD) {
855 mode = FORK_NOJOB;
856 if (sh_pipe(pip) < 0)
857 error("Pipe call failed");
858 }
859 #ifdef DO_SHAREDVFORK
860 /* It is essential that if DO_SHAREDVFORK is defined that the
861 * child's address space is actually shared with the parent as
862 * we rely on this.
863 */
864 if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) {
865 pid_t pid;
866 int serrno;
867
868 savelocalvars = localvars;
869 localvars = NULL;
870 vforked = 1;
871 switch (pid = vfork()) {
872 case -1:
873 serrno = errno;
874 TRACE(("Vfork failed, errno=%d\n", serrno));
875 INTON;
876 error("Cannot vfork (%s)", strerror(serrno));
877 break;
878 case 0:
879 /* Make sure that exceptions only unwind to
880 * after the vfork(2)
881 */
882 if (setjmp(jmploc.loc)) {
883 if (exception == EXSHELLPROC) {
884 /* We can't progress with the vfork,
885 * so, set vforked = 2 so the parent
886 * knows, and _exit();
887 */
888 vforked = 2;
889 _exit(0);
890 } else {
891 _exit(exerrno);
892 }
893 }
894 savehandler = handler;
895 handler = &jmploc;
896 listmklocal(varlist.list, VEXPORT | VNOFUNC);
897 forkchild(jp, cmd, mode, vforked);
898 break;
899 default:
900 handler = savehandler; /* restore from vfork(2) */
901 poplocalvars();
902 localvars = savelocalvars;
903 if (vforked == 2) {
904 vforked = 0;
905
906 (void)waitpid(pid, NULL, 0);
907 /* We need to progress in a normal fork fashion */
908 goto normal_fork;
909 }
910 vforked = 0;
911 forkparent(jp, cmd, mode, pid);
912 goto parent;
913 }
914 } else {
915 normal_fork:
916 #endif
917 if (forkshell(jp, cmd, mode) != 0)
918 goto parent; /* at end of routine */
919 FORCEINTON;
920 #ifdef DO_SHAREDVFORK
921 }
922 #endif
923 if (flags & EV_BACKCMD) {
924 if (!vforked) {
925 FORCEINTON;
926 }
927 close(pip[0]);
928 if (pip[1] != 1) {
929 close(1);
930 copyfd(pip[1], 1, 1, 0);
931 close(pip[1]);
932 }
933 }
934 flags |= EV_EXIT;
935 }
936
937 /* This is the child process if a fork occurred. */
938 /* Execute the command. */
939 switch (cmdentry.cmdtype) {
940 case CMDFUNCTION:
941 #ifdef DEBUG
942 trputs("Shell function: "); trargs(argv);
943 #endif
944 redirect(cmd->ncmd.redirect, REDIR_PUSH);
945 saveparam = shellparam;
946 shellparam.malloc = 0;
947 shellparam.reset = 1;
948 shellparam.nparam = argc - 1;
949 shellparam.p = argv + 1;
950 shellparam.optnext = NULL;
951 INTOFF;
952 savelocalvars = localvars;
953 localvars = NULL;
954 INTON;
955 if (setjmp(jmploc.loc)) {
956 if (exception == EXSHELLPROC) {
957 freeparam((volatile struct shparam *)
958 &saveparam);
959 } else {
960 freeparam(&shellparam);
961 shellparam = saveparam;
962 }
963 poplocalvars();
964 localvars = savelocalvars;
965 handler = savehandler;
966 longjmp(handler->loc, 1);
967 }
968 savehandler = handler;
969 handler = &jmploc;
970 listmklocal(varlist.list, VEXPORT);
971 /* stop shell blowing its stack */
972 if (++funcnest > 1000)
973 error("too many nested function calls");
974 evaltree(cmdentry.u.func, flags & EV_TESTED);
975 funcnest--;
976 INTOFF;
977 poplocalvars();
978 localvars = savelocalvars;
979 freeparam(&shellparam);
980 shellparam = saveparam;
981 handler = savehandler;
982 popredir();
983 INTON;
984 if (evalskip == SKIPFUNC) {
985 evalskip = SKIPNONE;
986 skipcount = 0;
987 }
988 if (flags & EV_EXIT)
989 exitshell(exitstatus);
990 break;
991
992 case CMDBUILTIN:
993 case CMDSPLBLTIN:
994 #ifdef DEBUG
995 trputs("builtin command: "); trargs(argv);
996 #endif
997 mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
998 if (flags == EV_BACKCMD) {
999 memout.nleft = 0;
1000 memout.nextc = memout.buf;
1001 memout.bufsize = 64;
1002 mode |= REDIR_BACKQ;
1003 }
1004 e = -1;
1005 savehandler = handler;
1006 savecmdname = commandname;
1007 handler = &jmploc;
1008 temp_path = 0;
1009 if (!setjmp(jmploc.loc)) {
1010 /* We need to ensure the command hash table isn't
1011 * corruped by temporary PATH assignments.
1012 * However we must ensure the 'local' command works!
1013 */
1014 if (path != pathval() && (cmdentry.u.bltin == hashcmd ||
1015 cmdentry.u.bltin == typecmd)) {
1016 savelocalvars = localvars;
1017 localvars = 0;
1018 temp_path = 1;
1019 mklocal(path - 5 /* PATH= */, 0);
1020 }
1021 redirect(cmd->ncmd.redirect, mode);
1022
1023 /* exec is a special builtin, but needs this list... */
1024 cmdenviron = varlist.list;
1025 /* we must check 'readonly' flag for all builtins */
1026 listsetvar(varlist.list,
1027 cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
1028 commandname = argv[0];
1029 /* initialize nextopt */
1030 argptr = argv + 1;
1031 optptr = NULL;
1032 /* and getopt */
1033 optreset = 1;
1034 optind = 1;
1035 builtin_flags = flags;
1036 exitstatus = cmdentry.u.bltin(argc, argv);
1037 } else {
1038 e = exception;
1039 exitstatus = e == EXINT ? SIGINT + 128 :
1040 e == EXEXEC ? exerrno : 2;
1041 }
1042 handler = savehandler;
1043 flushall();
1044 out1 = &output;
1045 out2 = &errout;
1046 freestdout();
1047 if (temp_path) {
1048 poplocalvars();
1049 localvars = savelocalvars;
1050 }
1051 cmdenviron = NULL;
1052 if (e != EXSHELLPROC) {
1053 commandname = savecmdname;
1054 if (flags & EV_EXIT)
1055 exitshell(exitstatus);
1056 }
1057 if (e != -1) {
1058 if ((e != EXERROR && e != EXEXEC)
1059 || cmdentry.cmdtype == CMDSPLBLTIN)
1060 exraise(e);
1061 FORCEINTON;
1062 }
1063 if (cmdentry.u.bltin != execcmd)
1064 popredir();
1065 if (flags == EV_BACKCMD) {
1066 backcmd->buf = memout.buf;
1067 backcmd->nleft = memout.nextc - memout.buf;
1068 memout.buf = NULL;
1069 }
1070 break;
1071
1072 default:
1073 #ifdef DEBUG
1074 trputs("normal command: "); trargs(argv);
1075 #endif
1076 redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0);
1077 if (!vforked)
1078 for (sp = varlist.list ; sp ; sp = sp->next)
1079 setvareq(sp->text, VEXPORT|VSTACK);
1080 envp = environment();
1081 shellexec(argv, envp, path, cmdentry.u.index, vforked);
1082 break;
1083 }
1084 goto out;
1085
1086 parent: /* parent process gets here (if we forked) */
1087 if (mode == FORK_FG) { /* argument to fork */
1088 exitstatus = waitforjob(jp);
1089 } else if (mode == FORK_NOJOB) {
1090 backcmd->fd = pip[0];
1091 close(pip[1]);
1092 backcmd->jp = jp;
1093 }
1094 FORCEINTON;
1095
1096 out:
1097 if (lastarg)
1098 /* dsl: I think this is intended to be used to support
1099 * '_' in 'vi' command mode during line editing...
1100 * However I implemented that within libedit itself.
1101 */
1102 setvar("_", lastarg, 0);
1103 popstackmark(&smark);
1104 }
1105
1106
1107 /*
1108 * Search for a command. This is called before we fork so that the
1109 * location of the command will be available in the parent as well as
1110 * the child. The check for "goodname" is an overly conservative
1111 * check that the name will not be subject to expansion.
1112 */
1113
1114 STATIC void
1115 prehash(union node *n)
1116 {
1117 struct cmdentry entry;
1118
1119 if (n && n->type == NCMD && n->ncmd.args)
1120 if (goodname(n->ncmd.args->narg.text))
1121 find_command(n->ncmd.args->narg.text, &entry, 0,
1122 pathval());
1123 }
1124
1125 STATIC int
1126 in_function(void)
1127 {
1128 return funcnest;
1129 }
1130
1131 STATIC enum skipstate
1132 current_skipstate(void)
1133 {
1134 return evalskip;
1135 }
1136
1137 STATIC void
1138 stop_skipping(void)
1139 {
1140 evalskip = SKIPNONE;
1141 skipcount = 0;
1142 }
1143
1144 /*
1145 * Builtin commands. Builtin commands whose functions are closely
1146 * tied to evaluation are implemented here.
1147 */
1148
1149 /*
1150 * No command given.
1151 */
1152
1153 int
1154 bltincmd(int argc, char **argv)
1155 {
1156 /*
1157 * Preserve exitstatus of a previous possible redirection
1158 * as POSIX mandates
1159 */
1160 return back_exitstatus;
1161 }
1162
1163
1164 /*
1165 * Handle break and continue commands. Break, continue, and return are
1166 * all handled by setting the evalskip flag. The evaluation routines
1167 * above all check this flag, and if it is set they start skipping
1168 * commands rather than executing them. The variable skipcount is
1169 * the number of loops to break/continue, or the number of function
1170 * levels to return. (The latter is always 1.) It should probably
1171 * be an error to break out of more loops than exist, but it isn't
1172 * in the standard shell so we don't make it one here.
1173 */
1174
1175 int
1176 breakcmd(int argc, char **argv)
1177 {
1178 int n = argc > 1 ? number(argv[1]) : 1;
1179
1180 if (n > loopnest)
1181 n = loopnest;
1182 if (n > 0) {
1183 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
1184 skipcount = n;
1185 }
1186 return 0;
1187 }
1188
1189 int
1190 dotcmd(int argc, char **argv)
1191 {
1192 exitstatus = 0;
1193
1194 if (argc >= 2) { /* That's what SVR2 does */
1195 char *fullname;
1196 /*
1197 * dot_funcnest needs to be 0 when not in a dotcmd, so it
1198 * cannot be restored with (funcnest + 1).
1199 */
1200 int dot_funcnest_old;
1201 struct stackmark smark;
1202
1203 setstackmark(&smark);
1204 fullname = find_dot_file(argv[1]);
1205 setinputfile(fullname, 1);
1206 commandname = fullname;
1207 dot_funcnest_old = dot_funcnest;
1208 dot_funcnest = funcnest + 1;
1209 cmdloop(0);
1210 dot_funcnest = dot_funcnest_old;
1211 popfile();
1212 popstackmark(&smark);
1213 }
1214 return exitstatus;
1215 }
1216
1217 /*
1218 * Take commands from a file. To be compatible we should do a path
1219 * search for the file, which is necessary to find sub-commands.
1220 */
1221
1222 STATIC char *
1223 find_dot_file(char *basename)
1224 {
1225 char *fullname;
1226 const char *path = pathval();
1227 struct stat statb;
1228
1229 /* don't try this for absolute or relative paths */
1230 if (strchr(basename, '/'))
1231 return basename;
1232
1233 while ((fullname = padvance(&path, basename)) != NULL) {
1234 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
1235 /*
1236 * Don't bother freeing here, since it will
1237 * be freed by the caller.
1238 */
1239 return fullname;
1240 }
1241 stunalloc(fullname);
1242 }
1243
1244 /* not found in the PATH */
1245 error("%s: not found", basename);
1246 /* NOTREACHED */
1247 }
1248
1249
1250
1251 /*
1252 * The return command.
1253 *
1254 * Quoth the POSIX standard:
1255 * The return utility shall cause the shell to stop executing the current
1256 * function or dot script. If the shell is not currently executing
1257 * a function or dot script, the results are unspecified.
1258 *
1259 * As for the unspecified part, there seems to be no de-facto standard: bash
1260 * ignores the return with a warning, zsh ignores the return in interactive
1261 * mode but seems to liken it to exit in a script. (checked May 2014)
1262 *
1263 * We choose to silently ignore the return. Older versions of this shell
1264 * set evalskip to SKIPFILE causing the shell to (indirectly) exit. This
1265 * had at least the problem of circumventing the check for stopped jobs,
1266 * which would occur for exit or ^D.
1267 */
1268
1269 int
1270 returncmd(int argc, char **argv)
1271 {
1272 int ret = argc > 1 ? number(argv[1]) : exitstatus;
1273
1274 if ((dot_funcnest == 0 && funcnest)
1275 || (dot_funcnest > 0 && funcnest - (dot_funcnest - 1) > 0)) {
1276 evalskip = SKIPFUNC;
1277 skipcount = 1;
1278 } else if (dot_funcnest > 0) {
1279 evalskip = SKIPFILE;
1280 skipcount = 1;
1281 } else {
1282 /* XXX: should a warning be issued? */
1283 ret = 0;
1284 }
1285
1286 return ret;
1287 }
1288
1289
1290 int
1291 falsecmd(int argc, char **argv)
1292 {
1293 return 1;
1294 }
1295
1296
1297 int
1298 truecmd(int argc, char **argv)
1299 {
1300 return 0;
1301 }
1302
1303
1304 int
1305 execcmd(int argc, char **argv)
1306 {
1307 if (argc > 1) {
1308 struct strlist *sp;
1309
1310 iflag = 0; /* exit on error */
1311 mflag = 0;
1312 optschanged();
1313 for (sp = cmdenviron; sp; sp = sp->next)
1314 setvareq(sp->text, VEXPORT|VSTACK);
1315 shellexec(argv + 1, environment(), pathval(), 0, 0);
1316 }
1317 return 0;
1318 }
1319
1320 static int
1321 conv_time(clock_t ticks, char *seconds, size_t l)
1322 {
1323 static clock_t tpm = 0;
1324 clock_t mins;
1325 int i;
1326
1327 if (!tpm)
1328 tpm = sysconf(_SC_CLK_TCK) * 60;
1329
1330 mins = ticks / tpm;
1331 snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );
1332
1333 if (seconds[0] == '6' && seconds[1] == '0') {
1334 /* 59.99995 got rounded up... */
1335 mins++;
1336 strlcpy(seconds, "0.0", l);
1337 return mins;
1338 }
1339
1340 /* suppress trailing zeros */
1341 i = strlen(seconds) - 1;
1342 for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)
1343 seconds[i] = 0;
1344 return mins;
1345 }
1346
1347 int
1348 timescmd(int argc, char **argv)
1349 {
1350 struct tms tms;
1351 int u, s, cu, cs;
1352 char us[8], ss[8], cus[8], css[8];
1353
1354 nextopt("");
1355
1356 times(&tms);
1357
1358 u = conv_time(tms.tms_utime, us, sizeof(us));
1359 s = conv_time(tms.tms_stime, ss, sizeof(ss));
1360 cu = conv_time(tms.tms_cutime, cus, sizeof(cus));
1361 cs = conv_time(tms.tms_cstime, css, sizeof(css));
1362
1363 outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",
1364 u, us, s, ss, cu, cus, cs, css);
1365
1366 return 0;
1367 }
1368