Возникли проблемы с execvp

#c #shell #execvp

#c #оболочка #execvp

Вопрос:

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

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

 int extern_process(char *arg[]){
    pid_t pid;
    int errnum, ifFail;
    printf("i%sin",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," nt");

    if(retval == NULL){
        fprintf(stderr, "Error with allocationn");
        return;
    }
    if(tmp == NULL){
        printf("Error with parsing.n");
        return;
    }
    while(tmp != NULL){
        retval[i] = tmp;
        tmp = strtok(NULL," nt");
        i  ;
    }
    retval[i] = NULL;
}
  

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

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

Комментарии:

1. но, согласно вашему коду, i i означает, что команда, которую вы пытаетесь выполнить, пуста. Итак, ваши аргументы к extern_process выглядят неверно. Вам необходимо предоставить код, который вызывает функцию.

2. не будет полностью пустым, возможно, пробел " " . Также " nt" является избыточным, должно быть просто " nt" (строковые константы уже заканчиваются на '' ).

3. когда это: parse_cmd() возвращается, char *retval[] будет содержать указатели на локальный массив: a[100] Однако этот массив будет «вне области видимости» при завершении функции, поэтому обращение к нему является неопределенным поведением

4. что касается: ifFail = execvp(arg[0],arg); Это неверно, предлагаю: execvp(arg[0],arg); perror( "execvp failed" )' exit( EXIT_FAILURE ); не return; , поскольку дочерний процесс будет выполняться, и вы НЕ хотите, чтобы дочерний процесс возвращался к вызывающей функции: extern_process()

Ответ №1:

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

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

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

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

Комментарии:

1. Спасибо, я попробовал это, и это, казалось, прояснило мои проблемы.