From 76aef28b3147fb5ea944c793452e2d5ca3b348fe Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 15 Jul 2010 18:44:12 +0000 Subject: 28073: allow #! scripts to search path if interpreter not found --- ChangeLog | 7 ++++++- Src/exec.c | 7 +++++++ Src/init.c | 20 +------------------- Src/utils.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea4e3673d..600a859d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-07-15 Peter Stephenson + + * 28073: Src/exec.c, Src/init.c, Src/utils.c: allow #! + scripts to search path if interpreter not found. + 2010-07-15 Doug Kearns * 28078: Completion/Unix/Command/_xmlsoft: update. @@ -13374,5 +13379,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5025 $ +* $Revision: 1.5026 $ ***************************************************** diff --git a/Src/exec.c b/Src/exec.c index 6611e9c79..73b4c01a8 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -461,8 +461,15 @@ zexecve(char *pth, char **argv, char **newenvp) for (ptr = execvebuf + 2; *ptr && *ptr == ' '; ptr++); for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++); if (eno == ENOENT) { + char *pprog; if (*ptr) *ptr = '\0'; + if (*ptr2 != '/' && + (pprog = pathprog(ptr2, NULL))) { + argv[-2] = ptr2; + argv[-1] = ptr + 1; + execve(pprog, argv - 2, newenvp); + } zerr("%s: bad interpreter: %s: %e", pth, ptr2, eno); } else if (*ptr) { diff --git a/Src/init.c b/Src/init.c index 06f177725..e85d3875a 100644 --- a/Src/init.c +++ b/Src/init.c @@ -949,25 +949,7 @@ setupshin(char *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; - } - } + funmeta = pathprog(runscript, &sfname); } if (!sfname || (SHIN = movefd(open(funmeta, O_RDONLY | O_NOCTTY))) diff --git a/Src/utils.c b/Src/utils.c index 379f9f738..f311abd05 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -606,6 +606,44 @@ zwcwidth(wint_t wc) /**/ #endif /* MULTIBYTE_SUPPORT */ +/* + * Search the path for prog and return the file name. + * The returned value is unmetafied and in the unmeta storage + * area (N.B. should be duplicated if not used immediately and not + * equal to *namep). + * + * If namep is not NULL, *namep is set to the metafied programme + * name, which is in heap storage. + */ +/**/ +char * +pathprog(char *prog, char **namep) +{ + char **pp, ppmaxlen = 0, *buf, *funmeta; + struct stat st; + + for (pp = path; *pp; pp++) + { + int len = strlen(*pp); + if (len > ppmaxlen) + ppmaxlen = len; + } + buf = zhalloc(ppmaxlen + strlen(prog) + 2); + for (pp = path; *pp; pp++) { + sprintf(buf, "%s/%s", *pp, prog); + funmeta = unmeta(buf); + if (access(funmeta, F_OK) == 0 && + stat(funmeta, &st) >= 0 && + !S_ISDIR(st.st_mode)) { + if (namep) + *namep = buf; + return funmeta; + } + } + + return NULL; +} + /* get a symlink-free pathname for s relative to PWD */ /**/ -- cgit 1.4.1