#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    int pid, pid_ls, pid_grep, fd[2];
    if (argc != 3) {
        printf("Usage: pipeEx4 dirname string\n");
        return (-1); }
    printf("Parent process: Grepping %s for %s\n", argv[1], argv[2]);
    if (pipe(fd)==-1) {
        printf("Parent process: Failed to create pipe\n");
        return (-2); }
    // Fork a process to run grep
    pid_grep = fork();
    if (pid_grep == -1) {
        printf("Parent process: Could not fork process to run grep\n");
        return (-3); } 
    else if (pid_grep==0) {
         printf("Child process 1: grep child will now run\n");
         // Set fd[0] (stdin) to the read end of the pipe
         if (dup2(fd[0], STDIN_FILENO) == -1) {
             printf("Child process 1: grep dup2 failed\n");
             return (-4); }
         // Close the pipe now that we've duplicated it
         close(fd[0]);
         close(fd[1]);
         // Setup the arguments/environment to call
         char * new_argv[] = { "/bin/grep", argv[2], 0 };
         char * envp[] = { "HOME=/", "PATH=/bin:/usr/bin", "USER=brandon", 0 };
         // Call execve(2) which will replace the executable image of this process
         execve(new_argv[0], &new_argv[0], envp);
         // Execution will never continue in this process unless execve returns
         // because of an error
         printf("Child process 1: Oops, grep failed!\n");
         return (-5); }
    // Fork a process to run ls
    pid_ls = fork();
    if (pid_ls == -1) {
        printf("Parent Process: Could not fork process to run ls\n");
        return (-6); } 
    else if (pid_ls == 0) {
         printf("Child process 2: ls child will now run\n");
         printf("---------------------\n");
         // Set fd[1] (stdout) to the write end of the pipe
         if (dup2(fd[1], STDOUT_FILENO) == -1) {
             fprintf(stderr, "ls dup2 failed\n");
             return (-7); }
         // Close the pipe now that we've duplicated it
         close(fd[0]);
         close(fd[1]);
         // Setup the arguments/environment to call
         char *new_argv[] = { "/bin/ls", "-la", argv[1], 0 };
         char *envp[] = { "HOME=/", "PATH=/bin:/usr/bin", "USER=brandon", 0 };
         // Call execve(2) which will replace the executable image of this process
         execve(new_argv[0], &new_argv[0], envp);
         // Execution will never continue in this process unless execve returns
         // because of an error
         fprintf(stderr, "child: Oops, ls failed!\n");
         return (-8); }
    // Parent doesn't need the pipes
    close(fd[0]);
    close(fd[1]);
    printf("Parent: Parent will now wait for children to finish execution\n");
    // Wait for all children to finish
    while (wait(NULL) > 0);
    printf("---------------------\n");
    printf("parent: Children has finished execution, parent is done\n");
    return 0; }
