aboutsummaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2009-11-22 14:04:20 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2009-11-22 14:04:20 +0000
commiteaa3489312d377f27befcc40ebfc8f9e0460c0b9 (patch)
tree0ba1f228ffeefae0838e106fccaf6a76f2040cce /bin
parent301f81f0fbdbfb17ba5394898821af4f0b60b1b5 (diff)
downloadsrc-eaa3489312d377f27befcc40ebfc8f9e0460c0b9.tar.gz
src-eaa3489312d377f27befcc40ebfc8f9e0460c0b9.zip
sh: Ensure the same command input file is on top after executing a builtin.
This avoids weirdness when 'fc -e vi' or the like is done and there is a syntax error in the file. Formerly an interactive shell tried to execute stuff after the syntax error and exited. This should also avoid similar issues with 'command eval' and 'command .' when 'command' is implemented properly as in NetBSD sh. Special builtins did not have this problem since errors in them cause the shell to exit or to reset various state such as the current command input file.
Notes
Notes: svn path=/head/; revision=199647
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/eval.c3
-rw-r--r--bin/sh/input.c26
-rw-r--r--bin/sh/input.h4
3 files changed, 33 insertions, 0 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 5ba244d76e41..81de2d79e0f5 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 3d8f90c821c0..548ae92544e5 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 4d57b3bf0518..067d01197887 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);