blob: 700d13756d15f9822e2514178f7a4a96fe199b65 [file] [log] [blame]
/*
* linux/ipc/util.c
* Copyright (C) 1992 Krishna Balasubramanian
*/
#include <linux/config.h>
#include <linux/errno.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
void ipc_init (void);
extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr);
#ifdef CONFIG_SYSVIPC
int ipcperms (struct ipc_perm *ipcp, short flag);
extern void sem_init (void), msg_init (void), shm_init (void);
extern int sys_semget (key_t key, int nsems, int semflg);
extern int sys_semop (int semid, struct sembuf *sops, unsigned nsops);
extern int sys_semctl (int semid, int semnum, int cmd, void *arg);
extern int sys_msgget (key_t key, int msgflg);
extern int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
extern int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
int msgflg);
extern int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
extern int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
extern int sys_shmget (key_t key, int size, int flag);
extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr);
extern int sys_shmdt (char *shmaddr);
void ipc_init (void)
{
sem_init();
msg_init();
shm_init();
return;
}
/*
* Check user, group, other permissions for access
* to ipc resources. return 0 if allowed
*/
int ipcperms (struct ipc_perm *ipcp, short flag)
{
int i, perm = 0007, euid = current->euid, egid;
if (suser())
return 0;
if (euid == ipcp->cuid || euid == ipcp->uid)
perm = 0700;
else {
for (i = 0; (egid = current->groups[i]) != NOGROUP; i++)
if ((egid == ipcp->cgid) || (egid == ipcp->gid)) {
perm = 0070;
break;
}
}
if (!(flag & perm) || flag & perm & ~ipcp->mode)
return -1;
return 0;
}
extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr)
{
if (call <= SEMCTL)
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL:
return sys_semctl (first, second, third, ptr);
default:
return -EINVAL;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
case MSGRCV: {
struct ipc_kludge tmp;
if (!ptr)
return -EINVAL;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp));
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
third);
}
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
return sys_msgctl (first, second,
(struct msqid_ds *) ptr);
default:
return -EINVAL;
}
if (call <= SHMCTL)
switch (call) {
case SHMAT: /* returning shmaddr > 2G will screw up */
return sys_shmat (first, (char *) ptr, second,
(ulong *) third);
case SHMDT:
return sys_shmdt ((char *)ptr);
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
return sys_shmctl (first, second,
(struct shmid_ds *) ptr);
default:
return -EINVAL;
}
return -EINVAL;
}
#else /* not CONFIG_SYSVIPC */
extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr)
{
return -ENOSYS;
}
int shm_fork (struct task_struct *p1, struct task_struct *p2)
{
return 0;
}
void sem_exit (void)
{
return;
}
void shm_exit (void)
{
return;
}
int shm_swap (int prio)
{
return 0;
}
void shm_no_page (unsigned long *ptent)
{
return;
}
#endif /* CONFIG_SYSVIPC */