156 lines
3.5 KiB
C
156 lines
3.5 KiB
C
/*
|
|
* 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>
|
|
#include <linux/stat.h>
|
|
|
|
void ipc_init (void);
|
|
asmlinkage 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; mode_t perm; uid_t euid; int egid;
|
|
|
|
if (suser())
|
|
return 0;
|
|
|
|
perm = S_IRWXO; euid = current->euid;
|
|
|
|
if (euid == ipcp->cuid || euid == ipcp->uid)
|
|
perm = S_IRWXU;
|
|
else {
|
|
for (i = 0; (egid = current->groups[i]) != NOGROUP; i++)
|
|
if ((egid == ipcp->cgid) || (egid == ipcp->gid)) {
|
|
perm = S_IRWXG;
|
|
break;
|
|
}
|
|
}
|
|
if (!(flag & perm) || flag & perm & ~ipcp->mode)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
asmlinkage 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 */
|
|
|
|
asmlinkage 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 */
|