bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] findprog: Support searching in a specified path string


From: Bruno Haible
Subject: Re: [PATCH] findprog: Support searching in a specified path string
Date: Sun, 08 Sep 2019 13:38:37 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-159-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

> I'm addressing https://savannah.gnu.org/bugs/?56834
> 
> I want to invoke a child process, and I need the program I'm going to
> invoke to be searched for in a PATH which is (potentially) different
> than the PATH which is active in the parent.
> 
> When you use execlp(), you can just assign the child's environment
> before you invoke the exec.  Since you've already forked you're not
> modifying the parent's environment.
> 
> However, with posix_spawnp() that doesn't work

Thanks for explaining.

> the path search is done
> on the _parent's_ PATH environment value not the one passed in to
> posix_spawnp().  I don't want that, I need the search done in the
> child's environment.  I can't decide if this behavior by posix_spawnp()
> is correct or not, and the POSIX spec isn't clear, but it's how it
> works (at least on GNU/Linux).

For me, the POSIX spec [1] is clear: envp "constitute[s] the environment
for the new process image". It does not say that the search for the program
is done through envp.

All implementations agree on this: In the attached test, I get the output
  Callee found in parent's $PATH.
in all tested platforms (glibc/Linux, glibc/kFreeBSD, glibc/Hurd, Mac OS X,
FreeBSD 11, NetBSD 7, AIX, Solaris 10, Solaris 11, Solaris OpenIndiana,
Haiku) and with gnulib's replacement (tested on Solaris 9). So, there is
no portability issue here.

> At the same time, I don't want to be running putenv() to set then
> reset the PATH environment variable in the parent every time I invoke
> a command.
> 
> So what I want to do is run find_in_path_str() passing in the PATH from
> the child's environment then pass the result to posix_spawn.

Makes sense.

> I suppose an even simpler interface, for me, would be something like:
> 
>     find_in_path_envp (const char *prog, const char **envp);
> 
> where it would look up PATH in the environment passed in, so I don't
> have to do the lookup of PATH, and use that instead of getenv().  But I
> don't know if that's as generally useful an interface.

If there were many libc functions that take a '[const] char**' environment
as argument, I would agree that this was the way to go. But there are no
getenv, setenv, putenv variants that take a 'char **' arguments; so it appears
that POSIX and libc APIs don't recognize 'char **' as a valuable data type.
I therefore find it better to define the function with just the PATH value
as argument.

> Because that's not my use-case :).  I already have a PATH string, it's
> just not in my current environment.

OK.

>     prog = find_in_path_str ("myprog", lookup_path ());
> 
> and if lookup_path() returns NULL it defaults to the environment PATH,

I don't think NULL should be interpreted as "look in the default PATH".
Rather, the convention is that an empty or null PATH means the current
directory. Try
  $ (cd /tmp; PATH=; cat --version)
  $ (cd /bin; PATH=; cat --version)
  $ (cd /tmp; unset PATH; cat --version)
  $ (cd /bin; unset PATH; cat --version)

> rather than having to do something like:
> 
>     const char *path = lookup_path ();
>     if (path)
>       prog = find_in_path_str ("myprog", path);
>     else
>       prog = find_in_path ("myprog");

If the caller needs this logic, it should better be coded explicitly like this.

Note also that what you need is not merely an *attempt* to determine the
filename of the executable, but you need it always - since you _don't_ want
the program to be looked up in the parent's PATH. Thus you need also a
return value that indicates that the program was not found in PATH. Otherwise,
assume
  parent PATH = "/bin:/usr/bin"
  child PATH = "/tmp"
  program = "cat"
the find_in_path_str search would do a lookup in the child PATH, not find it,
return "cat", and the posix_spawnp would then find "cat" in the parent PATH
and invoke /bin/cat.

This, in turn, means that we need to provide also an implementation for
Windows, Cygwin, EMX, DOS.

And this means that it can't really share much with the existing findprog.c.
So the implementation should go into a different .c file.

Bruno

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html

Attachment: spawn-test.tar.gz
Description: application/compressed-tar


reply via email to

[Prev in Thread] Current Thread [Next in Thread]