#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

void abandon(char message[])
{
  perror(message);
  exit(EXIT_FAILURE);
}

/* affichage à l'envers du contenu d'un tampon de texte */

void afficher(char tampon[], int taille)
{
  char *ptr;
  int nb = 1;                 /* longueur ligne courante, y compris '\n'  */

  for (ptr = tampon + taille - 1; ptr >= tampon; ptr--) {
    if (*ptr == '\n') {
      write(1, ptr + 1, nb);
      nb = 0;
    }
    nb++;
  }
  write(1, ptr + 1, nb);
}

int main(int argc, char *argv[])
{
  int fd;
  struct stat s;
  char *t;

  if (argc != 2) {
    fprintf(stderr, "Usage: %s fichier\n", argv[0]);
    return EXIT_FAILURE;
  }
  if (stat(argv[1], &s) != 0)
    abandon("Contrôle du type");

  if (!S_ISREG(s.st_mode)) {
    fprintf(stderr, "%s n'est pas un fichier\n", argv[1]);
    return EXIT_FAILURE;
  }
  fd = open(argv[1], O_RDONLY);
  if (fd < 0)
    abandon("Ouverture");

  t = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (t == MAP_FAILED)
    abandon("Mise en mémoire");

  afficher(t, s.st_size);

  if (munmap(t, s.st_size) < 0)
    abandon("Détachement");

  close(fd);
  return EXIT_SUCCESS;
}
