#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

#define BUFSIZE 512

/*
 * Programa pai estabelece um pipe entre
 * dois processos filhos: o primeiro le o pipe
 * e o segundo le o terminal e escreve para o pipe.
 * Simbolo de pipe utilizado: "!"
 *
 * Jose Rogado
 */
main(int argc, char *argv[])
{
    pid_t pid1, pid2;
    int count, status;
    int pipeID[2];
    char buffer[BUFSIZE];
	int i, j;

    if (argc < 4) {
        printf("Usage: %s <arg1> ! <arg2>\n", argv[0]);
        exit(1);
    }
	// Parse args
	i = 1;
	while (strcmp(argv[i], "!") != 0) {
		printf("%s ", argv[i]);
		i++;
	}
	printf("\nSeparator %s\n", argv[i]);
	// Terminate arg list for arg1
	argv[i] = 0;
	// Skip separator
	i++;
	for (j = i; j < argc; j++) {
		printf("%s ", argv[j]);
	}
	printf("\n");
    // open a pipe
    if (pipe(pipeID) < 0) {
        perror("pipe");
        exit(1);
    }
    printf("Parent process: %d\n", getpid());

    /* fork another process */
    pid1 = fork();
    if (pid1 < 0) {       /* error occurred */
        perror("Fork Failed");
        exit(-1);
    } else if (pid1 == 0) {
        /* 1st child process */
        printf("Writer process: %d execing: %s %s\n", getpid(), argv[1], argv[2]);
        fflush(stdout);
        /* Redirect stdout to the write half of pipe */
        if (dup2(pipeID[1], 1) < 0){
            perror("dup2");
            exit(-1);
        }
        execvp(argv[1], &argv[1]);
        perror("exec");
        exit(1);
    } else {
        // /* Fork another process */
        pid2 = fork();
        if (pid2 < 0) {  /* error occurred */
	        perror("Fork Failed");
            exit(-1);
        } else if (pid2 == 0) {
            /* Redirect stdin to the read half of pipe */
            printf("Reader process: %d execing: %s %s\n", getpid(), argv[i], argv[i+1]);
            if (dup2(pipeID[0], 0) < 0){
                perror("dup2");
                exit(-1);
            }
			execvp(argv[i], &argv[i]);
			perror("exec");
			exit(1);
        } else {
            printf ("\nWaiting for process %d\n", pid1);
            waitpid(pid1, &status, NULL);
			write(pipeID[1], "\nEND\n", 5);
			write(pipeID[1], EOF, 1);
			close(pipeID[1]);
			close(pipeID[0]);
 			// printf ("\nWaiting for process %d\n", pid2);
            // waitpid(pid2, &status, NULL);
            printf ("Parent Process Exiting\n");
            exit(0);
        }
    }
}
