Я работаю над довольно простой оболочкой UNIX на C. В этом проекте я пытаюсь использовать fork()
и execvp()
для выполнения реальных команд оболочки. Однако я столкнулся с проблемой, когда кажется, что команды с одним аргументом работают нормально (например, ls -l
и echo howareyoutoday
работают отлично), но команды с несколькими аргументами не выполняются (echo how are you today
не запускается). Я проведу вас через мой код/обоснование, чтобы помочь найти причину этой проблемы.
char *token;
int count=0;
pid_t childProc;
int childStatus;
pid_t tpid;
char* argv[256];
int i=1;
childProc = fork();
if (childProc==0) {
//CHILD PROCESS IS HERE
argv[0] = malloc(strlen(token));
argv[0] = token;
token=strtok(NULL," \n\t()<>|&;");
while(token!=NULL) {
argv[i]=malloc(strlen(token));
argv[i]=token;
token=strtok(NULL," \n\t()<>|&;");
i++;
}
execvp(argv[0],argv);
//if this executes execvp fails
printf("failure to execute\n");
i=0;
exit(0);
}
else {
//PARENT PROCESS IS HERE
do {
tpid = wait(&childStatus);
} while(tpid != childProc);
}
Итак, все начинается с простого вызова fork()
для создания дочернего процесса. В этом дочернем процессе я выделяю память для первого элемента в моем массиве argv
. token
, который исходит от предыдущего вызова strtok
, назначается argv[0]
. Генерируется новый token
и добавляется к следующему элементу argv
. Этот процесс повторяется для оставшихся жетонов.
Как только массив argv
завершен, вызывается execvp
, причем первый аргумент содержит имя команды, а второй — весь массив argv
. Если команда не будет выполнена, вернется execvp
, и будет напечатано сообщение, указывающее на это.
Я не могу понять, почему у меня проблема с несколькими аргументами, о которой я упоминал выше. Любая помощь или предложения будут с благодарностью!
Для справки, полный код программы выглядит следующим образом:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char buffer[256];
char *token;
int count=0;
pid_t childProc;
int childStatus;
pid_t tpid;
char* argv[256];
int i=1;
int j=0;
while(1) {
fgets(buffer, 256, stdin);
token=strtok(buffer," \n\t()<>|&;");
while (token==NULL) {
fgets(buffer,256,stdin);
token=strtok(buffer," \n\t()<>|&;");
}
if (strcmp(token,"exit")==0) {
exit(0);
}
else if (strcmp(token,"cd")==0) {
token = strtok(NULL, " \n\t()<>|&;");
if (chdir(token)!=0) {
perror("Error: ");
}
}
else {
childProc = fork();
if (childProc==0) {
argv[0] = malloc(strlen(token));
argv[0] = token;
token=strtok(NULL," \n\t()<>|&;");
while(token!=NULL) {
argv[i]=malloc(strlen(token));
argv[i]=token;
token=strtok(NULL," \n\t()<>|&;");
i++;
}
execvp(argv[0],argv);
//if this executes execvp fails
printf("failure to execute\n");
i=0;
exit(0);
}
else {
do {
tpid = wait(&childStatus);
} while(tpid != childProc);
}
}
}
}