/********************************************************
 * This program runs "ls -al | grep arg1 > arg2 "       *
 * This uses the strategy that parent does redirection  *
 * before forking, so child does not need to do it.     *
 ********************************************************/

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc,char**argv) 
{
    if (argc < 3) {
        fprintf(stderr, "usage: lsgrep arg1 arg2\n");
        exit(1);
    }
    // Parent saves stdin/stdout
    int tempin = dup(0);
    int tempout = dup(1);

    int fdpipe[2];
    pipe(fdpipe);   // pipe must be created in parent so both children have access

    // Strategy: parent does the redirection before fork()
    dup2(fdpipe[1],1);  // Now stdout is a copy of the read end of pipe
    close(fdpipe[1]);  // Having made a copy, the original is no longer needed 

    // fork for "ls"
    int ret= fork();
    if(ret==0) {
        //  This is child process.
        close(fdpipe[0]);  // In child (for ls) the writing end of pipe is not needed
        char * args[3];
        args[0]="ls";
        args[1]="-al";
        args[2]=NULL;
        execvp(args[0], args);
	// If we reach here, there is an error in execvp
        perror("execvp");
        exit(1);
    }

    // We are still in parent process after first fork.
    // We are to set things up for "grep"
    dup2(fdpipe[0], 0);  // Set stdin to a copy of the reading end of pipe
    close(fdpipe[0]);   // The original is no longer needed, now a copy is made 
    //create outfile
    int fd=open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0600);
    if (fd < 0){
        perror("open failed");
        exit(1);
    }  
    dup2(fd,1);  // redirect stdout to a copy of fd
    close(fd);   // original fd no longer needed

    // fork for grep
    ret= fork();
    if(ret==0) {
        char * args[3];
        args[0]="grep";
        args[1]=argv[1];
        args[2]=NULL;
        execvp(args[0], args);
        // error in execvp
        perror("execvp failed");
        exit(1);
    }
    // Restore stdin/stdout
    dup2(tempin,0);
    dup2(tempout,1);
    // Parent waits for grep process to complete
    waitpid(ret,NULL);
    printf("All done!!\n");
} 

