0

I want to write a program which executes the Linux ls command. I really only want to type in ls and not /bin/ls, so I want to do this using execve (execvp is not an option).

I tried:

char *env[] = { "SHELL=/bin/bash",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games",
"_=/usr/bin/env",
(char *)0 };
execve(parmList[0], parmList, env);

But it does not seem to work, ls is not recognized but /bin/ls is. Nothing is wrong with parmList because I tried this with execvp and it worked.

Any ideas?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
今天春天
  • 941
  • 1
  • 13
  • 27
  • 1) Why is `execvp` not an option? 2) Have you looked up the difference between `execvp`/`execvpe` and `execv`/`execve`? –  Nov 08 '15 at 20:51
  • Please give complete data. How `parmList` is declared/filled? What is the result (`perror`, returned values…)? – hexasoft Nov 08 '15 at 20:52
  • 1) Because I want the possiblity to say one day: I use the program "abc" in e.g. "/home/user/programs" every day and all I don't want to type in the full path every time. Then it should be possible to simply add another array entry. 2) execvpe seems to be working but my compiler does not like it for any reason. – 今天春天 Nov 08 '15 at 21:00
  • In what way does the compiler not like it? Does it complain that it isn't declared? If the function works, presumably it means that the linker found it. You may need to specify `-std=gnu11` instead of `-std=c11`, or you may need to have `#define _GNU_SOURCE` to make the declaration of `execvpe()` visible. – Jonathan Leffler Nov 08 '15 at 21:56

1 Answers1

2

If parmList[0] contains just ls, execve() won't find the ls command unless it is in the current directory.

With execve(), the value of PATH in the environment is immaterial — execve() does not use it. You'd use execvp() (or execvpe() if it is available) to execute the command on the current process's PATH.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • What do you mean by immaterial? – 今天春天 Nov 08 '15 at 21:06
  • I mean that with `execve()`, it doesn't matter what the value of PATH is because it won't be used by `execve()`. It would matter if you use `execvp()`. (And it isn't clear from either the Linux or the OpenBSD manuals for `execvpe()` which value of PATH is used; the one set in the `envp` argument or the prevailing value.) – Jonathan Leffler Nov 08 '15 at 21:29
  • Okay... So there is no chance to achieve this behavour: Program abc is located in /home/user/somedir. I set /home/user/somedir in the array as an environment parameter. If I now enter ./abc it will be found even though I am not in the directory /home/user/somedir? – 今天春天 Nov 08 '15 at 21:31
  • No. If `parmList[0]` contains `./abc`, the only program that will ever be run by any variant of `exec` will be the program in the current directory. The variants of `exec` with `p` in the name only look on PATH if the name in the first argument contains no slashes. Any slashes means it is only found by that exact name. If `abc` is in `/home/user/somedir` and `/home/user/somedir` is one of the directories list in PATH and if you have `parmList[0]` containing only `abc`, then `execvp()` or `execlp()` (or `execvpe()`) would find the program in `/home/user/somedir`. _[…caveats to follow…]_ – Jonathan Leffler Nov 08 '15 at 21:50
  • _[…caveats…]_ The `abc` in `/home/user/somedir` will be executed as long as there isn't another program `abc` elsewhere in a directory listed in PATH before `/home/user/somedir`. Note that POSIX does not define `execvpe()`, but it is available on both Linux (which you're working on) and OpenBSD (but not some other BSD variants — Mac OS X in particular does not have an `execvpe()`). So, you can do what you want, more or less, with `execvpe()`. The only residual issue is whether `execvpe()` uses the value of `PATH` in `envp` or the value in the process's environment. It could use either. – Jonathan Leffler Nov 08 '15 at 21:51