3

我正在使用 C 语言开发一个非常基本的 UNIX shell。在这个项目中,我尝试使用fork()execvp()执行实际的 shell 命令。不过,我遇到了一个问题,它似乎可以与具有单个参数的命令一起正常工作(例如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);
                            }
                    }
    }
}
4

1 回答 1

2

您需要将参数字符串终止为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);
    }
}
于 2013-12-09T01:26:06.830 回答