execve() не выполняет программу, несмотря на передачу переменной PATH

Я запускаю простую программу оболочки из каталога:

/home/пользователь/shell.exe

Используя приведенный ниже код, я могу запускать файлы, находящиеся в той же папке, что и исполняемый файл оболочки, но не могу запускать такие программы, как ls.exe.

Контейнер маркеров включает имя файла в качестве первого элемента и любые последующие маркеры (например, "-l" во входных данных "ls.exe -l") в следующих элементах.

if (fork())
{
  int status;
  wait(&status);
}
else
{
std::vector<const char*> exeArgs;
std::vector<const char*> envArgs;

std::for_each(tokens.begin(), tokens.end(),
[&exeArgs](const string& elem){ exeArgs.push_back(elem.c_str()); }
             );

exeArgs.push_back(nullptr);

string path = "PATH=";
path.append(getenv("PATH"));

envArgs.push_back(path.c_str());
envArgs.push_back(nullptr);

if (execve(exeArgs[0], const_cast<char *const *>(&exeArgs[0]),
                       const_cast<char *const *>(&envArgs[0])))
{
  std::cout << word << ": command not found" << std::endl;
  exit(0);
}
}

Я провел бесчисленное количество часов, просто гугля и читая справочные страницы снова и снова, но, похоже, не могу понять, почему этот код не работает.

Идея состоит в том, что моя программа оболочки должна позволять пользователям устанавливать переменную PATH, а затем выполнять программы с этой переменной PATH, поэтому я должен заставить execve() работать правильно, а не просто использовать execvp().

У меня есть карта переменных оболочки в отдельной части файла, но поскольку я даже не могу заставить это работать, я подумал, что было бы бессмысленно включать это.


person ozma    schedule 20.10.2017    source источник


Ответы (1)


Вы знаете, что семейство функций exec заменяет текущий процесс образом новой программы? Вот почему так часто используется fork перед exec.

Вооружившись этими знаниями, легко найти решение для вас и то, как вы можете использовать execvp (что вам нужно использовать, execve на самом деле не использует среду, которую вы проходите, она просто передает ее к новой программе): вы fork и используете setenv для установки PATH процесса new перед вызовом execvp.

person Some programmer dude    schedule 20.10.2017
comment
Я отредактировал сообщение, чтобы включить остальную часть моей функции. Я просто хотел бы уточнить, если execve() не использует переменные среды, которые передаются для установки переменных среды процесса после загрузки новой программы, то для чего нужен параметр массива переменных среды? - person ozma; 20.10.2017
comment
@ozma Как я уже сказал, он передает среду новой программе, той, которую выполняет exec. Если вы не знаете, в системах POSIX (таких как Linux или macOS, где exec стандартизировано) функция main может иметь третий аргумент, обычно именуемый env, объявляется и работает аналогично массиву argv. . Это среда, переданная execve (и которая будет доступна через getenv в новой программе). - person Some programmer dude; 20.10.2017
comment
О верно! Все это время я предполагал, что, поскольку я передавал переменные среды, они также будут играть роль в выполнении программы. Это также первый раз, когда я слышу о третьем аргументе для main. Благодаря тонну. - person ozma; 20.10.2017