#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FNAME "/tmp/file"

void status(struct flock *lock)
{
  printf("Status: ");
  switch(lock->l_type)
   {
     case F_UNLCK:  printf("F_UNLCK (pid: %d) (Sperre aufgehoben)\n",lock->l_pid);
                    break;
     case F_RDLCK:  printf("F_RDLCK (pid: %d) (Lesesperre)\n", lock->l_pid);
                    break;
     case F_WRLCK:  printf("F_WRLCK (pid: %d) (Schreibsperre)\n", lock->l_pid);
                    break;
     default     :  break;
    }
}


int main(int argc, char **argv)
{
  struct flock lock;
  int fd;
  char puffer[100];
  int x,y;
  pid_t pid;
  unlink(FNAME);
  fd = open(FNAME, O_WRONLY|O_CREAT, 0777);

  memset(&lock, 0, sizeof(struct flock));
  fcntl(fd, F_GETLK, &lock);

  if(lock.l_type==F_WRLCK || lock.l_type==F_RDLCK)
    {
      status(&lock);
      memset(&lock,0,sizeof(struct flock));
      lock.l_type = F_UNLCK;
      if (fcntl(fd, F_SETLK, &lock) < 0)
        printf("Fehler : fcntl(fd, F_SETLK, F_UNLCK)  (%s)\n",strerror(errno));
      else
        printf("Erfolgreich gesetzt : fcntl(fd, F_SETLK, F_UNLCK)\n");
    }


  memset(&lock, 0, sizeof(struct flock));
  lock.l_type = F_WRLCK;
  lock.l_start=0;
  lock.l_whence = SEEK_SET;
  lock.l_len=0;
  lock.l_pid = getpid();
  if (fcntl(fd, F_SETLK, &lock) < 0)
     printf("Fehler bei : fcntl(fd, F_SETLK, F_WRLCK)(%s)\n",strerror(errno));
  else
     printf("Erfolgreich mit : fcntl(fd, F_SETLK, F_WRLCK)\n");
  status(&lock);

  switch(pid=fork())
    {
      case -1  :  exit(0);
      case 0   :  while(1) /*Kindprozess*/
                  {
                    fcntl(fd, F_GETLK, &lock);
                    status(&lock);
                    if(lock.l_type == F_WRLCK)
                      {
                        sleep(1);
                       }
                      else
                        {
                          for(y=0; y<10; y++){
                             sleep(1);
                             write(fd,(char *)"x",1);
                            }
                          exit(0);
                        }
                      }


        default  :   while(1)   /*Eltern*/
                      {
                        for(x=0; x<10; x++){
                          sleep(1);
                           write(fd,(char *)"X",1);
                          }
                       memset(&lock, 0, sizeof(struct flock));
                       lock.l_type = F_UNLCK;

                       if (fcntl(fd, F_SETLK, &lock) < 0)
                          printf("Fehler : fcntl(fd, F_SETLK, F_UNLCK)  (%s)\n",strerror(errno));
                       else
                           printf("Erfolgreich gesetzt : fcntl(fd, F_SETLK, F_UNLCK)\n");
                        status(&lock);
                        wait(NULL);
                        break;
                       }
    }
  close(fd);
  return 0;
}
