#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <fcntl.h>   
#include <stdio.h>
#include <string.h>
#include <errno.h>

# define VEZES 5

int s; /* semaforo a ser compartilhado entre pai e filho */

void filho();
void pai();
void i_p(); /* operacao para inicializar estrutura descrevendo P() */
void i_v(); /* operacao para inicializar estrutura descrevendo V() */

int main(int argc, char **argv) {
   
  key_t chave;
  int pid, oflag;
  union semun arg;
  struct semid_ds sinfo;

  i_p();
  i_v();

  /* obtem chave para descricao de semaforo */
  chave = ftok("arq",1);

  /* prepara flags para chamada a semget */
  oflag = IPC_CREAT | IPC_EXCL; /* criacao, indique erro se semaforo ja' existir */ 
  /* atencao: pode-se excluir o flag IPC_EXCL para fazer um prog. que "elimine" um sem. pendurado */
  oflag |= S_IRUSR | S_IWUSR; /* permita leitura e alteracao por esse processo */ 

  if ((s=semget(chave,1,oflag))<0) 
    printf("%s\n",strerror(errno));
  else {
    printf("conseguiu abrir semaforo\n");
    arg.buf = &sinfo;
    arg.val = 0; /* valor inicial do semaforo */
    if (semctl(s,0,SETVAL,arg)<0) 
      printf("%s\n",strerror(errno));
    else {
      printf("conseguiu inicializar semaforo\n");
      if ((pid=fork())<0)
        printf("%s\n",strerror(errno));
      else if (pid==0)
        filho();
      else {
        pai();
        /* nao esquecam que e' necessario remover o semaforo: */
        if (semctl(s,0,IPC_RMID,1)<0)
          printf("%s\n",strerror(errno));
        else
          printf("conseguiu fechar semaforo\n");
      }
    } 
  } 
}

struct sembuf p_op;
void i_p() {
  p_op.sem_num=0;
  p_op.sem_op=-1; 
  p_op.sem_flg=0;
}

struct sembuf v_op;
void i_v() {
  v_op.sem_num=0;
  v_op.sem_op=1; 
  v_op.sem_flg=0;
}

void filho() {
  int i;
  for (i=0;i<VEZES;i++) {
    printf("filho\n");
    sleep(2); /* faz pai ficar esperando... */
    semop(s,&v_op,1);
  }
}

void pai() {
  int i;
  for (i=0;i<VEZES;i++) {
    semop(s,&p_op,1); /* espera filho ... */
    printf("pai\n");
  }
}