
/*
 *  PORT.C	SEQUENT
 *
 * IDENTIFICATION:
 *    $Header: /usr/local/devel/postgres/src/backend/port/seq/RCS/port.c,v 1.12 1992/02/26 01:51:57 hong Exp $
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>

#ifdef sequent /* of course */
#include "/usr/att/usr/include/sys/shm.h"
#else
#include <sys/shm.h>	/* att-include file	*/
#endif
#include <sys/mman.h>

#include "utils/log.h"

typedef struct {
    key_t key;
    void  *base;
    long  size;
    short exists;
} SHMIDS;

static SHMIDS ShmIds[_NFILE];

/*
 *  shmget(key, size, shmflg)
 *
 *  key might be IPC_PRIVATE in which case a 'private' segment is created
 *  shmflg = file permissions
 *  size = size of shared memory segment
 */

shmget(key, size, shmflg)
key_t key;
int size, shmflg;
{
    int fd;
    char buf[64];
    int fileflags = O_RDWR;
    extern int errno;
    void *base;

    if (shmflg & IPC_CREAT)
	fileflags |= O_CREAT;
    if (shmflg & IPC_NOWAIT)
	fileflags |= O_NDELAY;
    if (shmflg & IPC_EXCL)
	fileflags |= O_EXCL;
    if (shmflg & IPC_ALLOC)
	elog(FATAL, "shmget: IPC_ALLOC flag not implemented");

    if (key == IPC_PRIVATE)
	sprintf(buf, "/usr/tmp/post.phm.%d", getpid());
    else
	sprintf(buf, "/usr/tmp/post.shm.%d", key);
    fd = open(buf, fileflags, (shmflg & 0777) | 0600);
    if (!(fileflags & O_CREAT) && fd >= 0 && !size) {
	size = lseek(fd,0L,2);
	lseek(fd,0L,0);	/* not really needed, in for conformity */
#ifdef PORT_DEBUG
	printf("Autosize %d\n", size);
#endif
    }
#ifdef PORT_DEBUG
    printf("%d = open(%s, 0%o, 0%o)\n", fd, buf, fileflags, (shmflg&0777)|0600);
#endif
    if (fd >= 0) {
	if (key == IPC_PRIVATE)
	    unlink(buf);
	Assert(fd < _NFILE);
	ShmIds[fd].key = key;
	ShmIds[fd].size = size;
	ShmIds[fd].base = (void *)0L;
	ShmIds[fd].exists = 1;
    }
#ifdef PORT_DEBUG
    printf("shared memory (fd %d size %d) %s\n", fd, size, buf);
#endif
    return(fd);
}

shmop()
{
    Assert(0);
}

shmctl(shmid, cmd, buf)
int shmid, cmd;
struct shmid_ds *buf;	/* sys/shm.h att-includes */
{
    struct stat stat;
    int result = 0;

    Assert(shmid >= 0 && shmid < _NFILE);
    Assert(ShmIds[shmid].exists);

    fstat(shmid, &stat);

    switch(cmd) {
    case IPC_STAT:
	buf->shm_perm.mode= stat.st_mode;
	buf->shm_perm.uid = stat.st_uid;
	buf->shm_perm.gid= stat.st_gid;
	buf->shm_perm.cuid = stat.st_uid;
	buf->shm_perm.cgid= stat.st_gid;
	buf->shm_perm.key = shmid;
	buf->shm_atime = stat.st_atime;
	buf->shm_ctime = stat.st_ctime;
	/* fill in more??? */
	break;
    case IPC_SET:	/* set only uid, guid, and low 9 bits of mode   */
	fchmod(shmid, (stat.st_mode & ~0777) | (buf->shm_perm.mode & 0777));
	fchown(shmid, buf->shm_perm.uid, buf->shm_perm.gid);
	break;
    case IPC_RMID:   /* delete the shared memory identifier		*/
	close(shmid);
	if (ShmIds[shmid].key != IPC_PRIVATE) {
	   char buf[64];
	   sprintf(buf, "/usr/tmp/post.shm.%d", ShmIds[shmid].key);
	   unlink(buf);
	 }
	ShmIds[shmid].exists = 0;
	break;
    }
    return(result);
}

char *
shmat(shmid, shmaddr, shmflg)
int shmid;
int shmaddr;
int shmflg;
{
    void *base;
    long size;
    long pgmask = getpagesize() - 1;
    int result;

    Assert(!shmaddr);
    Assert(!shmflg);

    Assert(shmid >= 0 && shmid < _NFILE);
    Assert(ShmIds[shmid].exists);

    if (ShmIds[shmid].base)		/* already mapped! */
	return((char *)ShmIds[shmid].base);
    base = (void *)(((int)sbrk(0) + pgmask) & ~pgmask);
    size = (ShmIds[shmid].size + pgmask) & ~pgmask;
    if (mmap(base, size, PROT_RDWR, MAP_SHARED, shmid, 0) < 0) {
	return((char *)-1);
    }
#ifdef PORT_DEBUG
    printf("mmap base = %08lx, size = %ld, prot = 0%o, shared = %d, fd = %d\n",
	base, size, PROT_RDWR, MAP_SHARED, shmid
    );
    printf("result %d\n", result);
#endif
    if (result < 0)
	perror(result);
    if (result < 0)
	return((char *)-1);
    ShmIds[shmid].base = base;
    return((char *)base);
}

int
shmdt(shmaddr)
void *shmaddr;
{
    short i;

    Assert(shmaddr);

    for (i = 0; i < _NFILE; ++i) {
	if (ShmIds[i].exists && ShmIds[i].base == shmaddr) {
	    if (munmap(ShmIds[i].base, ShmIds[i].size) < 0)
		elog(FATAL, "munmap failed!");
	    ShmIds[i].base = 0;
	    break;
	}
    }
    return(0);
}


/*
 *  CBRT.C
 *
 *  cube root function
 */

#include "tmp/c.h"
#include <math.h>

double
cbrt(x)
double x;
{
    return(pow(x, 1.0/3.0));
}

/*
 *  SENDANNOUNCE.C
 *
 *  A do-nothing routine?
 */

sendannounce(line)
char *line;
{

}
