about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-03-16 09:43:51 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-03-16 09:43:51 +0000
commit53745d8df0a6e00d2ddf1c08f7ea71820d587673 (patch)
tree8cbc8ea34d3c9d26dcc8428b2652ac8df3f2859d
parent1b68e0ea00deb508b394f1c0a4413205e621c293 (diff)
downloadzsh-53745d8df0a6e00d2ddf1c08f7ea71820d587673.tar.gz
zsh-53745d8df0a6e00d2ddf1c08f7ea71820d587673.tar.xz
zsh-53745d8df0a6e00d2ddf1c08f7ea71820d587673.zip
27793 and follow ups: add PATH_SCRIPT option to find script using $PATH
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/invoke.yo14
-rw-r--r--Doc/Zsh/options.yo14
-rw-r--r--Src/init.c104
-rw-r--r--Src/options.c1
-rw-r--r--Src/zsh.h1
-rw-r--r--Test/A01grammar.ztst18
7 files changed, 136 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 9fbed5276..f8ecd456d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2010-03-16  Peter Stephenson  <pws@csr.com>
+
+	* 27793 plus 27794, 27795: Doc/Zsh/invoke.yo, Doc/Zsh/options.yo,
+	Src/init.c, Src/options.c, Src/zsh.h, Test/A01grammar.ztst:
+	add PATH_SCRIPT option to find script using path.
+
 2010-03-15  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* Mikael: 27797: Completion/Base/Completer/_expand_alias:
@@ -12903,5 +12909,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4931 $
+* $Revision: 1.4932 $
 *****************************************************
diff --git a/Doc/Zsh/invoke.yo b/Doc/Zsh/invoke.yo
index 01e9b00e6..e03c1e25b 100644
--- a/Doc/Zsh/invoke.yo
+++ b/Doc/Zsh/invoke.yo
@@ -1,7 +1,7 @@
 texinode(Invocation)(Files)(Roadmap)(Top)
 chapter(Invocation)
 cindex(invocation)
-sect(Invocation Options)
+sect(Invocation)
 cindex(shell options)
 cindex(options, shell)
 cindex(shell flags)
@@ -17,7 +17,8 @@ first one is assigned to tt($0), rather than being used as a positional
 parameter.
 )
 item(tt(-i))(
-Force shell to be interactive.
+Force shell to be interactive.  It is still possible to specify a
+script to execute.
 )
 item(tt(-s))(
 Force shell to read commands from the standard input.
@@ -27,6 +28,15 @@ execute.
 )
 enditem()
 
+If there are any remaining arguments after option processing, and neither
+of the options tt(-c) or tt(-s) was supplied, the first argument is taken
+as the file name of a script containing shell commands to be executed.  If
+the option tt(PATH_SCRIPT) is set, and the file name does not contain a
+directory path (i.e. there is no `tt(/)' in the name), first the current
+directory and then the command path given by the variable tt(PATH) are
+searched for the script.  If the option is not set or the file name
+contains a `tt(/)' it is used directly.
+
 After the first one or two arguments have been appropriated as described above,
 the remaining arguments are assigned to the positional parameters.
 
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index e0934ff3d..003071aab 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1138,6 +1138,20 @@ executables specified in this form.  This takes place before any search
 indicated by this option, and regardless of whether `tt(.)' or the current
 directory appear in the command search path.
 )
+pindex(PATH_SCRIPT)
+pindex(NO_PATH_SCRIPT)
+pindex(PATHSCRIPT)
+pindex(NOPATHSCRIPT)
+cindex(path search, for script argument to shell)
+item(tt(PATH_SCRIPT) <K> <S>)(
+If this option is not set, a script passed as the first non-option argument
+to the shell must contain the name of the file to open.  If this
+option is set, and the script does not specify a directory path,
+the script is looked for first in the current directory, then in the
+command path.  See
+ifnzman(noderef(Invocation))\
+ifzman(the section INVOCATION in zmanref(zshmisc)).
+)
 pindex(PRINT_EIGHT_BIT)
 pindex(NO_PRINT_EIGHT_BIT)
 pindex(PRINTEIGHTBIT)
diff --git a/Src/init.c b/Src/init.c
index c65c4aaad..56c8c1822 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -219,8 +219,8 @@ static char *cmd;
 static int restricted;
 
 /**/
-void
-parseargs(char **argv)
+static void
+parseargs(char **argv, char **runscript)
 {
     int optionbreak = 0;
     char **x;
@@ -335,15 +335,11 @@ parseargs(char **argv)
     }
     if (*argv) {
 	if (unset(SHINSTDIN)) {
-	    if (!cmd)
-		SHIN = movefd(open(unmeta(*argv), O_RDONLY | O_NOCTTY));
-	    if (SHIN == -1) {
-		zerr("can't open input file: %s", *argv);
-		exit(127);
-	    }
+	    if (cmd)
+		argzero = *argv;
+	    else
+		*runscript = *argv;
 	    opts[INTERACTIVE] &= 1;
-	    argzero = *argv;
-	    scriptfilename = argzero;
 	    argv++;
 	}
 	while (*argv)
@@ -737,7 +733,6 @@ setupvals(void)
     zero_mnumber.type = MN_INTEGER;
     zero_mnumber.u.l = 0;
 
-    lineno = 1;
     noeval = 0;
     curhist = 0;
     histsiz = DEFAULT_HISTSIZE;
@@ -915,14 +910,6 @@ setupvals(void)
     hsubl = hsubr = NULL;
     lastpid = 0;
     lastpid_status = -1L;
-    bshin = SHIN ? fdopen(SHIN, "r") : stdin;
-    if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) {
-#ifdef _IONBF
-	setvbuf(stdin, NULL, _IONBF, 0);
-#else
-	setlinebuf(stdin);
-#endif
-    }
 
     get_usage();
 
@@ -935,6 +922,78 @@ setupvals(void)
     set_default_colour_sequences();
 }
 
+/*
+ * Setup shell input, opening any script file (runscript, may be NULL).
+ * This is deferred until we have a path to search, in case
+ * PATHSCRIPT is set for sh-compatible behaviour.
+ */
+static void
+setupshin(char *runscript)
+{
+    if (runscript) {
+	char *funmeta, *sfname = NULL;
+	struct stat st;
+
+	funmeta = unmeta(runscript);
+	/*
+	 * Always search the current directory first.
+	 */
+	if (access(funmeta, F_OK) == 0 &&
+	    stat(funmeta, &st) >= 0 &&
+	    !S_ISDIR(st.st_mode))
+	    sfname = runscript;
+	else if (isset(PATHSCRIPT) && !strchr(runscript, '/')) {
+	    /*
+	     * With the PATHSCRIPT option, search the path if no
+	     * path was given in the script name.
+	     */
+	    char **pp, ppmaxlen = 0, *buf;
+	    for (pp = path; *pp; pp++)
+	    {
+		int len = strlen(*pp);
+		if (len > ppmaxlen)
+		    ppmaxlen = len;
+	    }
+	    buf = zhalloc(ppmaxlen + strlen(runscript) + 2);
+	    for (pp = path; *pp; pp++) {
+		sprintf(buf, "%s/%s", *pp, runscript);
+		/* careful, static buffer used in open() later */
+		funmeta = unmeta(buf);
+		if (access(funmeta, F_OK) == 0 &&
+		    stat(funmeta, &st) >= 0 &&
+		    !S_ISDIR(st.st_mode)) {
+		    sfname = buf;
+		    break;
+		}
+	    }
+	}
+	if (!sfname ||
+	    (SHIN = movefd(open(funmeta, O_RDONLY | O_NOCTTY)))
+	    == -1) {
+	    zerr("can't open input file: %s", runscript);
+	    exit(127);
+	}
+	scriptfilename = sfname;
+	argzero = runscript;
+    }
+    /*
+     * We only initialise line numbering once there is a script to
+     * read commands from.
+     */
+    lineno = 1;
+    /*
+     * Finish setting up SHIN and its relatives.
+     */
+    bshin = SHIN ? fdopen(SHIN, "r") : stdin;
+    if (isset(SHINSTDIN) && !SHIN && unset(INTERACTIVE)) {
+#ifdef _IONBF
+	setvbuf(stdin, NULL, _IONBF, 0);
+#else
+	setlinebuf(stdin);
+#endif
+    }
+}
+
 /* Initialize signal handling */
 
 /**/
@@ -1389,7 +1448,7 @@ mod_export int use_exit_printed;
 mod_export int
 zsh_main(UNUSED(int argc), char **argv)
 {
-    char **t;
+    char **t, *runscript = NULL;
     int t0;
 #ifdef USE_LOCALE
     setlocale(LC_ALL, "");
@@ -1437,15 +1496,18 @@ zsh_main(UNUSED(int argc), char **argv)
     opts[LOGINSHELL] = (**argv == '-');
     opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
     opts[USEZLE] = 1;   /* may be unset in init_io() */
-    parseargs(argv);   /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
+    /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
+    parseargs(argv, &runscript);
 
     SHTTY = -1;
     init_io();
     setupvals();
+
     init_signals();
     init_bltinmods();
     init_builtins();
     run_init_scripts();
+    setupshin(runscript);
     init_misc();
 
     for (;;) {
diff --git a/Src/options.c b/Src/options.c
index 705546699..dedbf0c73 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -198,6 +198,7 @@ static struct optname optns[] = {
 {{NULL, "octalzeroes",        OPT_EMULATE|OPT_SH},	 OCTALZEROES},
 {{NULL, "overstrike",	      0},			 OVERSTRIKE},
 {{NULL, "pathdirs",	      OPT_EMULATE},		 PATHDIRS},
+{{NULL, "pathscript",	      OPT_EMULATE|OPT_BOURNE},	 PATHSCRIPT},
 {{NULL, "posixaliases",       OPT_EMULATE|OPT_BOURNE},	 POSIXALIASES},
 {{NULL, "posixbuiltins",      OPT_EMULATE|OPT_BOURNE},	 POSIXBUILTINS},
 {{NULL, "posixcd",            OPT_EMULATE|OPT_BOURNE},	 POSIXCD},
diff --git a/Src/zsh.h b/Src/zsh.h
index df7e251b9..1b1175cb2 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1977,6 +1977,7 @@ enum {
     OCTALZEROES,
     OVERSTRIKE,
     PATHDIRS,
+    PATHSCRIPT,
     POSIXALIASES,
     POSIXBUILTINS,
     POSIXCD,
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index 3b3f2f915..94836b4e2 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -559,3 +559,21 @@
   . ./dot_status
 0:"." file sees status from previous command
 >1
+
+  mkdir test_path_script
+  print "#!/bin/sh\necho Found the script." >test_path_script/myscript
+  chmod u+x test_path_script/myscript
+  path=($PWD/test_path_script $path)
+  export PATH
+  $ZTST_testdir/../Src/zsh -f -o pathscript myscript
+0:PATHSCRIPT option
+>Found the script.
+
+  $ZTST_testdir/../Src/zsh -f myscript
+127q:PATHSCRIPT option not used.
+?$ZTST_testdir/../Src/zsh: can't open input file: myscript
+
+  $ZTST_testdir/../Src/zsh -c 'echo $0; echo $1' myargzero myargone
+0:$0 is traditionally if bizarrely set to the first argument with -c
+>myargzero
+>myargone