You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.3 KiB
99 lines
2.3 KiB
/* |
|
* 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, 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: |
|
return sys_semtimedop(first, (struct sembuf __user *)ptr, |
|
second, |
|
(const struct timespec __user *)fifth); |
|
|
|
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
|
|
|