/*  
 * ######
 * ## SEMA1.c
 * ## ~~~~~~~
 * ## 04.02.1995: Creation T
 * ## 04.02.2008:
 * ######
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

  typedef void (*sighandler_t) (int);

  extern int errno;

  key_t      key = 3;
  int        semid, nsems, semnum;

  struct sembuf sops;

  union  semun {
	  int                 val;
	  struct semid_ds    *buf;
	  unsigned short int *array;
	  struct seminfo     *__buf;
  } arg;


void my_stop_1()
{
  int kr;
  semnum  = 0;
  arg.val = 0;
  
  kr = semctl( semid, semnum, SETVAL, arg );
  if ( kr == 1 ) {
    perror( " SIGUSR1> Pb. initialisation SEMAPHORE" );
  } else {
    printf( " SIGUSR1> Remise a Zero  SEMAPHORE( 3, 0 )\n" );
  }
}

void my_stop_2()
{
  int kr;
  semnum = 0;

  kr = semctl(semid, semnum, IPC_RMID, NULL);
  if ( kr == -1 ) {
    perror( " SIGUSR2> Pb. destruction semaphore" ); exit( 2 );
  } else {
    printf( " SIGUSR2> Destruction SEMAPHORE(3)\n" );
  }
  exit( 0 );
}


main()
{
  int    kr, val;
  char   SS[ 1024 ];

  signal( SIGUSR1, (sighandler_t) my_stop_1 );
  signal( SIGUSR2, (sighandler_t) my_stop_2 );

/* Creation/attachement du groupe 3 constitue de 1 semaphore */
  
  printf( " sema1> Ouverture SEMAPHORE(3) - Nombre = 1)\n");
  printf( " sema1> \n");

  key   = 3;
  nsems = 1;

  semid = semget( key, nsems, 0640 | IPC_CREAT );
  if ( semid == -1 ) {
    perror( " sema1> Creation SEMAPHORE impossible" ); exit( 1 );
  }

/* Initialisation du semaphore ( key, semnum ) a 0 */
  semnum  = 0;
  arg.val = 0;
  
  kr = semctl( semid, semnum, SETVAL, arg );
  if ( kr != 0 ) {
    perror( " sema1> Pb. initialisation SEMAPHORE" );
  }

  printf( " sema1> Pour deverouiller la ressource, lancer sema2\n");
  printf( " sema1> Pour remettre a Zero le SEMAPHORE(3), faire kill -%d %d\n"
		  , SIGUSR1, getpid() );
  printf( " sema1> Pour arreter le programme, faire ^C ou bien kill -%d %d\n"
		  , SIGUSR2, getpid() );

/* precaution deverouillage automatique semop */
  sops.sem_flg = SEM_UNDO;

/* boucle */
  for (;;) {
    printf( " sema1> Entrez un commentaire ----> " ); scanf( "%s", &SS );
    printf( " sema1> Echo du commentaire   - - > %s\n", SS );
    
    sops.sem_num =  0;    
    sops.sem_op  = -1; /* < 0 :  demande d'un droit */

    kr = semop( semid, &sops, 1 );
    if ( kr == -1 ) {
      if ( errno == 4 ) {
        printf( " sema1> Deblocage par signal\n" );
      } else {
        printf( " sema1> Erreur decrementation semaphore\n" );
      }
    }
    printf( " sema1> Liberation\n" );
    semnum = 0;
    
    val = semctl( semid, semnum, GETVAL, NULL );
    if ( val == -1 ) {
      perror( " sema1> Pb. recuperation valeur semaphore" );
    }
    printf( " sema1> Valeur du semaphore = %d\n", val );
  }
}
/* --- fin  sema1.c  --- */
