blob: 106d35e4f719ba691bfc0e26c4f5e79d2f2c290f [file] [log] [blame]
/*
* 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/compat_time.h>
#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, unsigned long, 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:
#if defined(CONFIG_ARCH_HAS_COMPAT_TIME) && !defined(CONFIG_64BIT)
return compat_sys_semtimedop(first, (struct sembuf __user *)ptr,
second,
(const struct compat_timespec __user *)fifth);
#else
return sys_semtimedop(first, (struct sembuf __user *)ptr,
second,
(const struct __kernel_timespec __user *)fifth);
#endif
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL: {
unsigned long arg;
if (!ptr)
return -EINVAL;
if (get_user(arg, (unsigned long __user *) ptr))
return -EFAULT;
return sys_semctl(first, second, third, arg);
}
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, SHMLBA);
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