234cc877a2
which is used as a basis for a more complete and cleaner ibcs2 emulator. (snapshot about May 1995 with a few files from September 1995) Some files and code from old emulator still remains. New files, features, and changes have been implemented by myself, which will be shown in following commits.
415 lines
9.7 KiB
C
415 lines
9.7 KiB
C
/*
|
|
* Copyright (c) 1995 Scott Bartram
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/namei.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/file.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/filedesc.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/resourcevar.h>
|
|
#include <sys/signal.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <sys/times.h>
|
|
#include <sys/vnode.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/utsname.h>
|
|
#include <sys/unistd.h>
|
|
#include <sys/msg.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/syscallargs.h>
|
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <compat/ibcs2/ibcs2_types.h>
|
|
#include <compat/ibcs2/ibcs2_signal.h>
|
|
#include <compat/ibcs2/ibcs2_syscallargs.h>
|
|
#include <compat/ibcs2/ibcs2_util.h>
|
|
|
|
#define IBCS2_IPC_RMID 0
|
|
#define IBCS2_IPC_SET 1
|
|
#define IBCS2_IPC_STAT 2
|
|
|
|
/*
|
|
* iBCS2 msgsys call
|
|
*/
|
|
|
|
struct ibcs2_msqid_ds {
|
|
struct ipc_perm msg_perm;
|
|
struct msg *msg_first;
|
|
struct msg *msg_last;
|
|
u_short msg_cbytes;
|
|
u_short msg_qnum;
|
|
u_short msg_qbytes;
|
|
u_short msg_lspid;
|
|
u_short msg_lrpid;
|
|
ibcs2_time_t msg_stime;
|
|
ibcs2_time_t msg_rtime;
|
|
ibcs2_time_t msg_ctime;
|
|
};
|
|
|
|
static void
|
|
cvt_msqid2imsqid(bp, ibp)
|
|
struct msqid_ds *bp;
|
|
struct ibcs2_msqid_ds *ibp;
|
|
{
|
|
ibp->msg_perm = bp->msg_perm;
|
|
ibp->msg_first = bp->msg_first;
|
|
ibp->msg_last = bp->msg_last;
|
|
ibp->msg_cbytes = (u_short)bp->msg_cbytes;
|
|
ibp->msg_qnum = (u_short)bp->msg_qnum;
|
|
ibp->msg_qbytes = (u_short)bp->msg_qbytes;
|
|
ibp->msg_lspid = (u_short)bp->msg_lspid;
|
|
ibp->msg_lrpid = (u_short)bp->msg_lrpid;
|
|
ibp->msg_stime = bp->msg_stime;
|
|
ibp->msg_rtime = bp->msg_rtime;
|
|
ibp->msg_ctime = bp->msg_ctime;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
cvt_imsqid2msqid(ibp, bp)
|
|
struct ibcs2_msqid_ds *ibp;
|
|
struct msqid_ds *bp;
|
|
{
|
|
bp->msg_perm = ibp->msg_perm;
|
|
bp->msg_first = ibp->msg_first;
|
|
bp->msg_last = ibp->msg_last;
|
|
bp->msg_cbytes = ibp->msg_cbytes;
|
|
bp->msg_qnum = ibp->msg_qnum;
|
|
bp->msg_qbytes = ibp->msg_qbytes;
|
|
bp->msg_lspid = ibp->msg_lspid;
|
|
bp->msg_lrpid = ibp->msg_lrpid;
|
|
bp->msg_stime = ibp->msg_stime;
|
|
bp->msg_rtime = ibp->msg_rtime;
|
|
bp->msg_ctime = ibp->msg_ctime;
|
|
return;
|
|
}
|
|
|
|
int
|
|
ibcs2_msgsys(p, uap, retval)
|
|
struct proc *p;
|
|
struct ibcs2_msgsys_args *uap;
|
|
int *retval;
|
|
{
|
|
switch (SCARG(uap, which)) {
|
|
case 0: /* msgget */
|
|
SCARG(uap, which) = 1;
|
|
return compat_10_msgsys(p, uap, retval);
|
|
case 1: { /* msgctl */
|
|
int error;
|
|
struct compat_10_msgsys_args margs;
|
|
caddr_t sg = stackgap_init();
|
|
|
|
SCARG(&margs, which) = 0;
|
|
SCARG(&margs, a2) = SCARG(uap, a2);
|
|
SCARG(&margs, a4) =
|
|
(int)stackgap_alloc(&sg, sizeof(struct msqid_ds));
|
|
SCARG(&margs, a3) = SCARG(uap, a3);
|
|
switch (SCARG(&margs, a3)) {
|
|
case IBCS2_IPC_STAT:
|
|
error = compat_10_msgsys(p, &margs, retval);
|
|
if (!error)
|
|
cvt_msqid2imsqid(SCARG(&margs, a4),
|
|
(struct ibcs2_msqid_ds *)SCARG(uap, a4));
|
|
return error;
|
|
case IBCS2_IPC_SET:
|
|
cvt_imsqid2msqid((struct ibcs2_msqid_ds *)SCARG(uap,
|
|
a4),
|
|
SCARG(&margs, a4));
|
|
return compat_10_msgsys(p, &margs, retval);
|
|
case IBCS2_IPC_RMID:
|
|
return compat_10_msgsys(p, &margs, retval);
|
|
}
|
|
return EINVAL;
|
|
}
|
|
case 2: /* msgrcv */
|
|
SCARG(uap, which) = 3;
|
|
return compat_10_msgsys(p, uap, retval);
|
|
case 3: /* msgsnd */
|
|
SCARG(uap, which) = 2;
|
|
return compat_10_msgsys(p, uap, retval);
|
|
default:
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* iBCS2 semsys call
|
|
*/
|
|
|
|
struct ibcs2_semid_ds {
|
|
struct ipc_perm sem_perm;
|
|
struct ibcs2_sem *sem_base;
|
|
u_short sem_nsems;
|
|
int pad1;
|
|
ibcs2_time_t sem_otime;
|
|
ibcs2_time_t sem_ctime;
|
|
};
|
|
|
|
struct ibcs2_sem {
|
|
u_short semval;
|
|
ibcs2_pid_t sempid;
|
|
u_short semncnt;
|
|
u_short semzcnt;
|
|
};
|
|
|
|
static void
|
|
cvt_sem2isem(bp, ibp)
|
|
struct sem *bp;
|
|
struct ibcs2_sem *ibp;
|
|
{
|
|
ibp->semval = bp->semval;
|
|
ibp->sempid = bp->sempid;
|
|
ibp->semncnt = bp->semncnt;
|
|
ibp->semzcnt = bp->semzcnt;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
cvt_isem2sem(ibp, bp)
|
|
struct ibcs2_sem *ibp;
|
|
struct sem *bp;
|
|
{
|
|
bp->semval = ibp->semval;
|
|
bp->sempid = ibp->sempid;
|
|
bp->semncnt = ibp->semncnt;
|
|
bp->semzcnt = ibp->semzcnt;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
cvt_semid2isemid(bp, ibp)
|
|
struct semid_ds *bp;
|
|
struct ibcs2_semid_ds *ibp;
|
|
{
|
|
ibp->sem_perm = bp->sem_perm;
|
|
ibp->sem_base = (struct ibcs2_sem *)bp->sem_base;
|
|
ibp->sem_nsems = bp->sem_nsems;
|
|
ibp->sem_otime = bp->sem_otime;
|
|
ibp->sem_ctime = bp->sem_ctime;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
cvt_isemid2semid(ibp, bp)
|
|
struct ibcs2_semid_ds *ibp;
|
|
struct semid_ds *bp;
|
|
{
|
|
bp->sem_perm = ibp->sem_perm;
|
|
bp->sem_base = (struct sem *)ibp->sem_base;
|
|
bp->sem_nsems = ibp->sem_nsems;
|
|
bp->sem_otime = ibp->sem_otime;
|
|
bp->sem_ctime = ibp->sem_ctime;
|
|
return;
|
|
}
|
|
|
|
int
|
|
ibcs2_semsys(p, uap, retval)
|
|
struct proc *p;
|
|
struct ibcs2_semsys_args *uap;
|
|
int *retval;
|
|
{
|
|
int error;
|
|
|
|
switch (SCARG(uap, which)) {
|
|
case 0: /* semctl */
|
|
switch(SCARG(uap, a4)) {
|
|
case IBCS2_IPC_STAT:
|
|
{
|
|
struct ibcs2_semid_ds *isp;
|
|
struct semid_ds *sp;
|
|
caddr_t sg = stackgap_init();
|
|
|
|
isp = (struct ibcs2_semid_ds *)SCARG(uap, a5);
|
|
sp = stackgap_alloc(&sg, sizeof(struct semid_ds));
|
|
SCARG(uap, a5) = (int)sp;
|
|
error = compat_10_semsys(p, uap, retval);
|
|
if (!error) {
|
|
SCARG(uap, a5) = (int)isp;
|
|
isp = stackgap_alloc(&sg, sizeof(*isp));
|
|
cvt_semid2isemid(sp, isp);
|
|
error = copyout((caddr_t)isp,
|
|
(caddr_t)SCARG(uap, a5),
|
|
sizeof(*isp));
|
|
}
|
|
return error;
|
|
}
|
|
case IBCS2_IPC_SET:
|
|
{
|
|
struct ibcs2_semid_ds *isp;
|
|
struct semid_ds *sp;
|
|
caddr_t sg = stackgap_init();
|
|
|
|
isp = stackgap_alloc(&sg, sizeof(*isp));
|
|
sp = stackgap_alloc(&sg, sizeof(*sp));
|
|
error = copyin((caddr_t)SCARG(uap, a5), (caddr_t)isp,
|
|
sizeof(*isp));
|
|
if (error)
|
|
return error;
|
|
cvt_isemid2semid(isp, sp);
|
|
SCARG(uap, a5) = (int)sp;
|
|
return compat_10_semsys(p, uap, retval);
|
|
}
|
|
}
|
|
return compat_10_semsys(p, uap, retval);
|
|
|
|
case 1: /* semget */
|
|
return compat_10_semsys(p, uap, retval);
|
|
|
|
case 2: /* semop */
|
|
return compat_10_semsys(p, uap, retval);
|
|
}
|
|
return EINVAL;
|
|
}
|
|
|
|
|
|
/*
|
|
* iBCS2 shmsys call
|
|
*/
|
|
|
|
struct ibcs2_shmid_ds {
|
|
struct ipc_perm shm_perm;
|
|
int shm_segsz;
|
|
int pad1;
|
|
char pad2[4];
|
|
u_short shm_lpid;
|
|
u_short shm_cpid;
|
|
u_short shm_nattch;
|
|
u_short shm_cnattch;
|
|
ibcs2_time_t shm_atime;
|
|
ibcs2_time_t shm_dtime;
|
|
ibcs2_time_t shm_ctime;
|
|
};
|
|
|
|
static void
|
|
cvt_shmid2ishmid(bp, ibp)
|
|
struct shmid_ds *bp;
|
|
struct ibcs2_shmid_ds *ibp;
|
|
{
|
|
ibp->shm_perm = bp->shm_perm;
|
|
ibp->shm_segsz = bp->shm_segsz;
|
|
ibp->shm_lpid = bp->shm_lpid;
|
|
ibp->shm_cpid = bp->shm_cpid;
|
|
ibp->shm_nattch = bp->shm_nattch;
|
|
ibp->shm_cnattch = 0; /* ignored anyway */
|
|
ibp->shm_atime = bp->shm_atime;
|
|
ibp->shm_dtime = bp->shm_dtime;
|
|
ibp->shm_ctime = bp->shm_ctime;
|
|
return;
|
|
}
|
|
|
|
static void
|
|
cvt_ishmid2shmid(ibp, bp)
|
|
struct ibcs2_shmid_ds *ibp;
|
|
struct shmid_ds *bp;
|
|
{
|
|
bp->shm_perm = ibp->shm_perm;
|
|
bp->shm_segsz = ibp->shm_segsz;
|
|
bp->shm_lpid = ibp->shm_lpid;
|
|
bp->shm_cpid = ibp->shm_cpid;
|
|
bp->shm_nattch = ibp->shm_nattch;
|
|
bp->shm_atime = ibp->shm_atime;
|
|
bp->shm_dtime = ibp->shm_dtime;
|
|
bp->shm_ctime = ibp->shm_ctime;
|
|
bp->shm_internal = (void *)0; /* ignored anyway */
|
|
return;
|
|
}
|
|
|
|
int
|
|
ibcs2_shmsys(p, uap, retval)
|
|
struct proc *p;
|
|
struct ibcs2_shmsys_args *uap;
|
|
int *retval;
|
|
{
|
|
int error;
|
|
|
|
switch (SCARG(uap, which)) {
|
|
case 0: /* shmat */
|
|
return compat_10_shmsys(p, uap, retval);
|
|
|
|
case 1: /* shmctl */
|
|
switch(SCARG(uap, a3)) {
|
|
case IBCS2_IPC_STAT:
|
|
{
|
|
struct ibcs2_shmid_ds *isp;
|
|
struct shmid_ds *sp;
|
|
caddr_t sg = stackgap_init();
|
|
|
|
isp = (struct ibcs2_shmid_ds *)SCARG(uap, a4);
|
|
sp = stackgap_alloc(&sg, sizeof(*sp));
|
|
SCARG(uap, a4) = (int)sp;
|
|
error = compat_10_shmsys(p, uap, retval);
|
|
if (!error) {
|
|
SCARG(uap, a4) = (int)isp;
|
|
isp = stackgap_alloc(&sg, sizeof(*isp));
|
|
cvt_shmid2ishmid(sp, isp);
|
|
error = copyout((caddr_t)isp,
|
|
(caddr_t)SCARG(uap, a4),
|
|
sizeof(*isp));
|
|
}
|
|
return error;
|
|
}
|
|
case IBCS2_IPC_SET:
|
|
{
|
|
struct ibcs2_shmid_ds *isp;
|
|
struct shmid_ds *sp;
|
|
caddr_t sg = stackgap_init();
|
|
|
|
isp = stackgap_alloc(&sg, sizeof(*isp));
|
|
sp = stackgap_alloc(&sg, sizeof(*sp));
|
|
error = copyin((caddr_t)SCARG(uap, a4), (caddr_t)isp,
|
|
sizeof(*isp));
|
|
if (error)
|
|
return error;
|
|
cvt_ishmid2shmid(isp, sp);
|
|
SCARG(uap, a4) = (int)sp;
|
|
return compat_10_shmsys(p, uap, retval);
|
|
}
|
|
}
|
|
return compat_10_shmsys(p, uap, retval);
|
|
|
|
case 2: /* shmdt */
|
|
return compat_10_shmsys(p, uap, retval);
|
|
|
|
case 3: /* shmget */
|
|
return compat_10_shmsys(p, uap, retval);
|
|
}
|
|
return EINVAL;
|
|
}
|