0

当我简单地通过管道 ls -l | 用这个排序,程序只是无限地从 ls -l 吐出结果。任何人都可以看到有什么问题吗?假设您只需要查看 main 函数。不过,这将编译。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>


#define COMMAND_LINE_LENGTH 256
#define HISTORY_LENGTH 10
#define TOKEN_MAX 50
#define DIRECTORY_LENGTH 5
#define DIRECTORY_PREFIX "/bin/"

struct prog_def
{
    //Binary location
    char *bin;

    //Is this program expecting a pipe?
    int expecting_pipe;

    //Arguments
    char *args[TOKEN_MAX + 1];

    pid_t pid;

} prog_def;

int get_prog_defs(const char* buf, struct prog_def prog_defs[])
{
    char *line = malloc(strlen(buf) + 1);

    int prog_count = 0;
    char* token;

    strcpy(line, buf);
    line[strlen(buf)] = 0;

    while(1)
    {
        int arg_count = 0;

        //The first time through we have to pass the line
        token = strtok(line, " ");

        //Each subsequent call we have to pass NULL
        //http://www.cplusplus.com/reference/cstring/strtok/
        line = NULL;

        //Start building the binary location string
        prog_defs[prog_count].bin = (char*)malloc(strlen(token) + DIRECTORY_LENGTH + 1);

        //Concatenate the directory prefix and command name
        strcat(prog_defs[prog_count].bin, DIRECTORY_PREFIX);
        strcat(prog_defs[prog_count].bin, token);

        //The first argument execvp will expect is the binary location itself
        //Redundant but if I wasn't too lazy to read the doc then I'd know why
        prog_defs[prog_count].args[arg_count++] = prog_defs[prog_count].bin;

        while(1)
        {
            prog_defs[prog_count].expecting_pipe = 0;

            //Check next token for end, pipe, IO redirection, or argument
            token = strtok(NULL, " ");

            //If we've consumed all tokens
            if (token == NULL)
                break;

            //Pipe
            if (strcmp(token, "|") == 0)
            {
                prog_defs[prog_count - 1].expecting_pipe = 1;
                break;
            }

            //Regular argument
            prog_defs[prog_count].args[arg_count++] = token;
        }

        ++prog_count;

        if (token == NULL) break;
    }

    return prog_count;
}


int main(int argc, char** argv)
{

    char command[COMMAND_LINE_LENGTH] = {0};

    //Generic loop counter
    int x = 0;

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

        //Get the command
        gets(command);

        struct prog_def prog_defs[TOKEN_MAX];
        int prog_count = get_prog_defs(command, prog_defs);

        //Keep the previous out fd for the in of the subsequent process
        int prev_out_fd = open("/dev/null", O_RDONLY);

        for (x = 0; x < prog_count; ++x)
        {
            //Create a pipe for both processes to share
            int pipefd[2];

            if (x != prog_count -1)
            {
                pipe(pipefd);
            }

            prog_defs[x].pid = fork();

            if(prog_defs[x].pid == 0)
            {
                dup2(prev_out_fd, STDIN_FILENO);
                close(pipefd[1]);

                if(x != prog_count - 1)
                {
                    dup2(pipefd[1], STDOUT_FILENO);
                    close(pipefd[0]);
                    close(pipefd[1]);
                }


                execvp(prog_defs[x].bin, prog_defs[x].args);
            prev_out_fd = pipefd[0];
            close(pipefd[1]);
            }

        close(prev_out_fd);

            prev_out_fd = pipefd[0];
            close(pipefd[1]);

        }

        printf("\n");

        for (x = 0; x < prog_count; ++x)
        {
            waitpid(prog_defs[x].pid, NULL, 0);
        }

    }
}
4

1 回答 1

1

您调用malloc为字符串获取一些内存,该字符串将未初始化,因此包含随机垃圾。然后,您调用strcatwhich 将尝试将另一个字符串附加到随机垃圾中,并且几乎可以肯定会跑出 malloc 空间的末尾,从而导致随机的混乱行为和崩溃。

您还使用prog_defs[prog_count - 1]before ever incrementing prog_count,因此第一次通过循环时, (when prog_count == 0) 这将在数组开始之前写入,这也会导致随机的混乱行为和崩溃。

于 2013-02-09T00:43:30.413 回答