/* Unnamed pipes. */ #include #include #include #include #include #include #define BUFSIZE 2048 #define EVEN_BUFSIZE 1024 #define massert( cond, msg ) \ if( cond ) { \ perror(msg); \ exit(-1); \ } #define WC "/usr/bin/wc" /* * 1. pipe: r & w. * 2. fork * 3. Parent closes `r`, child closes `w` * 4. Parent reads a file and writes even letters. * 5. On file end parent sends EOF ( -1 ) and close read descriptor. */ int main( int argc, char* argv[] ) { pid_t chd_pid; int pfd[2]; massert( pipe(pfd) < 0, "pipe"); chd_pid = fork(); if( chd_pid > 0 ) { /* Parent. */ int fd, ret; char buf[BUFSIZE], even_buf[EVEN_BUFSIZE]; close( pfd[0] ); /* If no file, read stdin. Bad and not taskcompatible idea? */ if( argc > 1 ) { massert((fd = open( argv[1], O_RDONLY )) < 0, "open"); } else { fd = STDIN_FILENO; } while(( ret = read( fd, buf, BUFSIZE)) > 0 ) { int i, j; for( i = 1, j = 0; i < ret; i+=2 ) { even_buf[j++] = buf[i]; } write( pfd[1], even_buf, j); } /* The end of PIPED connection. */ close( pfd[1] ); /* Good tone.*/ close( fd ); /* Don't care of case with stdin? */ wait( NULL ); } else if( chd_pid == 0 ) { /* Child.*/ close( pfd[1] ); massert(dup2( pfd[0], STDIN_FILENO ) < 0, "dup2"); massert(execl( WC, WC, "--", (char*)0 ) < 0, "execl"); close(pfd[0]); exit(0); } else { /* Error. */ perror("fork"); _exit(-1); } /* Do some clever things. */ /* Nope. */ return 0; }