#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#ifndef MAPFILE
#define MAPFILE 0 /*für nicht BSD-Systeme*/
#endif

extern int errno;
static volatile sig_atomic_t sflag;
static sigset_t signal_neu, signal_alt, signal_leer;
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,fd1;
  void *speicherquelle, *speicherziel;
  struct stat attr;

  signale_mmap();

  if((fd1=open(argv[1],O_RDONLY)) <0)
    {
      fprintf(stderr,"%s : Konnte %s nicht öffnen\n",strerror(errno),argv[2]);
      exit(0);
    }

  if(( fd=open(argv[2], O_RDWR|O_CREAT,0777)) < 0)
    {
      fprintf(stderr,"%s : Konnte %s nicht erstellen\n",strerror(errno),argv[2]);
      exit(0);
    }

  if(fstat(fd1, &attr) == -1)
    {
      fprintf(stderr,"Fehler bei fstat.......\n");
      exit(0);
    }

/*Größe der Zieldatei festlegen*/
  lseek(fd, attr.st_size-1, SEEK_SET);
  write(fd, "", 1);

  speicherquelle=mmap(0, attr.st_size, PROT_READ, MAPFILE|MAP_SHARED, fd1, 0);
  speicherziel=mmap(0, attr.st_size, PROT_READ|PROT_WRITE, MAPFILE|MAP_SHARED, fd, 0);
  if((speicherquelle == ((caddr_t) -1)) || (speicherziel == ((caddr_t)-1)) )
    {
      fprintf(stderr, "%s: Fehler bei mmap ...........\n",strerror(errno));
      exit(0);
    }
/*Datei die mit fd und fd1 geöffnet wurden sind jetzt im Arbeitsspeicher*/
  close(fd);
  close(fd1);

  memcpy(/*(char *)*/speicherziel, /*(char *)*/speicherquelle, attr.st_size);

  exit(0);
}