diff options
Diffstat (limited to 'ipc/syscall.c')
| -rw-r--r-- | ipc/syscall.c | 99 | 
1 files changed, 99 insertions, 0 deletions
diff --git a/ipc/syscall.c b/ipc/syscall.c new file mode 100644 index 00000000000..1d6f53f6b56 --- /dev/null +++ b/ipc/syscall.c @@ -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, 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: { +		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  |