在C fork中,print()在while()循环后没有执行

时间:2014-01-30 03:55:40

标签: c fork printf

我正在为学校项目编写自定义shell,我需要能够通过“execv”函数运行外部命令。我需要我的命令要么使用适当的输出成功运行,要么声明找不到命令。这是我的代码(有一些printf()输出用于调试):

/* Create a child process */
pid_t pid = fork();

/* Check if the fork failed */
if (pid >= 0)
{
    if (pid == 0)
    {                           
        /* This is the child process - see if we need to search for the PATH */
        if( strchr( command.args[0], '/' ) == NULL )
        {
            /* Search the PATH for the program to run */
            char fullpath[ sizeof( getenv("PATH") ) ];
            strcpy( fullpath, getenv("PATH") );

            /* Iterate through all the paths to find the appropriate program */
            char* path;

            path = strtok( fullpath, colon );
            while(path != NULL)
            {
                char progpath[COMMAND_SIZE];

                /* Try the next path */
                path = strtok( NULL, colon );
                strcpy(progpath, path);
                strcat(progpath, "/");
                strcat(progpath, command.args[0]);

                /* Determine if the command exists */
                struct stat st;
                if(stat(progpath, &st) == 0)
                {
                    /* File exists. Set the flag and break. */
                    execv( progpath, command.args );
                    exit(0);
                }
                else
                {
                    printf("Not found!\n");
                }
            }
            printf("%s: Command not found!\n", command.args[0]);
        }
        else
        {
            ...
        }

        /* Exit the process */
        exit(EXIT_FAILURE);
    }
    else
    {
        /* This is the parent process - wait for the child command to exit */
        waitpid( pid, NULL, 0 );
        printf("Done with fork!\n");
    }
}
else
{
    /* Could not fork! */
    printf("%s: %s > Failed to fork command!\n", command.args[0], strerror(errno) );
}

这是输出:

john@myshell:/home/john/project>dir
/usr/local/sbin/dir: Not found!
/usr/local/bin/dir: Not found!
/usr/sbin/dir: Not found!
/usr/bin/dir: Not found!
/sbin/dir: Not found!
/bin/dir: Found!
makefile  makefile~  myshell.c  myshell.c~  myshell.x
Done with fork!
john@myshell:/home/john/project>foo
/usr/local/sbin/foo: Not found!
/usr/local/bin/foo: Not found!
/usr/sbin/foo: Not found!
/usr/bin/foo: Not found!
/sbin/foo: Not found!
/bin/foo: Not found!
/usr/games/foo: Not found!
Done with fork!
john@myshell:/home/john/project>

正在找到并正确执行已知命令“dir”。输出很棒。但是,当我使用假的“foo”命令时,我希望它找不到命令(显然没有),完成“while”循环,并执行以下“printf”命令。话虽如此,我预计会在输出结束时看到以下内容:

foo: Command not found!

我尝试使用布尔值和整数值作为“标志”来确定是否找到了命令。但是,根本没有代码在while循环之外运行。如果我删除“exit(0)”,则“printf”命令仍然无法运行。我很困惑,并且为什么while循环之外的代码似乎根本不运行而感到困惑。我也不知道这是我的分叉问题,还是与输出缓冲区有关。

我是以错误的方式执行此操作,或者如果找不到命令,如何确保“命令未找到”消息始终只运行一次?

1 个答案:

答案 0 :(得分:2)

您的代码中存在错误 - 您正在使用strcpy()并导致缓冲区溢出:

// Note the declaration of getenv():
char *getenv(const char *name);

因此sizeof(getenv("PATH")) == sizeof(char*),可能是4或8。

/* Search the PATH for the program to run */
char fullpath[ sizeof( getenv("PATH") ) ];   // allocate fullpath[4] or [8]
strcpy(fullpath, getenv("PATH"));   // overrun... copy to 4-8 char stack buffer
// UNDEFINED behavior after this - Bad Things ahead.

您可以使用malloc()来动态地在堆上分配完整路径:

char* fullpath = malloc(strlen(getenv("PATH")) + 1); // +1 for terminating NUL
strcpy(fullpath, getenv("PATH"));   // OK, buffer is allocated large enough

// ... use fullpath ...

// Then when you are done, free the allocated memory.
free(fullpath);
// And as a general habit you want to clear the pointer after freeing
// the memory to prevent hard-to-debug use-after-free bugs.
fullpath = 0;