Does this multiple pipes code in C makes sense?

后端 未结 5 1550
暖寄归人
暖寄归人 2020-12-18 13:39

I\'ve created a question about this a few days. My solution is something in the lines of what was suggested in the accepted answer. However, a friend of mine came up with th

5条回答
  •  鱼传尺愫
    2020-12-18 14:31

    Both in this question and in another (as linked in the first post), ephemient suggested me a solution to the problem without messing with the parents file descriptors as demonstrated by a possible solution in this question.

    I didn't get his solution, I tried and tried to understand but I can't seem to get it. I also tried to code it without understanding but it didn't work. Probably because I've failed to understand it correctly and wasn't able to code it the it should have been coded.

    Anyway, I tried to come up with my own solution using some of the things I understood from the pseudo code and came up with this:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define NUMPIPES 5
    #define NUMARGS 10
    
    int main(int argc, char *argv[]) {
        char *bBuffer, *sPtr, *aPtr = NULL, *pipeComms[NUMPIPES], *cmdArgs[NUMARGS];
        int aPipe[2], bPipe[2], pCount, aCount, i, status;
        pid_t pid;
    
        using_history();
    
        while(1) {
            bBuffer = readline("\e[1;31mShell \e[1;32m# \e[0m");
    
            if(!strcasecmp(bBuffer, "exit")) {
                return 0;
            }
    
            if(strlen(bBuffer) > 0) {
                add_history(bBuffer);
            }
    
            sPtr = bBuffer;
            pCount =0;
    
            do {
                aPtr = strsep(&sPtr, "|");
    
                if(aPtr != NULL) {
                    if(strlen(aPtr) > 0) {
                        pipeComms[pCount++] = aPtr;
                    }
                }
            } while(aPtr);
    
            cmdArgs[pCount] = NULL;
    
            for(i = 0; i < pCount; i++) {
                aCount = 0;
    
                do {
                    aPtr = strsep(&pipeComms[i], " ");
    
                    if(aPtr != NULL) {
                        if(strlen(aPtr) > 0) {
                            cmdArgs[aCount++] = aPtr;
                        }
                    }
                } while(aPtr);
    
                cmdArgs[aCount] = NULL;
    
                // Do we have a next command?
                if(i < pCount-1) {
                    // Is this the first, third, fifth, etc... command?
                    if(i%2 == 0) {
                        pipe(aPipe);
                    }
    
                    // Is this the second, fourth, sixth, etc... command?
                    if(i%2 == 1) {
                        pipe(bPipe);
                    }
                }
    
                pid = fork();
    
                if(pid == 0) {
                    // Is this the first, third, fifth, etc... command?
                    if(i%2 == 0) {
                        // Do we have a previous command?
                        if(i > 0) {
                            close(bPipe[1]);
                            dup2(bPipe[0], STDIN_FILENO);
                            close(bPipe[0]);
                        }
    
                        // Do we have a next command?
                        if(i < pCount-1) {
                            close(aPipe[0]);
                            dup2(aPipe[1], STDOUT_FILENO);
                            close(aPipe[1]);
                        }
                    }
    
                    // Is this the second, fourth, sixth, etc... command?
                    if(i%2 == 1) {
                        // Do we have a previous command?
                        if(i > 0) {
                            close(aPipe[1]);
                            dup2(aPipe[0], STDIN_FILENO);
                            close(aPipe[0]);
                        }
    
                        // Do we have a next command?
                        if(i < pCount-1) {
                            close(bPipe[0]);
                            dup2(bPipe[1], STDOUT_FILENO);
                            close(bPipe[1]);
                        }
                    }
    
                    execvp(cmdArgs[0], cmdArgs);
                    exit(1);
                } else {
                    // Do we have a previous command?
                    if(i > 0) {
                        // Is this the first, third, fifth, etc... command?
                        if(i%2 == 0) {
                            close(bPipe[0]);
                            close(bPipe[1]);
                        }
    
                        // Is this the second, fourth, sixth, etc... command?
                        if(i%2 == 1) {
                            close(aPipe[0]);
                            close(aPipe[1]);
                        }
                    }
    
                    // wait for the last command? all others will run in the background
                    if(i == pCount-1) {
                        waitpid(pid, &status, 0);
                    }
    
                    // I know they will be left as zombies in the table
                    // Not relevant for this...
                }
            }
        }
    
        return 0;
    }
    

    This may not be the best and cleanest solution but it was something I could come up with and, most importantly, something I can understand. What good is to have something working that I don't understand and then I'm evaluated by my teacher and I can't explain to him what the code is doing?

    Anyway, what do you think about this one?

提交回复
热议问题