在C中创建shell,execv()无法执行大多数命令

时间:2015-10-01 00:41:55

标签: c linux shell

到目前为止,我知道在shell中工作的唯一命令是ls和echo。当我尝试触摸或帮助之类的东西时,我要么得不到任何东西,要么出现错误。

这是执行命令的方法:

void mySystem(char * cmdargv[], char *searchpaths[], int numpaths, int numargs)
{
    int pid=fork();
    if(pid==0);
    {
        for(int i=0; i<numpaths; i++)
        {
            char * fullcmd = malloc(strlen(searchpaths[i] + strlen(cmdargv[0]) + 2));
            sprintf(fullcmd, "%s/%s", searchpaths[i], cmdargv[0]);
            //execv(fullcmd, cmdargv);
            printf("%s",fullcmd);
            free(fullcmd);

        }
        exit(0);
    }
    wait(NULL);
}

这是我的主要计划:

int main()
{
    const char space[]="\n"; //"deliminator," specifies where to tokenize commands

int numpaths;
int numargs;
char *searchpaths[MAX_PATHS];
char *fullCMD[MAX_CMD];
InitializeArray(fullCMD, MAX_CMD);
InitializeArray(searchpaths, MAX_PATHS);

char cmd[MAX_CMD];

SaveSearchPaths(searchpaths, (int *) &numpaths); //fills the searchpaths array with
                                                 //the system PATH and returns the
                                                 //the size of the array, numpaths

while(1)
{
    printf("> ");

    fgets(cmd, MAX_CMD, stdin);

    char *token;
    token=strtok(cmd, space);

    if(strncmp(cmd,"quit",4) == 0)
    {
        exit(0);
    }
    else if(strncmp(cmd, "path", 4)==0)
    {
        PrintAll(searchpaths, MAX_PATHS);
    }
    else
    {
        int i=0;
        while(token!=NULL)
        {
            InsertStringAt(fullCMD,token,i);
            token=strtok(NULL,space);
            i++;
            numargs+=1;
        }
        mySystem(fullCMD, searchpaths, numpaths, numargs);
    }

InitializeArray()函数将数组中的所有索引初始化为NULLInsertStringAt()将字符串插入数组中的某个索引,SaveSearchPaths()使用标记化的系统searchpaths[]填充PATH数组。

当我在shell中输入ls时会发生什么:

./a.out
> ls
a.out arrayOfStrings.c  arrayOfStrings.h  arrayOfStrings.h.gch  arrayOfStrings.o  arrayOfStringsTester.c  arrayOfStringsTester.o  myshell.c  mySystem.c  out  SaveSearchPaths.c

以下是我提供帮助时会发生的事情:

$ ./a.out
> help
$

什么都没发生。

以下是触摸时会发生的事情:

> touch file
*** Error in `./a.out': free(): invalid next size (fast): 0x00000000006a2130 ***
*** Error in `./a.out': free(): invalid next size (fast): 0x00000000006a2130 ***
Aborted (core dumped)

任何想法为什么只有ls似乎有效?

2 个答案:

答案 0 :(得分:2)

你这里有一个错字

strlen(searchpaths[i] + strlen(cmdargv[0]) + 2)
/*                   ^ the ) goes here  not   ^ here

这是有效的,因为您正在递增searchpaths[i]指针并对结果指针执行strlen(),这可能会导致未定义的行为,但它是有效的代码,编译器应该正确编译它。

正确的方法是

strlen(searchpaths[i]) + strlen(cmdargv[0]) + 2

此外,您应检查malloc()是否未返回NULL,这表示错误。

您可以阻止此操作,并在存储strlen()的结果时处理更多错误。习惯它也是好的恕我直言,因为有时你可能需要不止一次的值,并且由于strlen()计算值,因此在这些情况下存储它会更有效,在这种情况下,唯一的好处是清晰度和提高处理错误和维护代码的能力。

答案 1 :(得分:0)

未经测试,我希望这有效。

void mySystem(char * cmdargv[], char *searchpaths[], int numpaths, int numargs)
{
    int pid=fork();
    if(pid==0) /* remove junk semicolon */
    {
        for(int i=0; i<numpaths; i++)
        {
            char * fullcmd = malloc(strlen(searchpaths[i]) + strlen(cmdargv[0]) + 2); /* improve this expression */
            sprintf(fullcmd, "%s/%s", searchpaths[i], cmdargv[0]);
            //execv(fullcmd, cmdargv);
            printf("%s",fullcmd);
            free(fullcmd);

        }
        exit(0);
    }
    wait(NULL);
}