summaryrefslogtreecommitdiff
path: root/sys/compat/common/kern_ipc_23.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2001-05-16 17:14:40 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2001-05-16 17:14:40 +0000
commitd081888ede32893d5dfa6a13f09405aa730c9092 (patch)
treedf2c5452e4612103cc5e3b507980de79f926318b /sys/compat/common/kern_ipc_23.c
parenta298e9ff9d4b9418b1b5b64c70a04ed9774e676d (diff)
Create COMPAT_25 and move ogetfsstat, ostatfs and ostatfs into it.
Create COMPAT_23 and move __osemctl, omsgctl, oshmctl there.
Diffstat (limited to 'sys/compat/common/kern_ipc_23.c')
-rw-r--r--sys/compat/common/kern_ipc_23.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/sys/compat/common/kern_ipc_23.c b/sys/compat/common/kern_ipc_23.c
new file mode 100644
index 00000000000..171154d4b9a
--- /dev/null
+++ b/sys/compat/common/kern_ipc_23.c
@@ -0,0 +1,449 @@
+/* $OpenBSD: kern_ipc_23.c,v 1.1 2001/05/16 17:14:38 millert Exp $ */
+
+/*
+ * Implementation of SVID semaphores
+ *
+ * Author: Daniel Boulet
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ */
+/*
+ * Implementation of SVID messages
+ *
+ * Author: Daniel Boulet
+ *
+ * Copyright 1993 Daniel Boulet and RTMX Inc.
+ *
+ * This system call was implemented by Daniel Boulet under contract from RTMX.
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ */
+/*
+ * Copyright (c) 1994 Adam Glass and Charles M. Hannum. 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 by Adam Glass and Charles M.
+ * Hannum.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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/kernel.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/malloc.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#ifdef SYSVMSG
+
+void msg_freehdr __P((struct msg *));
+
+int
+compat_23_sys_msgctl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct compat_23_sys_msgctl_args /* {
+ syscallarg(int) msqid;
+ syscallarg(int) cmd;
+ syscallarg(struct msqid_ds *) buf;
+ } */ *uap = v;
+ int msqid = SCARG(uap, msqid);
+ int cmd = SCARG(uap, cmd);
+ struct omsqid_ds *user_msqptr = SCARG(uap, buf);
+ struct ucred *cred = p->p_ucred;
+ int rval, eval;
+ struct omsqid_ds omsqbuf;
+ register struct msqid_ds *msqptr;
+
+#ifdef MSG_DEBUG_OK
+ printf("call to msgctl(%d, %d, %p)\n", msqid, cmd, user_msqptr);
+#endif
+
+ msqid = IPCID_TO_IX(msqid);
+
+ if (msqid < 0 || msqid >= msginfo.msgmni) {
+#ifdef MSG_DEBUG_OK
+ printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
+ msginfo.msgmni);
+#endif
+ return(EINVAL);
+ }
+
+ msqptr = &msqids[msqid];
+
+ if (msqptr->msg_qbytes == 0) {
+#ifdef MSG_DEBUG_OK
+ printf("no such msqid\n");
+#endif
+ return(EINVAL);
+ }
+ if (msqptr->msg_perm.seq != IPCID_TO_SEQ(SCARG(uap, msqid))) {
+#ifdef MSG_DEBUG_OK
+ printf("wrong sequence number\n");
+#endif
+ return(EINVAL);
+ }
+
+ eval = 0;
+ rval = 0;
+
+ switch (cmd) {
+
+ case IPC_RMID:
+ {
+ struct msg *msghdr;
+ if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M)) != 0)
+ return(eval);
+ /* Free the message headers */
+ msghdr = msqptr->msg_first;
+ while (msghdr != NULL) {
+ struct msg *msghdr_tmp;
+
+ /* Free the segments of each message */
+ msqptr->msg_cbytes -= msghdr->msg_ts;
+ msqptr->msg_qnum--;
+ msghdr_tmp = msghdr;
+ msghdr = msghdr->msg_next;
+ msg_freehdr(msghdr_tmp);
+ }
+
+#ifdef DIAGNOSTIC
+ if (msqptr->msg_cbytes != 0)
+ panic("sys_omsgctl: msg_cbytes is screwed up");
+ if (msqptr->msg_qnum != 0)
+ panic("sys_omsgctl: msg_qnum is screwed up");
+#endif
+
+ msqptr->msg_qbytes = 0; /* Mark it as free */
+
+ wakeup((caddr_t)msqptr);
+ }
+
+ break;
+
+ case IPC_SET:
+ if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M)))
+ return(eval);
+ if ((eval = copyin(user_msqptr, &omsqbuf, sizeof(omsqbuf))) != 0)
+ return(eval);
+ if (omsqbuf.msg_qbytes > msqptr->msg_qbytes && cred->cr_uid != 0)
+ return(EPERM);
+ if (omsqbuf.msg_qbytes > msginfo.msgmnb) {
+#ifdef MSG_DEBUG_OK
+ printf("can't increase msg_qbytes beyond %d (truncating)\n",
+ msginfo.msgmnb);
+#endif
+ omsqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */
+ }
+ if (omsqbuf.msg_qbytes == 0) {
+#ifdef MSG_DEBUG_OK
+ printf("can't reduce msg_qbytes to 0\n");
+#endif
+ return(EINVAL); /* non-standard errno! */
+ }
+ msqptr->msg_perm.uid = omsqbuf.msg_perm.uid; /* change the owner */
+ msqptr->msg_perm.gid = omsqbuf.msg_perm.gid; /* change the owner */
+ msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) |
+ (omsqbuf.msg_perm.mode & 0777);
+ msqptr->msg_qbytes = omsqbuf.msg_qbytes;
+ msqptr->msg_ctime = time.tv_sec;
+ break;
+
+ case IPC_STAT:
+ if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_R))) {
+#ifdef MSG_DEBUG_OK
+ printf("requester doesn't have read access\n");
+#endif
+ return(eval);
+ }
+ msqid_n2o(msqptr, &omsqbuf);
+ eval = copyout((caddr_t)&omsqbuf, user_msqptr, sizeof omsqbuf);
+ break;
+
+ default:
+#ifdef MSG_DEBUG_OK
+ printf("invalid command %d\n", cmd);
+#endif
+ return(EINVAL);
+ }
+
+ if (eval == 0)
+ *retval = rval;
+ return(eval);
+}
+#endif /* SYSVMSG */
+
+#ifdef SYSVSHM
+
+struct shmid_ds *shm_find_segment_by_shmid __P((int));
+void shm_deallocate_segment __P((struct shmid_ds *));
+
+#define SHMSEG_REMOVED 0x0400 /* XXX */
+
+int
+compat_23_sys_shmctl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct compat_23_sys_shmctl_args /* {
+ syscallarg(int) shmid;
+ syscallarg(int) cmd;
+ syscallarg(struct shmid_ds *) buf;
+ } */ *uap = v;
+ int error;
+ struct ucred *cred = p->p_ucred;
+ struct oshmid_ds oinbuf;
+ struct shmid_ds *shmseg;
+ extern int shm_last_free;
+
+ shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid));
+ if (shmseg == NULL)
+ return EINVAL;
+ switch (SCARG(uap, cmd)) {
+ case IPC_STAT:
+ if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0)
+ return error;
+ shmid_n2o(shmseg, &oinbuf);
+ error = copyout((caddr_t)&oinbuf, SCARG(uap, buf),
+ sizeof(oinbuf));
+ if (error)
+ return error;
+ break;
+ case IPC_SET:
+ if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0)
+ return error;
+ error = copyin(SCARG(uap, buf), (caddr_t)&oinbuf,
+ sizeof(oinbuf));
+ if (error)
+ return error;
+ shmseg->shm_perm.uid = oinbuf.shm_perm.uid;
+ shmseg->shm_perm.gid = oinbuf.shm_perm.gid;
+ shmseg->shm_perm.mode =
+ (shmseg->shm_perm.mode & ~ACCESSPERMS) |
+ (oinbuf.shm_perm.mode & ACCESSPERMS);
+ shmseg->shm_ctime = time.tv_sec;
+ break;
+ case IPC_RMID:
+ if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0)
+ return error;
+ shmseg->shm_perm.key = IPC_PRIVATE;
+ shmseg->shm_perm.mode |= SHMSEG_REMOVED;
+ if (shmseg->shm_nattch <= 0) {
+ shm_deallocate_segment(shmseg);
+ shm_last_free = IPCID_TO_IX(SCARG(uap, shmid));
+ }
+ break;
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+#endif /* SYSVSHM */
+
+#ifdef SYSVSEM
+
+void semundo_clear __P((int, int));
+
+int
+compat_23_sys___semctl(p, v, retval)
+ struct proc *p;
+ register void *v;
+ register_t *retval;
+{
+ register struct compat_23_sys___semctl_args /* {
+ syscallarg(int) semid;
+ syscallarg(int) semnum;
+ syscallarg(int) cmd;
+ syscallarg(union semun *) arg;
+ } */ *uap = v;
+ int semid = SCARG(uap, semid);
+ int semnum = SCARG(uap, semnum);
+ int cmd = SCARG(uap, cmd);
+ union semun *arg = SCARG(uap, arg);
+ union semun real_arg;
+ struct ucred *cred = p->p_ucred;
+ int i, rval, eval;
+ struct semid_ds *semaptr;
+ struct osemid_ds osbuf;
+ extern int semtot;
+
+#ifdef SEM_DEBUG
+ printf("call to semctl(%d, %d, %d, %p)\n", semid, semnum, cmd, arg);
+#endif
+
+ semid = IPCID_TO_IX(semid);
+ if (semid < 0 || semid >= seminfo.semmsl)
+ return(EINVAL);
+
+ semaptr = &sema[semid];
+ if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
+ semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid)))
+ return(EINVAL);
+
+ eval = 0;
+ rval = 0;
+
+ switch (cmd) {
+ case IPC_RMID:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0)
+ return(eval);
+ semaptr->sem_perm.cuid = cred->cr_uid;
+ semaptr->sem_perm.uid = cred->cr_uid;
+ semtot -= semaptr->sem_nsems;
+ for (i = semaptr->sem_base - sem; i < semtot; i++)
+ sem[i] = sem[i + semaptr->sem_nsems];
+ for (i = 0; i < seminfo.semmni; i++) {
+ if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
+ sema[i].sem_base > semaptr->sem_base)
+ sema[i].sem_base -= semaptr->sem_nsems;
+ }
+ semaptr->sem_perm.mode = 0;
+ semundo_clear(semid, -1);
+ wakeup((caddr_t)semaptr);
+ break;
+
+ case IPC_SET:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)))
+ return(eval);
+ if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
+ return(eval);
+ if ((eval = copyin(real_arg.buf, (caddr_t)&osbuf,
+ sizeof(osbuf))) != 0)
+ return(eval);
+ semaptr->sem_perm.uid = osbuf.sem_perm.uid;
+ semaptr->sem_perm.gid = osbuf.sem_perm.gid;
+ semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
+ (osbuf.sem_perm.mode & 0777);
+ semaptr->sem_ctime = time.tv_sec;
+ break;
+
+ case IPC_STAT:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
+ return(eval);
+ semid_n2o(semaptr, &osbuf);
+ eval = copyout((caddr_t)&osbuf, real_arg.buf, sizeof osbuf);
+ break;
+
+ case GETNCNT:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if (semnum < 0 || semnum >= semaptr->sem_nsems)
+ return(EINVAL);
+ rval = semaptr->sem_base[semnum].semncnt;
+ break;
+
+ case GETPID:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if (semnum < 0 || semnum >= semaptr->sem_nsems)
+ return(EINVAL);
+ rval = semaptr->sem_base[semnum].sempid;
+ break;
+
+ case GETVAL:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if (semnum < 0 || semnum >= semaptr->sem_nsems)
+ return(EINVAL);
+ rval = semaptr->sem_base[semnum].semval;
+ break;
+
+ case GETALL:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
+ return(eval);
+ for (i = 0; i < semaptr->sem_nsems; i++) {
+ eval = copyout((caddr_t)&semaptr->sem_base[i].semval,
+ &real_arg.array[i], sizeof(real_arg.array[0]));
+ if (eval != 0)
+ break;
+ }
+ break;
+
+ case GETZCNT:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
+ return(eval);
+ if (semnum < 0 || semnum >= semaptr->sem_nsems)
+ return(EINVAL);
+ rval = semaptr->sem_base[semnum].semzcnt;
+ break;
+
+ case SETVAL:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
+ return(eval);
+ if (semnum < 0 || semnum >= semaptr->sem_nsems)
+ return(EINVAL);
+ if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
+ return(eval);
+ semaptr->sem_base[semnum].semval = real_arg.val;
+ semundo_clear(semid, semnum);
+ wakeup((caddr_t)semaptr);
+ break;
+
+ case SETALL:
+ if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
+ return(eval);
+ if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
+ return(eval);
+ for (i = 0; i < semaptr->sem_nsems; i++) {
+ eval = copyin(&real_arg.array[i],
+ (caddr_t)&semaptr->sem_base[i].semval,
+ sizeof(real_arg.array[0]));
+ if (eval != 0)
+ break;
+ }
+ semundo_clear(semid, -1);
+ wakeup((caddr_t)semaptr);
+ break;
+
+ default:
+ return(EINVAL);
+ }
+
+ if (eval == 0)
+ *retval = rval;
+ return(eval);
+}
+#endif /* SYSVSEM */