mmap/mmap_tests.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. sigquit
  2. sigalrm
  3. sigsegv
  4. test_child
  5. main

/* $Id: mmap_tests.c,v 1.2 2002/03/24 13:24:23 proff Exp $
 * 
 * various mmap() implimentations suck; we attempt to find out just how
 * hard.
 *
 *        - Julian Assange (proff@iq.org)
 *
 * Test results: (please send additions to proff@iq.org)
 *
 *   linux 2.0.0 allows shared mmaps only for files, while 1.2.13
 *   doesn't permit shared mmaps at all.
 *
 *   Linux suburbia 2.0.0 #29- Thu Jul 11 18:03:20 EST 1996 i586 
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *
 *   Linux server 1.2.13 #6 Wed Feb 28 15:45:11 CST 1996 i486 (forget it)
 *      
 *      program output:
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *
 *   Freebsd is purrrrfect.
 *
 *   FreeBSD profane 2.2-CURRENT #0 Sat Jul 27 19:16:00 EST 1996
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED
 *      HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Suprisingly, AIX is faultless too.
 *
 *   AIX whisky 2 3 000027477600
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED
 *      HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Shared mmap file writes are screwed under BSDI!  
 *
 *   BSD/OS telepath.com 2.1 BSDI BSD/OS 2.1 Kernel #3: Thu Mar  7 10:47:49 CST 1996
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED
 *      HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   SunOS omega.iqm.unicamp.br 5.4 generic i86pc i386
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   SunOS chaos 4.1C 4.1.3 sun4
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *      
 *   SunOS unix1 5.3 Generic_101318-59 sun4m sparc (no shared file write?)
 *      
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *      
 *   SunOS sydney6 5.5 Generic_103093-03 sun4m sparc SUNW,SPARCstation-20
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   Novell Unixware 2.03 (System V Release 4.2MP) UNIX_SV aapo 4.2MP 2.03 i386 x86at
 *
 *      HAVE_MMAP_FILE_PRIVATE_READ
 *      HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_FILE_PRIVATE_WRITE
 *      HAVE_MMAP_FILE_SHARED_READ
 *      HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
 *      HAVE_MMAP_FILE_SHARED_WRITE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
 *
 *   ULTRIX wolf.cs.washington.edu 4.2 0 RISC (way to go ultrix)
 *
 *      nothing. zilch. 
 *
 *   OSF1 porky-pig V3.2 214 alpha (unexpected. osf/1 sucks).
 *
 *      HAVE_MMAP_DEV_ZERO_PRIVATE
 *      HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_DEV_ZERO_SHARED
 *      HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_ANON_PRIVATE
 *      HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED
 *      HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
 *      HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
 *      HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
 */

#include "config.h"

#ifdef HAVE_MMAP
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>

#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MM_SIZE (100*1024)
#define TEST_FILE "mmap_test.tmp"

#if SIZEOF_CHAR_P > 4
#  define POINTER_FMT "0x%lx"
#  define POINTER_CAST unsigned long int
#else
#  define POINTER_FMT "0x%x"
#  define POINTER_CAST unsigned int
#endif

int caught_sigquit;

void sigquit (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
        caught_sigquit++;
        signal (SIGQUIT, sigquit);
}

void sigalrm (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
        caught_sigquit++;
        signal (SIGALRM, sigalrm);
}

jmp_buf jmp;

void sigsegv (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
        signal (SIGSEGV, sigsegv);
        longjmp (jmp, 1);
}

/* 
 * TODO: test MAP_INHERIT, MAP_FIXED  (can't see that latter being much of an issue)
 */

void
test_child(char *p, char *msg)
/* [<][>][^][v][top][bottom][index][help] */
{
        char *im = "inherit_magic";
        char *pm = "parent_magic";
        char *cm = "child_magic";
        pid_t pid;
        int ws;
        fflush (stdout);
        if (!setjmp(jmp))
                strcpy (p, im);
        caught_sigquit = 0;
        signal (SIGQUIT, sigquit);
        signal (SIGCHLD, SIG_IGN);
        signal (SIGALRM, sigalrm);
        pid = fork();
        if (pid<0)
                return;
        if (pid==0)
        {
                if (!setjmp(jmp))
                        if (strcmp(p, im)==0)
                                printf("%s_CHILD_INHERIT " POINTER_FMT "\n", msg, (POINTER_CAST)p);
                alarm(5);
                kill (getppid(), SIGQUIT);
                while (!caught_sigquit)
                        pause ();
                caught_sigquit = 0;
                if (!setjmp(jmp))
                        if (strcmp(p, pm)==0)
                                printf("%s_CHILD_READ_PARENT_WRITE " POINTER_FMT "\n", msg, (POINTER_CAST)p);
                if (!setjmp(jmp))
                        strcpy (p, cm);
                fflush (stdout);
                kill (getppid(), SIGQUIT);
                exit(0);
        }
        /* parent */
        alarm(5);
        while (!caught_sigquit)
                pause ();
        caught_sigquit = 0;
        if (!setjmp(jmp))
                strcpy (p, pm);
        alarm(5);
        kill (pid, SIGQUIT);
        while (!caught_sigquit)
                pause ();
        if (!setjmp(jmp))
                if (strcmp(p, cm)==0)
                        printf("%s_PARENT_READ_CHILD_WRITE " POINTER_FMT "\n", msg, (POINTER_CAST)p);
        signal (SIGQUIT, SIG_DFL);
        alarm(0);
        wait(&ws);
}

int
main()
/* [<][>][^][v][top][bottom][index][help] */
{
        volatile int fd;
        char *m = malloc(MM_SIZE);
        char buf[1024];
        signal (SIGSEGV, sigsegv);
#if defined(MAP_PRIVATE)
        fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
        strcpy (m, "mmap magic");
        write (fd, m, MM_SIZE);
        lseek (fd, 0, SEEK_SET);
        if (fd>=0)
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                                if (strcmp(p, m)==0)
                                        printf("HAVE_MMAP_FILE_PRIVATE_READ " POINTER_FMT "\n", (POINTER_CAST)p);
                        test_child(p, "HAVE_MMAP_FILE_PRIVATE");
                        if (!setjmp(jmp))
                        {
                                write (fd, "mmap magic2", 12);
                                if (strcmp(p, "mmap magic2")==0) /* changes should be *private* */
                                        printf("HAVE_MMAP_FILE_PRIVATE_BAD_MERGED_VM_BUFFER_CACHE " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic3");
                                munmap (p, MM_SIZE);
                                lseek (fd, SEEK_SET, 0);
                                read (fd, buf, 12);
                                if (strcmp(buf, "mmap magic3")==0)
                                        printf("HAVE_MMAP_FILE_PRIVATE_WRITE " POINTER_FMT "\n", (POINTER_CAST)p);
                        } else
                                munmap (p, MM_SIZE);
                }
                close (fd);
        }
#endif
#if defined(MAP_SHARED)
        fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
        strcpy (m, "mmap magic");
        write (fd, m, MM_SIZE);
        lseek (fd, 0, SEEK_SET);
        if (fd>=0)
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                                if (strcmp(p, m)==0)
                                        printf("HAVE_MMAP_FILE_SHARED_READ " POINTER_FMT "\n", (POINTER_CAST)p);
                        test_child(p, "HAVE_MMAP_FILE_SHARED");
                        if (!setjmp(jmp))
                        {
                                write (fd, "mmap magic2", 12);
                                if (strcmp(p, "mmap magic2")==0)
                                        printf("HAVE_MMAP_FILE_SHARED_MERGED_VM_BUFFER_CACHE " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic3");
                                munmap (p, MM_SIZE);
                                lseek (fd, SEEK_SET, 0);
                                read (fd, buf, 12);
                                if (strcmp(buf, "mmap magic3")==0)
                                        printf("HAVE_MMAP_FILE_SHARED_WRITE " POINTER_FMT "\n", (POINTER_CAST)p);
                        } else
                                munmap (p, MM_SIZE);
                }
                close (fd);
        }
#endif
#if defined(MAP_PRIVATE)
        fd = open("/dev/zero", O_RDWR, 0666);
        if (fd>=0)
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic_dev_zero");
                                if (strcmp (p, "mmap magic_dev_zero")==0)
                                        printf("HAVE_MMAP_DEV_ZERO_PRIVATE " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        test_child(p, "HAVE_MMAP_DEV_ZERO_PRIVATE");
                        munmap (p, MM_SIZE);
                }
                close (fd);
        }
#endif
#if defined(MAP_PRIVATE)
        fd = open("/dev/zero", O_RDWR, 0666);
        if (fd>=0)
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic_dev_zero_shared");
                                if (strcmp (p, "mmap magic_dev_zero_shared")==0)
                                        printf("HAVE_MMAP_DEV_ZERO_SHARED " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        test_child(p, "HAVE_MMAP_DEV_ZERO_SHARED");
                        munmap (p, MM_SIZE);
                }
                close (fd);
        }
#endif
#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
#define MAP_ANON MAP_ANONYMOUS
#endif
#ifdef MAP_ANON
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic_anon");
                                if (strcmp(p, "mmap magic_anon")==0)
                                        printf("HAVE_MMAP_ANON_PRIVATE " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        test_child(p, "HAVE_MMAP_ANON_PRIVATE");
                        munmap (p, MM_SIZE);
                }
        }
#endif
#if defined(MAP_ANON) && defined(MAP_SHARED)
        {
                char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
                if (p!=(char *)-1)
                {
                        if (!setjmp(jmp))
                        {
                                strcpy (p, "mmap magic_shared_anon");
                                if (strcmp(p, "mmap magic_shared_anon")==0)
                                        printf("HAVE_MMAP_ANON_SHARED " POINTER_FMT "\n", (POINTER_CAST)p);
                        }
                        test_child(p, "HAVE_MMAP_ANON_SHARED");
                        munmap (p, MM_SIZE);
                }
        }
#endif
        unlink(TEST_FILE);
        exit (0);
}
#else /* HAVE_MMAP */
#  error mmap, not even dentures.
#endif

/* [<][>][^][v][top][bottom][index][help] */