File:  [Research Unix] / researchv9 / ipc / src / libipc / ipcopen.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <ipc.h>
#include "defs.h"

/* exported */
char *errstr;

/* imports */
extern int atoi();
extern char *memchr();

/* dial a name and return an fd to the connection */
int
ipcopen(name, param)
	char *name;	/* name being dialed */
	char *param;	/* parameters for dialer */
{
	ipcinfo info;

	info.rfd = info.cfd = -1;
	info.myname = info.user = info.machine = NULL;
	info.uid = info.gid = -1;
	info.name = name;
	info.param = param;
	info.flags = IPC_OPEN;
	return ipcdial(&info);
}

/*
 *  Open a mounted steam.  ip->name points to a string of the form
 *  path!address.  Path must be a file system path to a mounted stream.
 */ 
_ipcopen(ip)
	ipcinfo *ip;
{
	static stretch path;
	char *np;
	int fd;
	struct stat sbuf;

	/* split into path and network address */
	_strcat(&path, ip->name, (char *)NULL, (char *)NULL);
	np = strchr(path.ptr, '!');
	if (np) {
		*np = '\0';
		ip->name += np - path.ptr + 1;
	}
	if (ip->flags&IPC_CAREFUL) {
		if (stat(path.ptr, &sbuf)<0)
			return ABORT(ENOENT, "destination nonexistent", NULLINFO);
		if (sbuf.st_mode&6 != 6)
			return ABORT(EACCES, "permission denied", NULLINFO);
	}
	if ((fd = open(path.ptr, 2))<0) {
		if (errno==EACCES){
			if (*(ip->name))
			    return ABORT(EACCES, "can't access dialer", NULLINFO);
			else
			    return ABORT(EACCES, "permission denied", NULLINFO);
		} else
			return ABORT(ENOENT, "destination nonexistent", NULLINFO);
	}

	/* update the translated part of the name */
	if(ip->myname)
		_strcat(&path, ip->myname, "!", path.ptr);
	ip->myname = path.ptr;
	return fd;
}

/* dial a name and return an fd to the connection */
int
ipcdial(ip)
	ipcinfo *ip;
{
	struct passfd pass;
	int fd;

	if ((fd = _ipcopen(ip))<0)
		return -1;

	/* pass reply channel */
	if (ip->rfd >= 0) {
		if (_fd_write(fd, ip->rfd)<0) {
			close(fd);
			return ABORT(EIO, "protocol botch", ip);
		}
		close(ip->rfd);
		ip->rfd = -1;
	}

	/* pass communications channel (if not same as reply channel) */
	if (ip->cfd >= 0) {
		if (_fd_write(fd, ip->cfd)<0) {
			close(fd);
			return ABORT(EIO, "protocol botch", ip);
		}
		close(ip->cfd);
		ip->cfd = -1;
	}

	/* pass the info on */
	if (_info_write(fd, ip) < 0) {
		close(fd);
		return ABORT(errno, errstr, ip);
	}
	if (ip->flags&IPC_HANDOFF)
		return fd;

	/* get the reply  */
	if (_fd_read(fd, &pass)>=0) {
		_reply_read(fd);
		if (errno != 0) {
			close(fd);
			close(pass.fd);
			return ABORT(errno, errstr, NULLINFO);
		}
		return pass.fd;
	} else {
		_reply_read(fd);
		if (errno != 0) {
			close(fd);
			return ABORT(errno, errstr, NULLINFO);
		}
		return fd;
	}
}

/*
 *  Pass a request to someone else to handle.
 */
ipcpass(ip)
	ipcinfo *ip;
{
	ip->flags |= IPC_HANDOFF;
	return ipcdial(ip);
}

/* set error number and string and return -1 */
int
_ipcabort(no, err, ip)
	int no;
	char *err;
	ipcinfo *ip;
{
	if (ip!=NULLINFO) {
		if (ip->cfd>0) {
			close(ip->cfd);
			ip->cfd = -1;
		}
		if (ip->rfd>0) {
			close(ip->rfd);
			ip->rfd = -1;
		}
	}
	errstr = err;
	errno = no;
	return -1;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.