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