diff options
author | Bruno Haible <bruno@clisp.org> | 2019-09-09 20:46:44 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2019-09-09 20:51:42 +0200 |
commit | 5b586b1ef88b79afcc5e2d98ec50dc360a7fb2a4 (patch) | |
tree | 24b7a6a15557e9218d9eecea995884d920398e6c | |
parent | 84cc75b23cedfb03d0339264d46e720650b405e2 (diff) | |
download | gnulib-5b586b1ef88b79afcc5e2d98ec50dc360a7fb2a4.tar.gz gnulib-5b586b1ef88b79afcc5e2d98ec50dc360a7fb2a4.tar.bz2 |
findprog-in: Make exec optimization optional.
* lib/findprog.h: Add double-inclusion guard. Include <stdbool.h>.
(find_in_given_path): Add optimize_for_exec parameter.
* lib/findprog-in.c (find_in_given_path): Likewise.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | lib/findprog-in.c | 98 | ||||
-rw-r--r-- | lib/findprog.h | 14 |
3 files changed, 97 insertions, 22 deletions
@@ -1,6 +1,13 @@ +2019-09-09 Bruno Haible <bruno@clisp.org> + + findprog-in: Make exec optimization optional. + * lib/findprog.h: Add double-inclusion guard. Include <stdbool.h>. + (find_in_given_path): Add optimize_for_exec parameter. + * lib/findprog-in.c (find_in_given_path): Likewise. + 2019-09-08 Bruno Haible <bruno@clisp.org> Add option to assume the best, not the worst, when cross-compiling. Suggested by Jonas Termansen <sortie@maxsi.org>. * m4/gnulib-common.m4 (gl_COMMON_BODY): Add --enable-cross-guesses=... option. Set gl_cross_guess_normal and gl_cross_guess_inverted. diff --git a/lib/findprog-in.c b/lib/findprog-in.c index 3d70b7b393..99b3c314d9 100644 --- a/lib/findprog-in.c +++ b/lib/findprog-in.c @@ -68,32 +68,90 @@ static const char * const suffixes[] = #else /* Unix */ "" #endif }; const char * -find_in_given_path (const char *progname, const char *path) +find_in_given_path (const char *progname, const char *path, + bool optimize_for_exec) { { bool has_slash = false; - const char *p; + { + const char *p; - for (p = progname; *p != '\0'; p++) - if (ISSLASH (*p)) - { - has_slash = true; - break; - } + for (p = progname; *p != '\0'; p++) + if (ISSLASH (*p)) + { + has_slash = true; + break; + } + } if (has_slash) - /* If progname contains a slash, it is either absolute or relative to - the current directory. PATH is not used. - We could try the various suffixes and see whether one of the files - with such a suffix is actually executable. But this is not needed, - since the execl/execv/execlp/execvp functions will do these tests - anyway. */ - return progname; + { + /* If progname contains a slash, it is either absolute or relative to + the current directory. PATH is not used. */ + if (optimize_for_exec) + /* The execl/execv/execlp/execvp functions will try the various + suffixes anyway and fail if no executable is found. */ + return progname; + else + { + /* Try the various suffixes and see whether one of the files + with such a suffix is actually executable. */ + size_t i; + #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */ + const char *progbasename; + + { + const char *p; + + progbasename = progname; + for (p = progname; *p != '\0'; p++) + if (ISSLASH (*p)) + progbasename = p + 1; + } + #endif + + /* Try all platform-dependent suffixes. */ + for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++) + { + 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) + #endif + { + /* Concatenate progname and suffix. */ + char *progpathname = + xconcatenated_filename ("", progname, suffix); + + /* On systems which have the eaccess() system call, let's + use it. On other systems, let's hope that this program + is not installed setuid or setgid, so that it is ok to + call access() despite its design flaw. */ + if (eaccess (progpathname, X_OK) == 0) + { + /* Found! */ + if (strcmp (progpathname, progname) == 0) + { + free (progpathname); + return progname; + } + else + return progpathname; + } + + free (progpathname); + } + } + + return NULL; + } + } } if (path == NULL) /* If PATH is not set, the default search path is implementation dependent. In practice, it is treated like an empty PATH. */ path = ""; @@ -128,20 +186,20 @@ find_in_given_path (const char *progname, const char *path) #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */ /* File names without a '.' are not considered executable. */ if (*suffix != '\0' || strchr (progname, '.') != NULL) #endif { - /* Concatenate dir and progname. */ + /* Concatenate dir, progname, and suffix. */ char *progpathname = xconcatenated_filename (dir, progname, suffix); - /* On systems which have the eaccess() system call, let's use - it. On other systems, let's hope that this program is not - installed setuid or setgid, so that it is ok to call - access() despite its design flaw. */ + /* On systems which have the eaccess() system call, let's + use it. On other systems, let's hope that this program + is not installed setuid or setgid, so that it is ok to + call access() despite its design flaw. */ if (eaccess (progpathname, X_OK) == 0) { /* Found! */ if (strcmp (progpathname, progname) == 0) { free (progpathname); diff --git a/lib/findprog.h b/lib/findprog.h index 9bc8a60da2..f7b44071fb 100644 --- a/lib/findprog.h +++ b/lib/findprog.h @@ -12,12 +12,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef _FINDPROG_H +#define _FINDPROG_H + +#include <stdbool.h> #ifdef __cplusplus extern "C" { #endif @@ -38,13 +42,19 @@ extern const char *find_in_path (const char *progname); 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. */ -extern const char *find_in_given_path (const char *progname, const char *path); + - 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. */ +extern const char *find_in_given_path (const char *progname, const char *path, + bool optimize_for_exec); #ifdef __cplusplus } #endif + +#endif /* _FINDPROG_H */ |