Add generic sys_ipc wrapper
[safe/jmp/linux-2.6] / ipc / syscall.c
diff --git a/ipc/syscall.c b/ipc/syscall.c
new file mode 100644 (file)
index 0000000..355a3da
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
+ *
+ * This is really horribly ugly, and new architectures should just wire up
+ * the individual syscalls instead.
+ */
+#include <linux/unistd.h>
+
+#ifdef __ARCH_WANT_SYS_IPC
+#include <linux/errno.h>
+#include <linux/ipc.h>
+#include <linux/shm.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
+               unsigned long, third, void __user *, ptr, long, fifth)
+{
+       int version, ret;
+
+       version = call >> 16; /* hack for backward compatibility */
+       call &= 0xffff;
+
+       switch (call) {
+       case SEMOP:
+               return sys_semtimedop(first, (struct sembuf __user *)ptr,
+                                     second, NULL);
+       case SEMTIMEDOP:
+               return sys_semtimedop(first, (struct sembuf __user *)ptr,
+                                     second,
+                                     (const struct timespec __user *)fifth);
+
+       case SEMGET:
+               return sys_semget(first, second, third);
+       case SEMCTL: {
+               union semun fourth;
+               if (!ptr)
+                       return -EINVAL;
+               if (get_user(fourth.__pad, (void __user * __user *) ptr))
+                       return -EFAULT;
+               return sys_semctl(first, second, third, fourth);
+       }
+
+       case MSGSND:
+               return sys_msgsnd(first, (struct msgbuf __user *) ptr,
+                                 second, third);
+       case MSGRCV:
+               switch (version) {
+               case 0: {
+                       struct ipc_kludge tmp;
+                       if (!ptr)
+                               return -EINVAL;
+
+                       if (copy_from_user(&tmp,
+                                          (struct ipc_kludge __user *) ptr,
+                                          sizeof(tmp)))
+                               return -EFAULT;
+                       return sys_msgrcv(first, tmp.msgp, second,
+                                          tmp.msgtyp, third);
+               }
+               default:
+                       return sys_msgrcv(first,
+                                          (struct msgbuf __user *) ptr,
+                                          second, fifth, third);
+               }
+       case MSGGET:
+               return sys_msgget((key_t) first, second);
+       case MSGCTL:
+               return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
+
+       case SHMAT:
+               switch (version) {
+               default: {
+                       unsigned long raddr;
+                       ret = do_shmat(first, (char __user *)ptr,
+                                      second, &raddr);
+                       if (ret)
+                               return ret;
+                       return put_user(raddr, (unsigned long __user *) third);
+               }
+               case 1:
+                       /*
+                        * This was the entry point for kernel-originating calls
+                        * from iBCS2 in 2.2 days.
+                        */
+                       return -EINVAL;
+               }
+       case SHMDT:
+               return sys_shmdt((char __user *)ptr);
+       case SHMGET:
+               return sys_shmget(first, second, third);
+       case SHMCTL:
+               return sys_shmctl(first, second,
+                                  (struct shmid_ds __user *) ptr);
+       default:
+               return -ENOSYS;
+       }
+}
+#endif