проблемы с системным вызовом execvp

Я делаю небольшую оболочку, чтобы лучше понять C. Я использую функцию getline POSIX, чтобы получить строку и разбить ее на токены по пробелу. Но когда я вызываю execvp() для выполнения системного вызова, ничего не происходит. Если кто-то укажет мне, где у меня проблема, очевидно, что я упускаю что-то, вероятно, небольшое.. (Я не включил весь код поэтому некоторые фигурные скобки будут отсутствовать внизу, просто игнорируйте это, извините) Большое спасибо

        char *args[3];  // array for the command and arguments

        cmd = strtok(line, " ");            
        args[0] = cmd;              // put the first command in the array

        for(int i = 1; i < whitespace+1; ++i){

            cmd = strtok('\0', " \n");
            args[i] = cmd;              // fill the array of strings with the arguments
        }
        args[2] = '\0';    // assign last element to NULL


        pid = fork();

        if(pid != 0){        
            waitpid(-1, &stat, 0); 
        }
        else{

            char *const *test[1];
            test[0] = '\0';
            execvp("/bin/ls", test[0]);
            execvp(args[0], &args[1]);

В самом конце у меня возникли проблемы, я попробовал обе версии execvp по отдельности, но ни одна из них не работает, и я застрял в этой проблеме на 2 дня. Спасибо за любую помощь.


person Daniel Callaghan    schedule 13.11.2014    source источник
comment
Ваш args[2] = '\0'; - это неортодоксальный (но законный) способ установки нулевого указателя. Это также ограничивает вашу команду не более чем одним именем файла. Цикл перед ним становится немного избыточным. Затем у вас есть два вызова execvp(); если первый завершится успешно, второй не будет выполнен. Правильный способ вызова execvp()execvp(args[0], args);. У вас должен быть код сообщения об ошибке после execvp() - если он возвращается, это не удалось - и должен нормально завершиться.   -  person Jonathan Leffler    schedule 13.11.2014
comment
Обратите внимание, что getline() — это расширение GNU, не указанное в POSIX. У меня есть только ваше слово, что вы его используете, поскольку его нет в представленном вами коде.   -  person John Bollinger    schedule 13.11.2014
comment
Как более ортодоксальный способ установить нулевой указатель. Спасибо за подсказку о том, как правильно вызывать execvp.   -  person Daniel Callaghan    schedule 13.11.2014
comment
Обратите внимание, что когда execvp() работает, он не возвращает значение, поэтому редко уместно вызывать его дважды подряд. Если он возвращается, значит, произошла ошибка, и вы можете определить природу этой ошибки с помощью переменной errno, возможно, с помощью функции perror().   -  person John Bollinger    schedule 13.11.2014
comment
Как можно более ортодоксально установить нулевой указатель? args[2] = NULL; Если NULL не определено, включите <stddef.h>   -  person Paul Roub    schedule 13.11.2014
comment
Извините, я на самом деле не вызываю execvp дважды. Я прокомментировал тот, который использует массивы, и проверил буквальную строку, чтобы увидеть, была ли это проблема с настройкой моего массива. Спасибо за предложение файла заголовка NULL   -  person Daniel Callaghan    schedule 13.11.2014


Ответы (1)


Вот минимальный пример того, как заставить execvp работать.

#include <stdio.h>
#include <unistd.h>

int main( void )
{
    char *test[2];              // declare an array of pointers
    test[0] = "/bin/ls";        // first arg is the path to the executable
    test[1] = NULL;             // NULL terminator indicates no additional args
    execvp( test[0], test );
}

Вот объяснение из справочной страницы для execvp

Первый аргумент по соглашению должен указывать на имя файла, связанного с исполняемым файлом. Массив указателей должен заканчиваться указателем NULL.

person user3386109    schedule 13.11.2014