#include <stdio.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>

/*Musste ich einbauen da bei mir keine union semun vorhanden war*/
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/*union semun ist in <sys/sem.h> definiert*/
#else /*Wir müssen es selbst definieren (siehe man-Page semctl)*/
union semun{
  int val;
  struct semid_ds *buf;
  unsigned short int *array;
  struct seminfo *__buf;
} ;
#endif


int main()
{
  key_t key;
  int sem_id;
  struct sembuf lock_it;
  union semun options;
  int i;

  key = ftok(".", 'a');

/*Wir erzeugen eine neue Semaphore*/
  sem_id = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
  if(sem_id == -1)
    { perror("semget"); exit(0); }
  printf("Semaphore id=%d\n", sem_id);

  options.val = 1;
   /*Wir setzen option.val in union semun auf 1*/
  i=semctl(sem_id, 0, SETVAL, options);
  if(i == -1)
     { perror("semctl"); exit(0); }

/*Wir fragen ab ob der Wert der Semaphorvariable ungleich 0 ist*/
/*Wir haben ihn ja gerade zuvor auf 1 gesetzt*/
  if (semctl(sem_id, 0, GETVAL, 0) == 0)
   {
     printf("Der Wert der Semaphorvariable darf nicht 0 sein........\n");
     exit(1);
   }

  i = semctl(sem_id, 0, GETVAL, 0);
  printf("Der Wert der Semaphorvariable des Indexes 0 ist %d (1=unlock,0=lock)\n", i);

/*Jetzt setzen wir die Semaphorevariable auf 0 für lock*/
  lock_it.sem_num = 0; /*Nummer der Semaphorvariable in der Menge*/
   /*Operation = -1 Damit wird die Semaphorvariable val subtrahiert*/
  lock_it.sem_op = -1;
  lock_it.sem_flg = IPC_NOWAIT; /*Prozess wird nicht suspendiert*/
/*Jetzt wollen wir den Prozess sperren*/
  if (semop(sem_id, &lock_it, 1) == -1)
    {
      printf("Kann die Semaphore nicht sperren\n");
      exit(1);
    }

/*Testen wir wieder die Semaphorevariable müsste 0 sein*/
  i = semctl(sem_id, 0, GETVAL, 0);
  printf("Der Wert der Semaphorvariable des Indexes 0 ist %d (1=unlock,0=lock)\n", i);


/*Jetzt wollen wir den Prozess wieder freigeben*/
  lock_it.sem_num = 0; /*Nummer der Semaphorvariable in der Menge*/
  /*Wir dekremtieren die Semaphorvariable wieder um den Wert 1*/
  lock_it.sem_op = 1;
  lock_it.sem_flg = IPC_NOWAIT;/*Wieder sofort ausführen es wird nicht gewartet*/
/*Jetzt wollen wir wieder unlocken*/
  if ((i=semop(sem_id, &lock_it, 1)) == -1)
    {
      printf("Kann die Sperre der Semaphore nicht mehr aufheben......\n");
      exit(1);
    }

/*Müsste wieder 1 sein*/
  i = semctl(sem_id, 0, GETVAL, 0);
  printf("Der Wert der Semaphorvariable des Indexes 0 ist %d (1=unlock,0=lock)\n", i);

/*Wir löschen den Semaphor*/
  i=semctl(sem_id, 0, IPC_RMID, 0);
  if(i == -1)
      perror("semct...IPC_RMID");
return 0;
}