Re: [PATCH] findprog: Support searching in a specified path string
Hi Paul, > note that > on Windows, which is the only place this matters, so far, IIRC it is > illegal to use "prog.exe.exe" so if an extension is already provided > the system won't search again Indeed, the native Windows execlp() function behaves like this: - If the caller specifies "prog.exe.exe" or "prog.foo.exe" and that file will be exists, it will be found and executed. - If the caller specifies "prog.exe" or "prog.foo" but that file does not exist, the search will NOT extend to "prog.exe.exe" or "prog.foo.exe", respectively. I'm updating the code (patch below). > I actually don't see any need for this optimization, especially > compared to the added complexity of the API and docs: the suffix check > needs to be done somewhere after all. But on platforms like Cygwin, it would be done twice. 2019-09-14 Bruno Haible findprog-in: Better mimic the system on native Windows. Reported by Paul Smith . * lib/findprog-in.c (find_in_given_path): On native Windows, don't try non-empty suffixes when the file name already contains a '.'. diff --git a/lib/findprog-in.c b/lib/findprog-in.c index 99b3c31..d601e06 100644 --- a/lib/findprog-in.c +++ b/lib/findprog-in.c @@ -118,8 +118,9 @@ find_in_given_path (const char *progname, const char *path, const char *suffix = suffixes[i]; #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */ -/* File names without a '.' are not considered executable. */ -if (*suffix != '\0' || strchr (progbasename, '.') != NULL) +/* File names without a '.' are not considered executable, and + for file names with a '.' no additional suffix is tried. */ +if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL)) #endif { /* Concatenate progname and suffix. */ @@ -185,8 +186,9 @@ find_in_given_path (const char *progname, const char *path, const char *suffix = suffixes[i]; #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */ -/* File names without a '.' are not considered executable. */ -if (*suffix != '\0' || strchr (progname, '.') != NULL) +/* File names without a '.' are not considered executable, and + for file names with a '.' no additional suffix is tried. */ +if ((*suffix != '\0') != (strchr (progname, '.') != NULL)) #endif { /* Concatenate dir, progname, and suffix. */
make autoconf tests work with -Werror=implicit-function-declaration
There are indications that future GCC versions may be stricter regarding invocations of undeclared functions. [1] Configuring with CC="gcc -Werror=implicit-function-declaration" is a way to exercise similar functionality with released GCCs. So, what I did is 1. create a testdir of all of gnulib, 2. configure it once with CC="gcc" and once with CC="gcc -Werror=implicit-function-declaration", both with option '-C', 3. compare the resulting config.cache files. I got differences in the cache variables gl_cv_func_ptsname_sets_errno gt_cv_locale_tr_utf8 This patch fixes the issues. [1] https://lists.gnu.org/archive/html/bug-gettext/2019-09/msg00012.html 2019-09-14 Bruno Haible Make autoconf tests work with -Werror=implicit-function-declaration. * m4/locale-tr.m4 (gt_LOCALE_TR_UTF8): Include , for towupper() declaration. * m4/ptsname.m4 (gl_FUNC_PTSNAME): Include , for ptsname() declaration. diff --git a/m4/locale-tr.m4 b/m4/locale-tr.m4 index aeb2419..4c413f0 100644 --- a/m4/locale-tr.m4 +++ b/m4/locale-tr.m4 @@ -1,4 +1,4 @@ -# locale-tr.m4 serial 11 +# locale-tr.m4 serial 12 dnl Copyright (C) 2003, 2005-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -21,6 +21,7 @@ changequote(,)dnl #endif #include #include +#include struct tm t; char buf[16]; int main () { diff --git a/m4/ptsname.m4 b/m4/ptsname.m4 index 5033d90..04bfd3b 100644 --- a/m4/ptsname.m4 +++ b/m4/ptsname.m4 @@ -1,4 +1,4 @@ -# ptsname.m4 serial 7 +# ptsname.m4 serial 8 dnl Copyright (C) 2010-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -19,10 +19,12 @@ AC_DEFUN([gl_FUNC_PTSNAME], AC_CACHE_CHECK([whether ptsname sets errno on failure], [gl_cv_func_ptsname_sets_errno], [AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[#include - ]], [[ - return ptsname (-1) || !errno; - ]])], + [AC_LANG_PROGRAM([[ + #include + #include +]], [[ + return ptsname (-1) || !errno; +]])], [gl_cv_func_ptsname_sets_errno=yes], [gl_cv_func_ptsname_sets_errno=no], [case "$host_os" in
[PATCH] findprog-in: Set errno to indicate why NULL was returned.
Set errno to either ENOENT if the program was not found, or another error if a program was found but was no suitable (i.e., EACCES). * modules/findprog: Depend on errno. * lib/findprog-in.c (find_in_given_path): Save errno if it is not ENOENT and reset errno before returning NULL. * lib/findprog.h (find_in_given_path): Update the documentation. --- lib/findprog-in.c | 9 + lib/findprog.h | 20 modules/findprog-in | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/findprog-in.c b/lib/findprog-in.c index d601e060d..8ea03f8f7 100644 --- a/lib/findprog-in.c +++ b/lib/findprog-in.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "filename.h" @@ -74,6 +75,8 @@ const char * find_in_given_path (const char *progname, const char *path, bool optimize_for_exec) { + int saved_errno = ENOENT; + { bool has_slash = false; { @@ -142,11 +145,14 @@ find_in_given_path (const char *progname, const char *path, else return progpathname; } +else if (errno != ENOENT) + saved_errno = errno; free (progpathname); } } +errno = saved_errno; return NULL; } } @@ -221,6 +227,8 @@ find_in_given_path (const char *progname, const char *path, free (path_copy); return progpathname; } +else if (errno != ENOENT) + saved_errno = errno; free (progpathname); } @@ -234,5 +242,6 @@ find_in_given_path (const char *progname, const char *path, free (path_copy); } + errno = saved_errno; return NULL; } diff --git a/lib/findprog.h b/lib/findprog.h index f7b44071f..b1b6caa5f 100644 --- a/lib/findprog.h +++ b/lib/findprog.h @@ -41,14 +41,18 @@ extern const char *find_in_path (const char *progname); directory. A null PATH is equivalent to an empty PATH, that is, to the singleton list that contains only the current directory. Determines the pathname that would be called by execlp/execvp of PROGNAME. - - If successful, it returns a pathname containing a slash (either absolute - or relative to the current directory). The returned string can be used - with either execl/execv or execlp/execvp. It is freshly malloc()ed if it - is != PROGNAME. - - Otherwise, it returns NULL. - If OPTIMIZE_FOR_EXEC is true, the function saves some work, under the - assumption that the resulting pathname will not be accessed directly, - only through execl/execv or execlp/execvp. */ + On systems which support executable suffixes these are checked, if PROGNAME + does not already contain a suffix. + Returns either PROGNAME, or a freshly malloc()ed string, or NULL. If NULL + is returned then errno is set (ENOENT, EACCES, etc.) + If PROGNAME contains a slash ('/' on POSIX; '/' or '\' on Windows) then: + - If OPTIMIZE_FOR_EXEC is true returns PROGNAME without checking suffixes + or existence under the assumption that the resulting pathname will be + used with execl/execv/execlp/execvp. + - Else if PROGNAME refers an executable program it is returned. + - Else NULL is returned and errno is set. + Otherwise PATH is searched and the pathname is returned if found, or + returns NULL and errno is set. */ extern const char *find_in_given_path (const char *progname, const char *path, bool optimize_for_exec); diff --git a/modules/findprog-in b/modules/findprog-in index ce7faa50e..d38e6f2be 100644 --- a/modules/findprog-in +++ b/modules/findprog-in @@ -9,6 +9,7 @@ m4/eaccess.m4 Depends-on: stdbool +errno filename xalloc xconcat-filename -- 2.18.0
Re: [PATCH] findprog-in: Set errno to indicate why NULL was returned.
On Sat, 2019-09-14 at 15:35 -0400, Paul Smith wrote: > Set errno to either ENOENT if the program was not found, or another > error if a program was found but was no suitable (i.e., EACCES). Without this change it's impossible for a program to show the correct error message when the program is found on the path, but is not executable.