/*
 * Outro exemplo de uso de pipes.  Este pai controla a entrada padrão,
 * a saída padrão e a saída de erros do filho. Pobre filho!!! 
 */

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

   
int  main (void) {
  int pipe_entrada_padrao_filho[2];
  int pipe_saida_padrao_filho[2];
  int pipe_saida_erros_filho[2];
    
  pipe (pipe_entrada_padrao_filho);
  pipe (pipe_saida_padrao_filho);
  pipe (pipe_saida_erros_filho);

  if (fork() != 0) { /* Processo pai */
    /* Entrada padrão: pai escreve, filho lê */
    close(pipe_entrada_padrao_filho[0]);
    FILE* pai_escreve = fdopen (pipe_entrada_padrao_filho[1],"w");
    /* Saída padrão: pai lê, filho escreve */
    FILE* pai_le = fdopen (pipe_saida_padrao_filho[0],"r"); 
    close(pipe_saida_padrao_filho[1]);
    /* Saída erros padrão: pai lê, filho escreve */
    FILE* pai_le_erros = fdopen (pipe_saida_erros_filho[0],"r");
    close(pipe_saida_erros_filho[1]);

    fprintf(pai_escreve, "Oi,filho!\n");
    fflush(pai_escreve);

    char buffer_leitura_pai[100];
    dup2(pipe_saida_padrao_filho[0], 0); 
    fscanf(pai_le,"%s", buffer_leitura_pai); 
    printf("Pai recebeu mensagem do filho: %s\n", buffer_leitura_pai);  
    fscanf(pai_le_erros,"%s", buffer_leitura_pai);
    printf("Pai recebeu mensagem de erro do filho: %s\n", buffer_leitura_pai); 
  }
  else { /* Processo filho */
    /* Entrada padrão: pai escreve, filho lê */
    dup2(pipe_entrada_padrao_filho[0], 0); 
    close(pipe_entrada_padrao_filho[1]); 
    /* Saída padrão: pai lê, filho escreve */ 
    close(pipe_saida_padrao_filho[0]);
    dup2(pipe_saida_padrao_filho[1], 1); 
    /* Saída erros padrão: pai lê, filho escreve */
    close(pipe_saida_erros_filho[0]);
    dup2(pipe_saida_erros_filho[1], 2); 

    char buffer_leitura_filho[100];
    scanf("%s", buffer_leitura_filho); 
    printf("Oi,pai!");
    fprintf(stderr,"Ops!");
  }

  return 0;
}