2010-03-11 02:21:18 +03:00
/*
* 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>
2010-03-22 09:47:59 +03:00
SYSCALL_DEFINE6 ( ipc , unsigned int , call , int , first , unsigned long , second ,
2010-03-11 02:21:18 +03:00
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 : {
2013-03-06 00:04:55 +04:00
unsigned long arg ;
2010-03-11 02:21:18 +03:00
if ( ! ptr )
return - EINVAL ;
2013-03-06 00:04:55 +04:00
if ( get_user ( arg , ( unsigned long __user * ) ptr ) )
2010-03-11 02:21:18 +03:00
return - EFAULT ;
2013-03-06 00:04:55 +04:00
return sys_semctl ( first , second , third , arg ) ;
2010-03-11 02:21:18 +03:00
}
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 ,
2012-07-31 01:42:38 +04:00
second , & raddr , SHMLBA ) ;
2010-03-11 02:21:18 +03:00
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