Вы разбиваете командную строку на отдельные строки (имя команды, аргументы) и сохраняете их в массиве символьных указателей с нулевым символом в конце. Затем вы разветвляетесь и передаете имя команды и команду + аргументы execvp()
, если это не verboten. В конечном итоге вам также придется беспокоиться о каналах и перенаправлении ввода / вывода, но основная идея остается прежней.
char *args[MAXARGS];
args[0] = "cat";
args[1] = "foo.txt";
args[2] = 0;
if ((pid = fork()) == 0)
{
execvp(args[0], args);
...print error...
exit(1);
/* execvp() does not return unless there's an error */
}
else if (pid < 0)
...fork failed...
else
...wait for child to finish - or start other commands, or ...
Вы можете динамически размещать args
в реальной оболочке. Он становится на один шаг сложнее, если вам нужно предоставить пользовательскую среду для исполняемой программы. По сути, вы соберете копию среды, а затем после разветвления установите глобальное значение environ
на новое значение, но если новое окружение содержит новое значение для PATH, это повлияет на поиск команды с помощью execvp()
. Поэтому вы можете написать свой собственный вариант execvp()
из-за этого. Если это так, возьмите лист из книги BSD (MacOS X); есть функция execvP()
:
int execvP(const char *file, const char *search_path, char *const argv[]);
, который позволяет указать путь поиска, который вы хотите использовать, даже если вы исправили среду Самый фундаментальный вызов - execve()
; это используется execvp()
за сценой (возможно, через execv()
).