#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. Спасибо, я попробовал это, и это, казалось, прояснило мои проблемы.