svn commit: r199647 - in head: bin/sh tools/regression/bin/sh/builtins

Jilles Tjoelker jilles at FreeBSD.org
Sun Nov 22 14:04:21 UTC 2009


Author: jilles
Date: Sun Nov 22 14:04:20 2009
New Revision: 199647
URL: http://svn.freebsd.org/changeset/base/199647

Log:
  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.

Added:
  head/tools/regression/bin/sh/builtins/fc1.0   (contents, props changed)
Modified:
  head/bin/sh/eval.c
  head/bin/sh/input.c
  head/bin/sh/input.h

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c	Sun Nov 22 12:19:50 2009	(r199646)
+++ head/bin/sh/eval.c	Sun Nov 22 14:04:20 2009	(r199647)
@@ -593,6 +593,7 @@ evalcommand(union node *cmd, int flags, 
 	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, 
 			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)

Modified: head/bin/sh/input.c
==============================================================================
--- head/bin/sh/input.c	Sun Nov 22 12:19:50 2009	(r199646)
+++ head/bin/sh/input.c	Sun Nov 22 14:04:20 2009	(r199647)
@@ -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.
  */
 

Modified: head/bin/sh/input.h
==============================================================================
--- head/bin/sh/input.h	Sun Nov 22 12:19:50 2009	(r199646)
+++ head/bin/sh/input.h	Sun Nov 22 14:04:20 2009	(r199647)
@@ -45,6 +45,8 @@ extern int parsenleft;		/* number of cha
 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);
 

Added: head/tools/regression/bin/sh/builtins/fc1.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/fc1.0	Sun Nov 22 14:04:20 2009	(r199647)
@@ -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}


More information about the svn-src-all mailing list