From 53745d8df0a6e00d2ddf1c08f7ea71820d587673 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 16 Mar 2010 09:43:51 +0000 Subject: 27793 and follow ups: add PATH_SCRIPT option to find script using $PATH --- ChangeLog | 8 +++- Doc/Zsh/invoke.yo | 14 ++++++- Doc/Zsh/options.yo | 14 +++++++ Src/init.c | 104 ++++++++++++++++++++++++++++++++++++++++----------- Src/options.c | 1 + Src/zsh.h | 1 + Test/A01grammar.ztst | 18 +++++++++ 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 + + * 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 * 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) )( +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 -- cgit 1.4.1