Используя новый путь с execve для запуска команды ls
Я пытаюсь использовать execve для запуска команды ls. В настоящее время я запускаю его со следующими аргументами:
execve(args[0], args, env_args)
//args looks like {"ls", "-l", "-a", NULL}
//env_args looks like {"PATH=/bin", "USER=me", NULL}
Я ожидал, что это будет выполнением команды ls с использованием моего нового env_args, означающего, что он будет искать ls в моем PATH. Однако этот код на самом деле ничего не делает, и когда я запускаю код, он просто возвращается в мою командную строку без вывода.
Используя те же аргументы [], я использовал execvp, и ls работал и искал мой текущий путь.
Можете ли вы сказать мне, что я делаю не так?
То, что я пытаюсь сделать, это написать свою собственную программу оболочки, где я могу создавать и экспортировать свою собственную среду и использовать exec среду, которую я определил в char**. По сути, я пишу свои собственные функции для работы с env_args, чтобы добавлять и удалять переменные, и когда я вызываю exec, я хочу иметь возможность вызывать exec для {"ls", "-l", NULL} и видеть его в моих новых средах. переменная пути для допустимой программы с именем ls. Я надеюсь, что это объясняет, что я делаю немного лучше. Я не думаю, что внешняя среда будет работать для меня в этом случае.
1 ответ
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!"
тогда я не получаю "Ой!" и получите "Ха-ха!".