diff options
author | 1995-10-18 08:37:01 +0000 | |
---|---|---|
committer | 1995-10-18 08:37:01 +0000 | |
commit | df930be708d50e9715f173caa26ffe1b7599b157 (patch) | |
tree | aa317e49e28cb999c9cf3db7f00c20903fe6010a /sys/compat/linux/linux_ipc.c | |
download | wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.tar.xz wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.zip |
initial import of NetBSD tree
Diffstat (limited to 'sys/compat/linux/linux_ipc.c')
-rw-r--r-- | sys/compat/linux/linux_ipc.c | 707 |
1 files changed, 707 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c new file mode 100644 index 00000000000..407a075eb7e --- /dev/null +++ b/sys/compat/linux/linux_ipc.c @@ -0,0 +1,707 @@ +/* $NetBSD: linux_ipc.c,v 1.9 1995/10/08 22:49:29 fvdl Exp $ */ + +/* + * Copyright (c) 1995 Frank van der Linden + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project + * by Frank van der Linden + * 4. 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/types.h> +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <sys/msg.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/systm.h> +#include <sys/stat.h> + +#include <sys/mount.h> +#include <sys/syscallargs.h> + +#include <compat/linux/linux_types.h> +#include <compat/linux/linux_signal.h> +#include <compat/linux/linux_syscallargs.h> +#include <compat/linux/linux_util.h> +#include <compat/linux/linux_ipc.h> +#include <compat/linux/linux_msg.h> +#include <compat/linux/linux_shm.h> +#include <compat/linux/linux_sem.h> +#include <compat/linux/linux_ipccall.h> + +/* + * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux. + * The main difference is, that Linux handles it all via one + * system call, which has the usual maximum amount of 5 arguments. + * This results in a kludge for calls that take 6 of them. + * + * The SYSVXXXX options have to be enabled to get the appropriate + * functions to work. + */ + +#ifdef SYSVSEM +static int linux_semop __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_semget __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_semctl __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +#endif + +#ifdef SYSVMSG +static int linux_msgsnd __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_msgrcv __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_msgop __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_msgctl __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +#endif + +#ifdef SYSVSHM +static int linux_shmat __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_shmdt __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_shmget __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +static int linux_shmctl __P((struct proc *, struct linux_sys_ipc_args *, + register_t *)); +#endif + + +int +linux_sys_ipc(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap = v; + int what, error; + + switch (SCARG(uap, what)) { +#ifdef SYSVSEM + case LINUX_SYS_semop: + return linux_semop(p, uap, retval); + case LINUX_SYS_semget: + return linux_semget(p, uap, retval); + case LINUX_SYS_semctl: + return linux_semctl(p, uap, retval); +#endif +#ifdef SYSVMSG + case LINUX_SYS_msgsnd: + return linux_msgsnd(p, uap, retval); + case LINUX_SYS_msgrcv: + return linux_msgrcv(p, uap, retval); + case LINUX_SYS_msgget: + return linux_msgget(p, uap, retval); + case LINUX_SYS_msgctl: + return linux_msgctl(p, uap, retval); +#endif +#ifdef SYSVSHM + case LINUX_SYS_shmat: + return linux_shmat(p, uap, retval); + case LINUX_SYS_shmdt: + return linux_shmdt(p, uap, retval); + case LINUX_SYS_shmget: + return linux_shmget(p, uap, retval); + case LINUX_SYS_shmctl: + return linux_shmctl(p, uap, retval); +#endif + default: + return ENOSYS; + } +} + +/* + * Convert between Linux and NetBSD ipc_perm structures. Only the + * order of the fields is different. + */ +static void +linux_to_bsd_ipc_perm(lpp, bpp) + struct linux_ipc_perm *lpp; + struct ipc_perm *bpp; +{ + + bpp->key = lpp->l_key; + bpp->uid = lpp->l_uid; + bpp->gid = lpp->l_gid; + bpp->cuid = lpp->l_cuid; + bpp->cgid = lpp->l_cgid; + bpp->mode = lpp->l_mode; + bpp->seq = lpp->l_seq; +} + +static void +bsd_to_linux_ipc_perm(bpp, lpp) + struct ipc_perm *bpp; + struct linux_ipc_perm *lpp; +{ + + lpp->l_key = bpp->key; + lpp->l_uid = bpp->uid; + lpp->l_gid = bpp->gid; + lpp->l_cuid = bpp->cuid; + lpp->l_cgid = bpp->cgid; + lpp->l_mode = bpp->mode; + lpp->l_seq = bpp->seq; +} + +#ifdef SYSVSEM +/* + * Semaphore operations. Most constants and structures are the same on + * both systems. Only semctl() needs some extra work. + */ + +/* + * Convert between Linux and NetBSD semid_ds structures. + */ +static void +bsd_to_linux_semid_ds(bs, ls) + struct semid_ds *bs; + struct linux_semid_ds *ls; +{ + + bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm); + ls->l_sem_otime = bs->sem_otime; + ls->l_sem_ctime = bs->sem_ctime; + ls->l_sem_nsems = bs->sem_nsems; + ls->l_sem_base = bs->sem_base; +} + +static void +linux_to_bsd_semid_ds(ls, bs) + struct linux_semid_ds *ls; + struct semid_ds *bs; +{ + + linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm); + bs->sem_otime = ls->l_sem_otime; + bs->sem_ctime = ls->l_sem_ctime; + bs->sem_nsems = ls->l_sem_nsems; + bs->sem_base = ls->l_sem_base; +} + +int +linux_semop(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_semop_args bsa; + + SCARG(&bsa, semid) = SCARG(uap, a1); + SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr); + SCARG(&bsa, nsops) = SCARG(uap, a2); + + return sys_semop(p, &bsa, retval); +} + +int +linux_semget(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_semget_args bsa; + + SCARG(&bsa, key) = (key_t)SCARG(uap, a1); + SCARG(&bsa, nsems) = SCARG(uap, a2); + SCARG(&bsa, semflg) = SCARG(uap, a3); + + return sys_semget(p, &bsa, retval); +} + +/* + * Most of this can be handled by directly passing the arguments on, + * buf IPC_* require a lot of copy{in,out} because of the extra indirection + * (we are passed a pointer to a union cointaining a pointer to a semid_ds + * structure. + */ +int +linux_semctl(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + caddr_t sg, unptr, dsp, ldsp; + int error, cmd; + struct sys___semctl_args bsa; + struct linux_semid_ds lm; + struct semid_ds bm; + + SCARG(&bsa, semid) = SCARG(uap, a1); + SCARG(&bsa, semnum) = SCARG(uap, a2); + SCARG(&bsa, cmd) = SCARG(uap, a3); + SCARG(&bsa, arg) = (union semun *)SCARG(uap, ptr); + switch(SCARG(uap, a3)) { + case LINUX_GETVAL: + cmd = GETVAL; + break; + case LINUX_GETPID: + cmd = GETPID; + break; + case LINUX_GETNCNT: + cmd = GETNCNT; + break; + case LINUX_GETZCNT: + cmd = GETZCNT; + break; + case LINUX_SETVAL: + cmd = SETVAL; + break; + case LINUX_IPC_RMID: + cmd = IPC_RMID; + break; + case LINUX_IPC_SET: + if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp))) + return error; + if ((error = copyin(ldsp, (caddr_t)&lm, sizeof lm))) + return error; + linux_to_bsd_semid_ds(&lm, &bm); + sg = stackgap_init(p->p_emul); + unptr = stackgap_alloc(&sg, sizeof (union semun)); + dsp = stackgap_alloc(&sg, sizeof (struct semid_ds)); + if ((error = copyout((caddr_t)&bm, dsp, sizeof bm))) + return error; + if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp))) + return error; + SCARG(&bsa, arg) = (union semun *)unptr; + return sys___semctl(p, &bsa, retval); + case LINUX_IPC_STAT: + sg = stackgap_init(p->p_emul); + unptr = stackgap_alloc(&sg, sizeof (union semun *)); + dsp = stackgap_alloc(&sg, sizeof (struct semid_ds)); + if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp))) + return error; + SCARG(&bsa, arg) = (union semun *)unptr; + if ((error = sys___semctl(p, &bsa, retval))) + return error; + if ((error = copyin(dsp, (caddr_t)&bm, sizeof bm))) + return error; + bsd_to_linux_semid_ds(&bm, &lm); + if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp))) + return error; + return copyout((caddr_t)&lm, ldsp, sizeof lm); + default: + return EINVAL; + } + SCARG(&bsa, cmd) = cmd; + + return sys___semctl(p, &bsa, retval); +} +#endif /* SYSVSEM */ + +#ifdef SYSVMSG + +static void +linux_to_bsd_msqid_ds(lmp, bmp) + struct linux_msqid_ds *lmp; + struct msqid_ds *bmp; +{ + + linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm); + bmp->msg_first = lmp->l_msg_first; + bmp->msg_last = lmp->l_msg_last; + bmp->msg_cbytes = lmp->l_msg_cbytes; + bmp->msg_qnum = lmp->l_msg_qnum; + bmp->msg_qbytes = lmp->l_msg_qbytes; + bmp->msg_lspid = lmp->l_msg_lspid; + bmp->msg_lrpid = lmp->l_msg_lrpid; + bmp->msg_stime = lmp->l_msg_stime; + bmp->msg_rtime = lmp->l_msg_rtime; + bmp->msg_ctime = lmp->l_msg_ctime; +} + +static void +bsd_to_linux_msqid_ds(bmp, lmp) + struct msqid_ds *bmp; + struct linux_msqid_ds *lmp; +{ + + bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm); + lmp->l_msg_first = bmp->msg_first; + lmp->l_msg_last = bmp->msg_last; + lmp->l_msg_cbytes = bmp->msg_cbytes; + lmp->l_msg_qnum = bmp->msg_qnum; + lmp->l_msg_qbytes = bmp->msg_qbytes; + lmp->l_msg_lspid = bmp->msg_lspid; + lmp->l_msg_lrpid = bmp->msg_lrpid; + lmp->l_msg_stime = bmp->msg_stime; + lmp->l_msg_rtime = bmp->msg_rtime; + lmp->l_msg_ctime = bmp->msg_ctime; +} + +int +linux_msgsnd(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_msgsnd_args bma; + + SCARG(&bma, msqid) = SCARG(uap, a1); + SCARG(&bma, msgp) = SCARG(uap, ptr); + SCARG(&bma, msgsz) = SCARG(uap, a2); + SCARG(&bma, msgflg) = SCARG(uap, a3); + + return sys_msgsnd(p, &bma, retval); +} + +int +linux_msgrcv(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_msgrcv_args bma; + struct linux_msgrcv_msgarg kluge; + int error; + + if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge))) + return error; + + SCARG(&bma, msqid) = SCARG(uap, a1); + SCARG(&bma, msgp) = kluge.msg; + SCARG(&bma, msgsz) = SCARG(uap, a2); + SCARG(&bma, msgtyp) = kluge.type; + SCARG(&bma, msgflg) = SCARG(uap, a3); + + return sys_msgrcv(p, &bma, retval); +} + +int +linux_msgget(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_msgget_args bma; + + SCARG(&bma, key) = (key_t)SCARG(uap, a1); + SCARG(&bma, msgflg) = SCARG(uap, a2); + + return sys_msgget(p, &bma, retval); +} + +int +linux_msgctl(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_msgctl_args bma; + caddr_t umsgptr, sg; + struct linux_msqid_ds lm; + struct msqid_ds bm; + int error; + + SCARG(&bma, msqid) = SCARG(uap, a1); + SCARG(&bma, cmd) = SCARG(uap, a2); + switch (SCARG(uap, a2)) { + case LINUX_IPC_RMID: + return sys_msgctl(p, &bma, retval); + case LINUX_IPC_SET: + if ((error = copyin(SCARG(uap, ptr), (caddr_t)&lm, sizeof lm))) + return error; + linux_to_bsd_msqid_ds(&lm, &bm); + sg = stackgap_init(p->p_emul); + umsgptr = stackgap_alloc(&sg, sizeof bm); + if ((error = copyout((caddr_t)&bm, umsgptr, sizeof bm))) + return error; + SCARG(&bma, buf) = (struct msqid_ds *)umsgptr; + return sys_msgctl(p, &bma, retval); + case LINUX_IPC_STAT: + sg = stackgap_init(p->p_emul); + umsgptr = stackgap_alloc(&sg, sizeof (struct msqid_ds)); + SCARG(&bma, buf) = (struct msqid_ds *)umsgptr; + if ((error = sys_msgctl(p, &bma, retval))) + return error; + if ((error = copyin(umsgptr, (caddr_t)&bm, sizeof bm))) + return error; + bsd_to_linux_msqid_ds(&bm, &lm); + return copyout((caddr_t)&lm, SCARG(uap, ptr), sizeof lm); + } + return EINVAL; +} +#endif /* SYSVMSG */ + +#ifdef SYSVSHM +/* + * shmat(2). Very straightforward, except that Linux passes a pointer + * in which the return value is to be passed. This is subsequently + * handled by libc, apparently. + */ +int +linux_shmat(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_shmat_args bsa; + int error; + + SCARG(&bsa, shmid) = SCARG(uap, a1); + SCARG(&bsa, shmaddr) = SCARG(uap, ptr); + SCARG(&bsa, shmflg) = SCARG(uap, a2); + + if ((error = sys_shmat(p, &bsa, retval))) + return error; + + if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3), + sizeof retval[0]))) + return error; + + retval[0] = 0; + return 0; +} + +/* + * shmdt(): this could have been mapped directly, if it wasn't for + * the extra indirection by the linux_ipc system call. + */ +int +linux_shmdt(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_shmdt_args bsa; + + SCARG(&bsa, shmaddr) = SCARG(uap, ptr); + + return sys_shmdt(p, &bsa, retval); +} + +/* + * Same story as shmdt. + */ +int +linux_shmget(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + struct sys_shmget_args bsa; + + SCARG(&bsa, key) = SCARG(uap, a1); + SCARG(&bsa, size) = SCARG(uap, a2); + SCARG(&bsa, shmflg) = SCARG(uap, a3); + + return sys_shmget(p, &bsa, retval); +} + +/* + * Convert between Linux and NetBSD shmid_ds structures. + * The order of the fields is once again the difference, and + * we also need a place to store the internal data pointer + * in, which is unfortunately stored in this structure. + * + * We abuse a Linux internal field for that. + */ +static void +linux_to_bsd_shmid_ds(lsp, bsp) + struct linux_shmid_ds *lsp; + struct shmid_ds *bsp; +{ + + linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm); + bsp->shm_segsz = lsp->l_shm_segsz; + bsp->shm_lpid = lsp->l_shm_lpid; + bsp->shm_cpid = lsp->l_shm_cpid; + bsp->shm_nattch = lsp->l_shm_nattch; + bsp->shm_atime = lsp->l_shm_atime; + bsp->shm_dtime = lsp->l_shm_dtime; + bsp->shm_ctime = lsp->l_shm_ctime; + bsp->shm_internal = lsp->l_private2; /* XXX Oh well. */ +} + +static void +bsd_to_linux_shmid_ds(bsp, lsp) + struct shmid_ds *bsp; + struct linux_shmid_ds *lsp; +{ + + bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm); + lsp->l_shm_segsz = bsp->shm_segsz; + lsp->l_shm_lpid = bsp->shm_lpid; + lsp->l_shm_cpid = bsp->shm_cpid; + lsp->l_shm_nattch = bsp->shm_nattch; + lsp->l_shm_atime = bsp->shm_atime; + lsp->l_shm_dtime = bsp->shm_dtime; + lsp->l_shm_ctime = bsp->shm_ctime; + lsp->l_private2 = bsp->shm_internal; /* XXX */ +} + +/* + * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT + * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented + * by NetBSD itself. + * + * The usual structure conversion and massaging is done. + */ +int +linux_shmctl(p, uap, retval) + struct proc *p; + struct linux_sys_ipc_args /* { + syscallarg(int) what; + syscallarg(int) a1; + syscallarg(int) a2; + syscallarg(int) a3; + syscallarg(caddr_t) ptr; + } */ *uap; + register_t *retval; +{ + int error; + caddr_t sg; + struct sys_shmctl_args bsa; + struct shmid_ds *bsp, bs; + struct linux_shmid_ds lseg; + + switch (SCARG(uap, a2)) { + case LINUX_IPC_STAT: + sg = stackgap_init(p->p_emul); + bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds)); + SCARG(&bsa, shmid) = SCARG(uap, a1); + SCARG(&bsa, cmd) = IPC_STAT; + SCARG(&bsa, buf) = bsp; + if ((error = sys_shmctl(p, &bsa, retval))) + return error; + if ((error = copyin((caddr_t) &bs, (caddr_t) bsp, sizeof bs))) + return error; + bsd_to_linux_shmid_ds(&bs, &lseg); + return copyout((caddr_t) &lseg, SCARG(uap, ptr), sizeof lseg); + case LINUX_IPC_SET: + if ((error = copyin(SCARG(uap, ptr), (caddr_t) &lseg, + sizeof lseg))) + return error; + linux_to_bsd_shmid_ds(&lseg, &bs); + sg = stackgap_init(p->p_emul); + bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds)); + if ((error = copyout((caddr_t) &bs, (caddr_t) bsp, sizeof bs))) + return error; + SCARG(&bsa, shmid) = SCARG(uap, a1); + SCARG(&bsa, cmd) = IPC_SET; + SCARG(&bsa, buf) = bsp; + return sys_shmctl(p, &bsa, retval); + case LINUX_IPC_RMID: + case LINUX_SHM_LOCK: + case LINUX_SHM_UNLOCK: + SCARG(&bsa, shmid) = SCARG(uap, a1); + switch (SCARG(uap, a2)) { + case LINUX_IPC_RMID: + SCARG(&bsa, cmd) = IPC_RMID; + break; + case LINUX_SHM_LOCK: + SCARG(&bsa, cmd) = SHM_LOCK; + break; + case LINUX_SHM_UNLOCK: + SCARG(&bsa, cmd) = SHM_UNLOCK; + break; + } + SCARG(&bsa, buf) = NULL; + return sys_shmctl(p, &bsa, retval); + case LINUX_IPC_INFO: + case LINUX_SHM_STAT: + case LINUX_SHM_INFO: + default: + return EINVAL; + } +} +#endif /* SYSVSHM */ |