Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zsh bug in . builtin



On Wed, 01 Jul 2009 07:14:54 -0600
Eric Blake <ebb9@xxxxxxx> wrote:
> However, zsh fails to recognize syntax errors encountered when sourcing a
> file (tested with zsh 4.3.9):
> 
> $ echo 'if' > tmp
> $ zsh -c '. ./tmp; echo $?'
> 0
> $ zsh -c 'emulate sh; . ./tmp; echo $?'
> ./tmp:2: parse error near `\n'
> 0
> $ zsh -c 'emulate sh; (. ./tmp); echo $?'
> ./tmp:2: parse error near `\n'
> 0

Those are all bugs; it's not supposed to ignore errors even in native mode.
I've taken 128 to mean failed to execute file, 129 to mean failed to find
file---anyone can suggest better values if unhappy.

Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.121
diff -u -r1.121 builtins.yo
--- Doc/Zsh/builtins.yo	2 Mar 2009 10:12:14 -0000	1.121
+++ Doc/Zsh/builtins.yo	1 Jul 2009 14:21:45 -0000
@@ -46,7 +46,9 @@
 If any arguments var(arg) are given,
 they become the positional parameters; the old positional
 parameters are restored when the var(file) is done executing.
-The exit status is the exit status of the last command executed.
+If var(file) was not found the return status is 129; if var(file) was found
+but contained a syntax error the return status is 128; else the return
+status is the exit status of the last command executed.
 )
 findex(NOTRANS(:))
 cindex(expanding parameters)
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.228
diff -u -r1.228 builtin.c
--- Src/builtin.c	1 Jul 2009 09:07:08 -0000	1.228
+++ Src/builtin.c	1 Jul 2009 14:21:45 -0000
@@ -4701,9 +4701,10 @@
 bin_dot(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 {
     char **old, *old0 = NULL;
-    int ret, diddot = 0, dotdot = 0;
+    int diddot = 0, dotdot = 0;
     char *s, **t, *enam, *arg0, *buf;
     struct stat st;
+    enum source_return ret;
 
     if (!*argv)
 	return 0;
@@ -4719,14 +4720,14 @@
     }
     s = unmeta(enam);
     errno = ENOENT;
-    ret = 1;
+    ret = SOURCE_NOT_FOUND;
     /* for source only, check in current directory first */
     if (*name != '.' && access(s, F_OK) == 0
 	&& stat(s, &st) >= 0 && !S_ISDIR(st.st_mode)) {
 	diddot = 1;
 	ret = source(enam);
     }
-    if (ret) {
+    if (ret == SOURCE_NOT_FOUND) {
 	/* use a path with / in it */
 	for (s = arg0; *s; s++)
 	    if (*s == '/') {
@@ -4739,7 +4740,8 @@
 		ret = source(arg0);
 		break;
 	    }
-	if (!*s || (ret && isset(PATHDIRS) && diddot < 2 && dotdot == 0)) {
+	if (!*s || (ret == SOURCE_NOT_FOUND &&
+		    isset(PATHDIRS) && diddot < 2 && dotdot == 0)) {
 	    pushheap();
 	    /* search path for script */
 	    for (t = path; *t; t++) {
@@ -4766,12 +4768,12 @@
 	freearray(pparams);
 	pparams = old;
     }
-    if (ret)
+    if (ret == SOURCE_NOT_FOUND)
 	zwarnnam(name, "%e: %s", errno, enam);
     zsfree(arg0);
     if (old0)
 	argzero = old0;
-    return ret ? ret : lastval;
+    return ret == SOURCE_OK ? lastval : 127 + ret;
 }
 
 /*
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.100
diff -u -r1.100 init.c
--- Src/init.c	9 Mar 2009 15:57:59 -0000	1.100
+++ Src/init.c	1 Jul 2009 14:21:45 -0000
@@ -99,10 +99,11 @@
 /* keep executing lists until EOF found */
 
 /**/
-void
+int
 loop(int toplevel, int justonce)
 {
     Eprog prog;
+    int err;
 
     pushheap();
     if (!toplevel)
@@ -201,9 +202,12 @@
 	if (justonce)
 	    break;
     }
+    err = errflag;
     if (!toplevel)
 	lexrestore();
     popheap();
+
+    return err;
 }
 
 static char *cmd;
@@ -1049,10 +1053,13 @@
 	readhistfile(NULL, 0, HFILE_USE_OPTIONS);
 }
 
-/* source a file */
+/*
+ * source a file
+ * Returns one of the SOURCE_* enum values.
+ */
 
 /**/
-mod_export int
+mod_export enum source_return
 source(char *s)
 {
     Eprog prog;
@@ -1066,11 +1073,12 @@
     int ocsp;
     int otrap_return = trap_return, otrap_state = trap_state;
     struct funcstack fstack;
+    enum source_return ret = SOURCE_OK;
 
     if (!s || 
 	(!(prog = try_source_file((us = unmeta(s)))) &&
 	 (tempfd = movefd(open(us, O_RDONLY | O_NOCTTY))) == -1)) {
-	return 1;
+	return SOURCE_NOT_FOUND;
     }
 
     /* save the current shell state */
@@ -1121,8 +1129,13 @@
 	errflag = 0;
 	execode(prog, 1, 0);
 	popheap();
-    } else
-	loop(0, 0);		     /* loop through the file to be sourced  */
+	if (errflag)
+	    ret = SOURCE_ERROR;
+    } else {
+	/* loop through the file to be sourced  */
+	if (loop(0, 0))
+	    ret = SOURCE_ERROR;
+    }
     funcstack = funcstack->prev;
     sourcelevel--;
 
@@ -1152,7 +1165,7 @@
     cmdstack = ocs;
     cmdsp = ocsp;
 
-    return 0;
+    return ret;
 }
 
 /* Try to source a file in the home directory */
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.156
diff -u -r1.156 zsh.h
--- Src/zsh.h	5 Jun 2009 11:15:53 -0000	1.156
+++ Src/zsh.h	1 Jul 2009 14:21:45 -0000
@@ -1725,6 +1725,17 @@
 #define PRINT_WHENCE_FUNCDEF	(1<<9)
 #define PRINT_WHENCE_WORD	(1<<10)
 
+/* Return values from source() */
+
+enum source_return {
+    /* Source ran OK */
+    SOURCE_OK = 0,
+    /* Internal error sourcing file */
+    SOURCE_ERROR = 1,
+    /* File not found */
+    SOURCE_NOT_FOUND = 2
+};
+
 /***********************************/
 /* Definitions for history control */
 /***********************************/
Index: Src/Modules/newuser.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/newuser.c,v
retrieving revision 1.7
diff -u -r1.7 newuser.c
--- Src/Modules/newuser.c	11 Feb 2009 20:42:17 -0000	1.7
+++ Src/Modules/newuser.c	1 Jul 2009 14:21:45 -0000
@@ -97,7 +97,7 @@
 	VARARR(char, buf, strlen(*sp) + 9);
 	sprintf(buf, "%s/newuser", *sp);
 
-	if (!source(buf))
+	if (source(buf) != SOURCE_NOT_FOUND)
 	    break;
     }
 
Index: Test/A01grammar.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v
retrieving revision 1.19
diff -u -r1.19 A01grammar.ztst
--- Test/A01grammar.ztst	21 Apr 2009 10:38:00 -0000	1.19
+++ Test/A01grammar.ztst	1 Jul 2009 14:21:45 -0000
@@ -514,4 +514,11 @@
 >value
 >not#comment
 
-  
+  . ./nonexistent
+129: Attempt to "." non-existent file.
+?(eval):.:1: no such file or directory: ./nonexistent
+
+  echo '[[' >bad_syntax
+  . ./bad_syntax
+128: Attempt to "." file with bad syntax.
+?./bad_syntax:2: parse error near `\n'

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



Messages sorted by: Reverse Date, Date, Thread, Author