1

我在 C 中的管道实现存在问题。当我运行以下程序并输入“ls | more”时,结果是错误分段错误核心转储。这是程序:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <readline/readline.h>
#include <readline/history.h>

void execute(char **, int, char **);
void handle_signal(int);
int parse(char *, char **, char **, int *);
void chop(char *);

#define INPUT_STRING_SIZE 513

#define NORMAL                 00
#define OUTPUT_REDIRECTION     11
#define INPUT_REDIRECTION     22
#define PIPELINE             33
#define BACKGROUND            44
#define OUTPUT_APP    55

int main(int argc, char *argv[])
{
    int i, mode = NORMAL, cmdArgc;
    size_t len = INPUT_STRING_SIZE;
    char *cpt, *inputString, *cmdArgv[INPUT_STRING_SIZE], *supplement = NULL;
    inputString = (char*)malloc(sizeof(char)*INPUT_STRING_SIZE+200);

    char curDir[100];
    char *temp;
    while(1)
    {
        mode = NORMAL;
        getcwd(curDir, 100);
        inputString = readline("$ ");

        if(strcmp(inputString, "exit\n") == 0)
            exit(0);

        cmdArgc = parse(inputString, cmdArgv, &supplement, &mode);

        if(strcmp(*cmdArgv, "cd") == 0)
        {
            chdir(cmdArgv[1]);
        }
        else
            execute(cmdArgv, mode, &supplement);
    }
    return 0;
}

int parse(char *inputString, char *cmdArgv[], char **supplementPtr, int *modePtr)
{
    int cmdArgc = 0, terminate = 0;
    char *srcPtr = inputString;
    //printf("parse fun%sends", inputString);
    while(*srcPtr != '\0' && terminate == 0)
    {
        *cmdArgv = srcPtr;
        cmdArgc++;
        //printf("parse fun2%sends", *cmdArgv);
        while(*srcPtr != ' ' && *srcPtr != '\t' && *srcPtr != '\0' && *srcPtr != '\n' && terminate == 0)
        {
            switch(*srcPtr)
            {
                case '&':
                    *modePtr = BACKGROUND;
                    break;
                case '|':
                    *modePtr = PIPELINE;
                    *cmdArgv = '\0';
                    srcPtr++;
                    while(*srcPtr == ' ' || *srcPtr == '\t')
                        srcPtr++;
                    *supplementPtr = srcPtr;
                    //chop(*supplementPtr);
                    terminate = 1;
                    break;
            }
            srcPtr++;
        }
        while((*srcPtr == ' ' || *srcPtr == '\t' || *srcPtr == '\n') && terminate == 0)
        {
            *srcPtr = '\0';
            srcPtr++;
        }
        cmdArgv++;
    }
    /*srcPtr++;
    *srcPtr = '\0';
    destPtr--;*/
    *cmdArgv = '\0';
    return cmdArgc;
}

void chop(char *srcPtr)
{
    while(*srcPtr != ' ' && *srcPtr != '\t' && *srcPtr != '\n')
    {
        srcPtr++;
    }
    *srcPtr = '\0';
}

void execute(char **cmdArgv, int mode, char **supplementPtr)
{
    pid_t pid, pid2;
    FILE *fp;
    int mode2 = NORMAL, cmdArgc, status1, status2;
    char *cmdArgv2[INPUT_STRING_SIZE], *supplement2 = NULL;
    int myPipe[2];
    if(mode == PIPELINE)
    {
        if(pipe(myPipe))                    //create pipe
        {
            fprintf(stderr, "Pipe failed!");
            exit(-1);
        }
        parse(*supplementPtr, cmdArgv2, &supplement2, &mode2);
    }
    pid = fork();
    if( pid < 0)
    {
        printf("Error occured");
        exit(-1);
    }
    else if(pid == 0)
    {

        switch(mode)
        {
            case PIPELINE:
                close(myPipe[0]);        //close input of pipe
                dup2(myPipe[1], fileno(stdout));
                close(myPipe[1]);
                break;
        }
        execvp(*cmdArgv, cmdArgv);
    }
    else
    {
        if(mode == BACKGROUND)
            ;
        else if(mode == PIPELINE)
        {
            waitpid(pid, &status1, 0);        //wait for process 1 to finish
            pid2 = fork();
            if(pid2 < 0)
            {
                printf("error in forking");
                exit(-1);
            }
            else if(pid2 == 0)
            {
                close(myPipe[1]);        //close output to pipe
                dup2(myPipe[0], fileno(stdin));
                close(myPipe[0]);
                execvp(*cmdArgv2, cmdArgv2);
            }
            else
            {
                ;//wait(NULL);
                //waitpid(pid, &status1, 0);
                //waitpid(pid2, &status2, 0);
                close(myPipe[0]);
                close(myPipe[1]);
            }
        }
        else
            waitpid(pid, &status1, 0);
            //wait(NULL);
    }
}

ls、cat、sort 等标准命令正常工作。

4

0 回答 0