diff options
-rw-r--r-- | bin/sh/eval.c | 3 | ||||
-rw-r--r-- | bin/sh/input.c | 26 | ||||
-rw-r--r-- | bin/sh/input.h | 4 | ||||
-rw-r--r-- | tools/regression/bin/sh/builtins/fc1.0 | 27 |
4 files changed, 60 insertions, 0 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 5ba244d..81de2d7 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -593,6 +593,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) char *savecmdname; struct shparam saveparam; struct localvar *savelocalvars; + struct parsefile *savetopfile; volatile int e; char *lastarg; int realstatus; @@ -833,6 +834,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) mode |= REDIR_BACKQ; } savecmdname = commandname; + savetopfile = getcurrentfile(); cmdenviron = varlist.list; e = -1; savehandler = handler; @@ -867,6 +869,7 @@ cmddone: if ((e != EXERROR && e != EXEXEC) || cmdentry.special) exraise(e); + popfilesupto(savetopfile); FORCEINTON; } if (cmdentry.u.index != EXECCMD) diff --git a/bin/sh/input.c b/bin/sh/input.c index 3d8f90c..548ae92 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -509,6 +509,32 @@ popfile(void) /* + * Return current file (to go back to it later using popfilesupto()). + */ + +struct parsefile * +getcurrentfile(void) +{ + return parsefile; +} + + +/* + * Pop files until the given file is on top again. Useful for regular + * builtins that read shell commands from files or strings. + * If the given file is not an active file, an error is raised. + */ + +void +popfilesupto(struct parsefile *file) +{ + while (parsefile != file && parsefile != &basepf) + popfile(); + if (parsefile != file) + error("popfilesupto() misused"); +} + +/* * Return to top level. */ diff --git a/bin/sh/input.h b/bin/sh/input.h index 4d57b3b..067d011 100644 --- a/bin/sh/input.h +++ b/bin/sh/input.h @@ -45,6 +45,8 @@ extern int parsenleft; /* number of characters left in input buffer */ extern char *parsenextc; /* next character in input buffer */ extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */ +struct parsefile; + char *pfgets(char *, int); int pgetc(void); int preadbuffer(void); @@ -56,6 +58,8 @@ void setinputfile(char *, int); void setinputfd(int, int); void setinputstring(char *, int); void popfile(void); +struct parsefile *getcurrentfile(void); +void popfilesupto(struct parsefile *); void popallfiles(void); void closescript(void); diff --git a/tools/regression/bin/sh/builtins/fc1.0 b/tools/regression/bin/sh/builtins/fc1.0 new file mode 100644 index 0000000..54536ca --- /dev/null +++ b/tools/regression/bin/sh/builtins/fc1.0 @@ -0,0 +1,27 @@ +# $FreeBSD$ +set -e +trap 'echo Broken pipe -- test failed' pipe + +P=${TMPDIR:-/tmp} +cd $P +T=$(mktemp -d sh-test.XXXXXX) +cd $T + +mkfifo input output error +HISTFILE=/dev/null sh -i <input >output 2>error & +{ + # Syntax error + echo ')' >&3 + # Read error message, shell will read new input now + read dummy <&5 + # Execute bad command again + echo 'fc -e true' >&3 + # Verify that the shell is still running + echo 'echo continued' >&3 || rc=3 + echo 'exit' >&3 || rc=3 + read line <&4 && [ "$line" = continued ] && : ${rc:=0} +} 3>input 4<output 5<error + +rm input output error +rmdir ${P}/${T} +exit ${rc:-3} |