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