diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 8554943e889d..5cee55e90d95 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -74,11 +74,6 @@ __FBSDID("$FreeBSD$"); #endif -/* flags in argument to evaltree */ -#define EV_EXIT 01 /* exit after evaluating tree */ -#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ -#define EV_BACKCMD 04 /* command executing within back quotes */ - MKINIT int evalskip; /* set if we are skipping commands */ STATIC int skipcount; /* number of levels to skip */ MKINIT int loopnest; /* current loop nesting level */ @@ -163,20 +158,28 @@ evalstring(char *s, int flags) { union node *n; struct stackmark smark; + int flags_exit; + flags_exit = flags & EV_EXIT; + flags &= ~EV_EXIT; setstackmark(&smark); setinputstring(s, 1); while ((n = parsecmd(0)) != NEOF) { - if (n != NULL) - evaltree(n, flags); + if (n != NULL) { + if (flags_exit && preadateof()) + evaltree(n, flags | EV_EXIT); + else + evaltree(n, flags); + } popstackmark(&smark); } popfile(); popstackmark(&smark); + if (flags_exit) + exitshell(exitstatus); } - /* * Evaluate a parse tree. The value is left in the global variable * exitstatus. diff --git a/bin/sh/eval.h b/bin/sh/eval.h index 11f74702ab20..c82585ea888f 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -45,6 +45,11 @@ struct backcmd { /* result of evalbackcmd */ struct job *jp; /* job structure for command */ }; +/* flags in argument to evaltree/evalstring */ +#define EV_EXIT 01 /* exit after evaluating tree */ +#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ +#define EV_BACKCMD 04 /* command executing within back quotes */ + int evalcmd(int, char **); void evalstring(char *, int); union node; /* BLETCH for ansi C */ diff --git a/bin/sh/input.c b/bin/sh/input.c index 81c1f0b77cc9..c97c49665a93 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -320,6 +320,23 @@ check: return *parsenextc++; } +/* + * Returns if we are certain we are at EOF. Does not cause any more input + * to be read from the outside world. + */ + +int +preadateof(void) +{ + if (parsenleft > 0) + return 0; + if (parsefile->strpush) + return 0; + if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) + return 1; + return 0; +} + /* * Undo the last call to pgetc. Only one character may be pushed back. * PEOF may be pushed back. diff --git a/bin/sh/input.h b/bin/sh/input.h index 0d188c5850dc..4d57b3bf0518 100644 --- a/bin/sh/input.h +++ b/bin/sh/input.h @@ -48,6 +48,7 @@ extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */ char *pfgets(char *, int); int pgetc(void); int preadbuffer(void); +int preadateof(void); void pungetc(void); void pushstring(char *, int, void *); void popstring(void); diff --git a/bin/sh/main.c b/bin/sh/main.c index 77526b569ea1..85a6d20ee457 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -178,7 +178,7 @@ state2: state3: state = 4; if (minusc) { - evalstring(minusc, 0); + evalstring(minusc, sflag ? 0 : EV_EXIT); } if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */