Ultrix-3.1/sys/sys/ipc.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   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);
}