#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>

#include <string.h>

#define USAGE "usage: %s <tmpfile>\n"

#ifndef MAPFILE
#define MAPFILE 0 /*für nicht BSD-Systeme*/
#endif

#define MAPSIZE 64

extern int errno;
static volatile sig_atomic_t sflag;
static sigset_t signal_neu, signal_alt, signal_leer;
char *mapped;
void sigfunc1(int);
void sigfunc2(int);


void signale_mmap(void)
{
  if(signal(SIGSEGV, sigfunc1) == SIG_ERR)
   {
     fprintf(stderr, "Konnte signalhandler für SIGSEGV nicht einrichten......\n");
     exit(0);
   }
  if(signal(SIGBUS, sigfunc2) == SIG_ERR)
   {
     fprintf(stderr, "Konnte signalhandler für SIGBUS nicht einrichten......\n");
     exit(0);
   }

/*Wir entfernen alle Signale aus der Signalmenge*/
  sigemptyset(&signal_leer);
  sigemptyset(&signal_neu);
/*Wir fürgen die zwei Signal SIGSEGV und SIGBUS zur Signalmenge hinzu*/
  sigaddset(&signal_neu, SIGSEGV);
  sigaddset(&signal_neu, SIGBUS);

/*Jetzt setzen wir signal_neu und sichern die noch aktuelle Signalmaske in signal_alt*/
if(sigprocmask(SIG_BLOCK, &signal_neu, &signal_alt) < 0)
exit(0);
}

void sigfunc1(int sig)
{
  printf("SIGSEGV: Es wurde versucht auf einen unerlaubten Speicherbereich zu schreiben\n");
  exit(0);
}

void sigfunc2(int sig)
{
  printf("SIGBUS: Der Speicherbereich ist nicht mehr gültig\n");
  exit(0);
}


int main(int argc, char *argv[])
{
  int fd;
  int n,lines=1;
  char string[MAPSIZE];

  if(argc!=2)
   {
     fprintf(stderr,USAGE,*argv);
     exit(1);
   }

  signale_mmap() ;

  if((fd=open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0777))<0)
   {
     perror("open");
     exit(1);
   }

/*Größe der Datei festlegen*/
  lseek(fd, 2*MAPSIZE-1, SEEK_SET);
  write(fd,"",1);

/*mapped-Speicherberreich festlegen*/
  if((mapped=(char*)mmap(0,2*MAPSIZE,PROT_WRITE|PROT_READ,MAPFILE|MAP_SHARED,fd,0)) ==(caddr_t )-1)
  {
    perror("mmap: ");
    exit(1);
  }

  close(fd);

  while(1)
    {
      n=read(STDIN_FILENO,string,2*MAPSIZE);
      mapped+=n; /*aktuelle Position im Speicherbereich*/
      memcpy(mapped, string, n);
      msync(mapped,2*MAPSIZE,MS_SYNC);
    }
  exit(0);
}