execvp не работает с несколькими аргументами или без них

Я работаю над довольно простой оболочкой 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);
                            }
                    }
    }
}

person sven    schedule 09.12.2013    source источник


Ответы (1)


Вам нужно обнулить строки ваших аргументов до execvp.

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++;
    }

    argv[i] = NULL;  //<--- insert here

    if (execvp(argv[0], argv) == -1)
    {
        printf("failure to execute because %s\n", strerror(errno));
        exit(0);
    }
}
person Duck    schedule 09.12.2013