problem with implementing pipe

From: Greg (djbitchpimp_at_snowboard.com)
Date: 09/29/04


Date: 28 Sep 2004 23:45:57 -0700

I am trying to implement the UNIX pipe command using C but with the
"->" operator. Everything works fine with 1 pipe, but when I try to
use 2 or more, it hangs up when reading the pipe_in filestream. If
ANYONE could offer ANY suggestion as to why this is happening it would
be much appreciated.

Thanks in advance!

#define MAX_PIPES 5
#define MAX_CMD_LEN 255

#include <string.h>
#include <stdio.h>

// global vars

char piped_cmds [MAX_PIPES][MAX_CMD_LEN] ;
int numPipes ;

// fcn prototypes

int pipeCmds (int cmd1, int cmd2) ;
char *stripFirstChar (char *str) ;
char *stripLastChar (char *str) ;
void splitPipes (char *toSplit) ;
int isPipe (char *cmd) ;

int main () {
        int i ;
        char command [] = "ps aux -> grep greg -> wc" ;
        //char command [] = "cat .bash_profile -> tail -15 -> tail -10 ->
tail -5 -> tail -3" ;
        //char command [] = "ps aux -> grep greg -> grep 5 -> grep 3 -> less"
;
        char *noPipe = "ps aux" ;

        //numPipes = 0 ;
        if (isPipe (command)) {
                splitPipes (command) ;
                for (i = 0; i < numPipes - 1; i++) {
                        if (!pipeCmds (i, i + 1))
                                printf ("Pipe failed\n") ;
                        else
                                printf ("Pipe succeeded\n") ;
                                
                }
        }
        printf ("Exit\n") ;
}

int pipeCmds (int cmd1, int cmd2) {
        FILE *pipe_in ;
        FILE *pipe_out ;
        char *my_string ;
        int nbytes = 100;
        int bytes_read;
        char readbuf[MAX_CMD_LEN];

        printf ("Piping [%i] %s -> [%i] %s\n", cmd1, piped_cmds [cmd1], cmd2,
             piped_cmds [cmd2]) ;
// open pipes
        pipe_in = popen (piped_cmds [cmd1], "r") ;
        printf ("Input pipe open\n") ;
        pipe_out = popen (piped_cmds [cmd2], "w") ;
        printf ("Output pipe open\n") ;
        
        if ((!pipe_in) || (!pipe_out)) {
                fprintf (stderr, "One or both pipes failed.\n") ;
                return 0 ;
        }

        printf ("Transferring file contents...\n") ;
// while(fgets(readbuf, 250, pipe_in))
// fputs(readbuf, pipe_out);
        while (!feof (pipe_in)) {
                printf ("Reading input pipe...\n") ;
/****************program hangs here**************************/
                fgets (readbuf, MAX_CMD_LEN, pipe_in);
                if(feof(pipe_in))
                        break;
                printf("%s", readbuf) ;
                fputs (readbuf, pipe_out) ;
        }

        pclose (pipe_in) ;
        pclose (pipe_out) ;
        printf ("Pipes closed\n") ;

        return 1 ;
        

}

char *stripFirstChar (char *str) {
        str++ ;
        return str ;
}

char *stripLastChar (char *str) {
        char *temp = str ;
        while (*temp != '\0') {
                temp++ ;
        }
        temp-- ;
        *temp = '\0' ;
        //printf ("\"%s\"\n", temp) ;

        return str ;
}

void splitPipes (char *toSplit) {
        char *tokenPtr = NULL ;
        int i ;
        
        for (tokenPtr = strtok (toSplit, "->"); tokenPtr != NULL;
                tokenPtr = strtok (NULL, "->"))
        {
                        strcpy (piped_cmds [numPipes], tokenPtr) ;
                        numPipes++ ;
        }

        for (i = 1; i < numPipes; i++) {
                strcpy (piped_cmds [i], stripFirstChar (piped_cmds [i])) ;
        }

        for (i = 0; i < numPipes - 1; i++) {
                strcpy (piped_cmds [i], stripLastChar (piped_cmds [i])) ;
        }

        
        for (i = 0; i < numPipes; i++) {
                printf ("[%i] \"%s\"\n", i, piped_cmds [i]) ;
        }
}

int isPipe (char *cmd) {
        
        if (strchr (cmd, '>')) {
                printf ("%s contains at least 1 pipe\n", cmd) ;
                return 1 ;
        }
        else
                printf ("%s contains no pipes\n", cmd) ;
                return 0 ;
}



Relevant Pages

  • pipe(2), read/write, maximums and behavior.
    ... I've seen a few shells claim to limit pipe sizes to 8 512Byte buffers. ... write 2097152KB (and the child receives the 2GB-4K buffer upon read). ... int controlfd; ... void getout(int stat, char * msg) { ...
    (Linux-Kernel)
  • [PATCH] sys_vmsplice
    ... Attempt to steal a page from a pipe buffer. ... int ret, do_wakeup, i; ... unsigned int this_len; ...
    (Linux-Kernel)
  • Re: Tk and io from console program
    ... int main(int argc, char *argv) ... in pipe, it has a stdin and an stdout, but not a CRT console. ... Use fgetcinstead (and use int type for variable lettre, to be sure to handle return code correctly). ...
    (comp.lang.tcl)
  • vmsplice cant work well
    ... Use vmsplice to fill some user memory into a pipe. ... static inline int xerror ... int do_vmsplice(int fd, void *buffer, int len) ...
    (Linux-Kernel)
  • Re: Data consistency and "other" synchronization methods
    ... int someVariable; ... If the guarantee is not there and cannot be deduced from other ... Alexander Terekhov proposed to implement the pipe on top of strongly ... I don't know much about Unix internals, but I'd start by looking at ...
    (comp.programming.threads)