100 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			100 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * 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
 |