/*
 * debitub.c
 * - recoit un entier k en arg
 * - alloue un tableau de char s de lg k
 * cree un fils
 * - le pere entre dans une boucle infinie
 * ds laquelle il ecrit les k premiers
 * caracteres ds le tube
 * - le fils lit dans le tube
 * - gere la detection de fin de tube
 ***************************************
 * Davy Dequidt
 * L3 Info Luminy
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

int sigaction(int sig,const struct sigaction *p_action,struct sigaction *p_action_ancien);

int mysignal (int sig, void (*h)(int))
{
        struct sigaction s;
        s.sa_handler=h;
        sigemptyset (&s.sa_mask);
        s.sa_flags=SA_RESTART;
        return sigaction(sig,&s,NULL);
}

unsigned long n = 0;

void capte( int sig ){
  switch( sig ){
    case SIGPIPE :
      printf("Fin de tube\n");
      exit(1);
    case SIGALRM :
      printf("fils a lu : %d ko\n", n/1024);
      alarm(1);
      break;
    default : 
      printf("Signal recu : %d\n", sig);
  }
}

int main(int argc, char *argv[])
{  
  char *s;
  int p[2], pid, k;
  if(argc!=2){
    printf("Usage %s <k>\n",argv[0]);
    exit(0);
  }
  mysignal( SIGPIPE, capte);
  k = atoi(argv[1]);
  s = malloc( k * sizeof *s );
  if( !s ){ perror("malloc"); exit(1); }
  if( pipe(p)<0 ){ perror("pipe"); exit(1); }
  pid = fork();
  if( pid<0 ){
    perror("fork");
    exit(1);
  }
  if( pid==0 ){ /* fils */
    int i;
    mysignal( SIGALRM, capte);
    close( p[1] );
    alarm(1);
    while(1){
      i = read(p[0],s,k);
      if( i==0 ) kill( pid, SIGPIPE );
      n += i;
    }
    exit(0);
  }
  if( pid>0 ){ /* pere */
    printf("pere %d, fils %d\n", getpid(), pid);
    close( p[0] );
    while(1){
      if( write(p[1],s,k)<0 ){
        perror("write");
        exit(1);
      }
    }
    free(s);
  }
}

