/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * SCCSID: @(#)ipc.c 3.0 4/21/86 */ #include <errno.h> #include <sys/types.h> #include <sys/param.h> #include <sys/seg.h> #include <signal.h> #include <sys/proc.h> #include <sys/dir.h> #include <sys/user.h> #include <sys/ipc.h> /* * Common IPC routines. */ /* * Check message, semaphore, or shared memory access permissions. * * This routine verifies the requested access permission for the current * process. Super-user is always given permission. Otherwise, the * appropriate bits are checked corresponding to owner, group, or * everyone. Zero is returned on success. On failure, u.u_error is * set to EACCES and one is returned. * The arguments must be set up as follows: * p - Pointer to permission structure to verify * mode - Desired access permissions */ ipcaccess(p, mode) register struct ipc_perm *p; register ushort mode; { if(u.u_uid == 0) return(0); if(u.u_uid != p->uid && u.u_uid != p->cuid) { mode >>= 3; if(u.u_gid != p->gid && u.u_gid != p->cgid) mode >>= 3; } if(mode & p->mode) return(0); u.u_error = EACCES; return(1); } /* * Get message, semaphore, or shared memory structure. * * This routine searches for a matching key based on the given flags * and returns a pointer to the appropriate entry. A structure is * allocated if the key doesn't exist and the flags call for it. * The arguments must be set up as follows: * key - Key to be used * flag - Creation flags and access modes * base - Base address of appropriate facility structure array * cnt - # of entries in facility structure array * size - sizeof(facility structure) * status - Pointer to status word: set on successful completion * only: 0 => existing entry found * 1 => new entry created * Ipcget returns NULL with u.u_error set to an appropriate value if * it fails, or a pointer to the initialized entry if it succeeds. */ struct ipc_perm * ipcget(key, flag, base, cnt, size, status) register struct ipc_perm *base; int cnt, flag, size, *status; key_t key; { register struct ipc_perm *a; /* ptr to available entry */ register int i; /* loop control */ if(key == IPC_PRIVATE) { for(i = 0;i++ < cnt; base = (struct ipc_perm *)(((char *)base) + size)) { if(base->mode & IPC_ALLOC) continue; goto init; } u.u_error = ENOSPC; return(NULL); } else { for(i = 0, a = NULL;i++ < cnt; base = (struct ipc_perm *)(((char *)base) + size)) { if(base->mode & IPC_ALLOC) { if(base->key == key) { if((flag & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) { u.u_error = EEXIST; return(NULL); } if((flag & 0777) & ~base->mode) { u.u_error = EACCES; return(NULL); } *status = 0; return(base); } continue; } if(a == NULL) a = base; } if(!(flag & IPC_CREAT)) { u.u_error = ENOENT; return(NULL); } if(a == NULL) { u.u_error = ENOSPC; return(NULL); } base = a; } init: *status = 1; base->mode = IPC_ALLOC | (flag & 0777); base->key = key; base->cuid = base->uid = u.u_uid; base->cgid = base->gid = u.u_gid; return(base); }