/* Copyright (c)1994-2000 Begemot Computer Associates. All rights reserved.
 * See the file COPYRIGHT for details of redistribution and use. */

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

# include <begemot.h>
# include "../cdefs.h"
# include "util.h"

RCSID("$Id: sparent.c 417 2000-03-04 08:04:07Z hbb $")

/*
 * FreeBSD has a serious brokeness, which makes the use
 * of mmap for shared memory between processes quit hard.
 * It doesn't implement the MAP_INHERIT flag to mmap()! We can
 * inherit a mmap()ed area to a fork()ed child, but on exec the
 * area is removed.
 * To overcome the problem, we create a short file inherit the file
 * descriptor and mmap() in both the parent and the child. This should work
 * on any system.
 * The caller should close the file descriptors.
 */
caddr_t
mmap_shared_parent(size_t len, int *pfd)
{
	char fn[100];
	caddr_t c;

	sprintf(fn, "/var/tmp/p11.%u", (u_int)getpid());
	if((*pfd = open(fn, O_RDWR|O_EXCL|O_TRUNC|O_CREAT, 0666)) < 0)
		panic("open(%s): %s", fn, strerror(errno));
	(void)unlink(fn);
	if(ftruncate(*pfd, (off_t)len))
		panic("ftruncate: %s", strerror(errno));
	if((int)(c = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,*pfd,0))==-1)
		panic("mmap: %s", strerror(errno));
	return c;
}
