Проблемы с execvp

У меня возникли проблемы с базовой программой оболочки, которую я пытаюсь написать на c. Всякий раз, когда я пытаюсь вызвать exec в такой функции, как ls, execvp возвращает сообщение об ошибке, указывающее, что файл или каталог не найден. Я думаю, что проблема с разбором, потому что в основном команда может быть напечатана, но в функции она пуста. Спасибо

Вот код функции:

int extern_process(char *arg[]){
    pid_t pid;
    int errnum, ifFail;
    printf("i%si\n",arg[0]);
    pid = fork();

    if(pid == -1){
        errnum = errno;
        fprintf(stderr,"Error: fork %s", strerror(errnum));
        return FAIL;
    } else if(pid == 0){
        ifFail = execvp(arg[0],arg);
        if(ifFail < 0){
            errnum = errno;
            fprintf(stderr,"Error: exec %s", strerror(errnum));
            return FAIL;
        }
    } else {
        pid = wait(NULL);
    }
    return SUCCESS;
}

Вот код функции парсинга на всякий случай:

void parse_cmd(char *retval[], char *cmd){
    char *tmp;
    char a[100];
    strcpy(a,cmd);
    int i = 0;
    tmp = strtok(a," \n\t\0");

    if(retval == NULL){
        fprintf(stderr, "Error with allocation\n");
        return;
    }
    if(tmp == NULL){
        printf("Error with parsing.\n");
        return;
    }
    while(tmp != NULL){
        retval[i] = tmp;
        tmp = strtok(NULL," \n\t\0");
        i++;
    }
    retval[i] = NULL;
}

Вот результат:

shell> ls 
ls
i i 
Error: exec no file or directory found 

person dpatel125    schedule 05.03.2019    source источник
comment
но согласно вашему коду i i означает, что команда, которую вы пытаетесь выполнить, пуста. Итак, ваши доводы на extern_process выглядят неправильно. Вам нужно предоставить код, который вызывает функцию.   -  person Serge    schedule 05.03.2019
comment
не будет полностью пустым, возможно, пробел " ". Также " \n\t\0" является избыточным, должно быть просто " \n\t" (строковые константы уже заканчиваются на '\0').   -  person Ted D.    schedule 05.03.2019
comment
когда это: parse_cmd() возвращается, char *retval[] будет содержать указатели на локальный массив: a[100] Однако этот массив будет «вне области действия» при выходе из функции, поэтому доступ к нему является неопределенным поведением   -  person user3629249    schedule 06.03.2019
comment
относительно: ifFail = execvp(arg[0],arg); Это неверно. Предложите: execvp(arg[0],arg); perror( "execvp failed" )' exit( EXIT_FAILURE ); не делайте этого return;, так как будет выполняться дочерний процесс, и вы НЕ хотите, чтобы дочерний процесс возвращался к вызывающей стороне функции: extern_process()   -  person user3629249    schedule 06.03.2019


Ответы (1)


Я почти уверен, что strtok возвращает указатель на первый аргумент, который в вашем случае представляет собой выделение стека. Я полагаю, что возврат массива указателей на это распределение стека приведет к неопределенному поведению. Это может быть или не быть причиной вашей проблемы. Трудно понять, не видя больше кода. Для проверки попробуйте изменить эту часть кода следующим образом:

void parse_cmd(char *retval[], char *cmd){
    char *tmp;
    char *a = strdup(cmd);
    int i = 0;

Прежде чем использовать его в продакшне, вам нужно каким-то образом убедиться, что вы освобождаете «а», иначе вы получите утечку. Возможно, вы могли бы просто вернуть его вместо void и освободить его из другого места, или вы могли бы на самом деле использовать функцию strdup() для каждого токена и написать функцию, чтобы освободить их все или что-то, что работает для вас.

Если есть другие проблемы, они могут быть в другом коде. Я действительно не вижу здесь ничего плохого.

person Bob Shaffer    schedule 05.03.2019
comment
Спасибо, я попробовал это, и это, казалось, прояснило мои проблемы. - person dpatel125; 05.03.2019