#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.
 *
 * Jose Rogado
 */
main(int argc, char *argv[])
{
    pid_t pid, pid2;
    int count, status;
    int pipeID[2];
    char buffer[BUFSIZE];


    // open a pipe
    if (pipe(pipeID) < 0) {
        perror("pipe");
        exit(1);
    }
    printf("Parent process: %d\n", getpid());

    /* fork another process */
    pid = fork();
    if (pid < 0) {       /* error occurred */
        perror("Fork Failed");
        exit(-1);
    } else if (pid == 0) {
        /* child process */

        printf("Reader process: %d\n", getpid());
        fflush(stdout);
        /* Redirect stdin to the read half of pipe */
#if 0
        if (close(0) < 0) {
            perror("close");
            exit(-1);
        }
        if (dup(pipeID[0]) < 0){
            perror("dup");
            exit(-1);
        }
#else
        if (dup2(pipeID[0], 0) < 0){
            perror("dup2");
            exit(-1);
        }
#endif
        while (1) {
            bzero(buffer, sizeof(buffer));

            if (read(0, buffer, sizeof(buffer))< 0) {
                perror("write");
                break;
            }
            printf("Reader Process %d: %s\n", getpid(), buffer);
        }
        printf("Process %d exiting\n", getpid());
        exit(0);
    } else {
        /* Fork another process */
        pid2 = fork();
        if (pid2 < 0) {  /* error occurred */
	        perror("Fork Failed");
            exit(-1);
        } else if (pid2 == 0) {
            printf("Writer process: %d\n", getpid());

            /* Redirect stdout to the write half of pipe */
            if (dup2(pipeID[1], 1) < 0){
                perror("dup2");
                exit(-1);
            }

            while(1) {
                // loop reading input to send to sibling
                count = my_getline(buffer, sizeof(buffer));
                if (count < 0) {
                    printf("Writer Process %d %s\n", getpid(), count);
                    break;
                }
                if (write(1, buffer, count) < 0) {
                    perror("write");
                    break;
                }
                printf("Writer Process %d: %s\n", getpid(), buffer);
            }
            printf("Process %d exiting\n", getpid());
            exit(0);
        } else {
            wait(&status);
            kill (pid, SIGKILL);
            printf ("End of File\n");
            exit(0);
        }
    }
}

int my_getline (char *buffer, int bufsize)
{
    int count = 0;
    char *p;

    bzero(buffer, bufsize);
    p = fgets(buffer, bufsize, stdin);

    if (p)
        count = strlen(p);
    else
        count = -1;

    // printf("Sending %d: %s", count, buffer);
    return count;
}
