используя новый путь с execve для запуска команды ls - PullRequest
3 голосов
/ 03 октября 2011

Я пытаюсь использовать 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. Надеюсь, это объясняет, что я делаю немного лучше. Я не думаю, что внешняя среда var будет работать для меня в этом случае.

1 Ответ

10 голосов
/ 03 октября 2011

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!'и получите «Ха-ха!».

...