* lib/findprog.h (find_in_given_path): Add directory argument.
* lib/findprog-in.c (find_in_given_path): Likewise.
* lib/execute.c (execute): Update caller.
* lib/spawn-pipe.c (create_pipe): Likewise.
* lib/windows-spawn.c (spawnpvech): Likewise.
* NEWS: Mention the change.
+2020-12-14 Bruno Haible <bruno@clisp.org>
+
+ findprog-in: Allow overriding the current directory.
+ * lib/findprog.h (find_in_given_path): Add directory argument.
+ * lib/findprog-in.c (find_in_given_path): Likewise.
+ * lib/execute.c (execute): Update caller.
+ * lib/spawn-pipe.c (create_pipe): Likewise.
+ * lib/windows-spawn.c (spawnpvech): Likewise.
+ * NEWS: Mention the change.
+
2020-12-14 Bruno Haible <bruno@clisp.org>
posix_spawn-internal: Make better use of 'const'.
Date Modules Changes
+2020-12-14 findprog-in The function 'find_in_given_path' now takes a 3rd
+ argument 'const char *directory'. To maintain the
+ previous behaviour, insert NULL as additional 3rd
+ argument.
+
2020-12-11 sh-quote The argv argument of the 'shell_quote_argv' function
is now of type 'const char * const *'. You no
longer need to cast read-only strings to 'char *'
if (! IS_ABSOLUTE_FILE_NAME (prog_path))
{
const char *resolved_prog =
- find_in_given_path (prog_path, getenv ("PATH"), false);
+ find_in_given_path (prog_path, getenv ("PATH"), NULL, false);
if (resolved_prog == NULL)
goto fail_with_errno;
if (resolved_prog != prog_path)
const char *
find_in_given_path (const char *progname, const char *path,
- bool optimize_for_exec)
+ const char *directory, bool optimize_for_exec)
{
{
bool has_slash = false;
with such a suffix is actually executable. */
int failure_errno;
size_t i;
+
+ const char *directory_as_prefix =
+ (directory != NULL && IS_RELATIVE_FILE_NAME (progname)
+ ? directory
+ : "");
+
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
const char *progbasename;
if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL))
#endif
{
- /* Concatenate progname and suffix. */
+ /* Concatenate directory_as_prefix, progname, suffix. */
char *progpathname =
- concatenated_filename ("", progname, suffix);
+ concatenated_filename (directory_as_prefix, progname,
+ suffix);
if (progpathname == NULL)
return NULL; /* errno is set here */
{
const char *dir;
bool last;
+ char *dir_as_prefix_to_free;
+ const char *dir_as_prefix;
size_t i;
/* Extract next directory in PATH. */
if (dir == cp)
dir = ".";
+ /* Concatenate directory and dir. */
+ if (directory != NULL && IS_RELATIVE_FILE_NAME (dir))
+ {
+ dir_as_prefix_to_free =
+ concatenated_filename (directory, dir, NULL);
+ if (dir_as_prefix_to_free == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ goto failed;
+ }
+ dir_as_prefix = dir_as_prefix_to_free;
+ }
+ else
+ {
+ dir_as_prefix_to_free = NULL;
+ dir_as_prefix = dir;
+ }
+
/* Try all platform-dependent suffixes. */
for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
{
if ((*suffix != '\0') != (strchr (progname, '.') != NULL))
#endif
{
- /* Concatenate dir, progname, and suffix. */
+ /* Concatenate dir_as_prefix, progname, and suffix. */
char *progpathname =
- concatenated_filename (dir, progname, suffix);
+ concatenated_filename (dir_as_prefix, progname, suffix);
if (progpathname == NULL)
{
/* errno is set here. */
failure_errno = errno;
+ free (dir_as_prefix_to_free);
goto failed;
}
free (progpathname);
/* Add the "./" prefix for real, that
- xconcatenated_filename() optimized away.
+ concatenated_filename() optimized away.
This avoids a second PATH search when the
caller uses execl/execv/execlp/execvp. */
progpathname =
{
/* errno is set here. */
failure_errno = errno;
+ free (dir_as_prefix_to_free);
goto failed;
}
progpathname[0] = '.';
strlen (progname) + 1);
}
+ free (dir_as_prefix_to_free);
free (path_copy);
return progpathname;
}
}
}
+ free (dir_as_prefix_to_free);
+
if (last)
break;
}
directory. A null PATH is equivalent to an empty PATH, that is, to the
singleton list that contains only the current directory.
+ If DIRECTORY is not NULL, all relative filenames (i.e. PROGNAME when it
+ contains a slash, and the PATH elements) are considered relative to
+ DIRECTORY instead of relative to the current directory of this process.
+
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
- On POSIX systems excluding Cygwin: a '/',
- On Windows, OS/2, DOS platforms: a '/' or '\'. */
extern const char *find_in_given_path (const char *progname, const char *path,
+ const char *directory,
bool optimize_for_exec);
if (! IS_ABSOLUTE_FILE_NAME (prog_path))
{
const char *resolved_prog =
- find_in_given_path (prog_path, getenv ("PATH"), false);
+ find_in_given_path (prog_path, getenv ("PATH"), NULL, false);
if (resolved_prog == NULL)
goto fail_with_errno;
if (resolved_prog != prog_path)
/* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */
const char *resolved_progname =
- find_in_given_path (progname, getenv ("PATH"), false);
+ find_in_given_path (progname, getenv ("PATH"), NULL, false);
if (resolved_progname == NULL)
return -1;