execve()
не смотрит на PATH;для этого вам нужно execvp()
.Вашей программе не удалось выполнить ls
, и, очевидно, вы не сообщаете о сбоях при выполнении программы после execve()
.Обратите внимание, что члены семейства функций exec*()
возвращаются только при ошибке.
Вы получите ожидаемый результат (более или менее), если вы запустите программу с /bin
в качестве текущего каталога (потому что./ls
- иначе ls
- будет существовать).
Вам необходимо указать путь к исполняемому файлу в первом аргументе для execve()
, после нахождения его с использованием соответствующей настройки PATH.
Или продолжайте использовать execvp()
, но установите переменную environ
для вашей новой среды.Обратите внимание, что environ
теперь (POSIX 2008) объявлен в <unistd.h>
, но ранее нигде не был объявлен.
extern char **environ;
environ = env_args;
execvp(args[0], &args[0]);
Вам не нужно сохранять старое значение и восстанавливать его;вы находитесь в дочернем процессе, и переключение его среды не повлияет на основную программу (оболочку).
Это работает, как я и ожидал, - и демонстрирует, что исходный код ведет себя так, как яжду.
#include <stdio.h>
#include <unistd.h>
extern char **environ;
int main(void)
{
char *args[] = { "ls", "-l", "-a", NULL };
char *env_args[] = { "PATH=/bin", "USER=me", NULL };
execve(args[0], args, env_args);
fprintf(stderr, "Oops!\n");
environ = env_args;
execvp(args[0], &args[0]);
fprintf(stderr, "Oops again!\n");
return -1;
}
Я получаю "Ой!"с последующим перечислением моего каталога.Когда я создаю исполняемый файл ls
в моем текущем каталоге:
#!/bin/sh
echo "Haha!"
, тогда я не получаю 'Oops!'и получите «Ха-ха!».