summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/sh/eval.c3
-rw-r--r--bin/sh/input.c26
-rw-r--r--bin/sh/input.h4
-rw-r--r--tools/regression/bin/sh/builtins/fc1.027
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}
OpenPOWER on IntegriCloud