Используя новый путь с 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!"

тогда я не получаю "Ой!" и получите "Ха-ха!".

Другие вопросы по тегам