File:  [Research Unix] / researchv9 / ipc / src / libipc / ipccreat.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 <stdio.h>
#include <ipc.h>
#include "defs.h"

/* imports */
extern int conn_ld;
extern struct passwd *pwsearch();
extern char *strncpy();

/* global to this file */
#define ROOTUID 0

/* plug into the name space */
int
ipccreat(name, param)
	char *name;	/* name being dialed */
	char *param;	/* parameters for creation */
{
	int pfd[2];
	char *path=name;
	ipcinfo info;

	if (path==NULL)
		return ABORT(EINVAL, "name too long", (ipcinfo*)NULL);

	/* make a node to mount onto */
	if (strchr(path, '!')!=NULL || (access(path,0)<0 && creat(path, 0666)<0)) {
		/* remote creat */
		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_CREAT;
		return ipcdial(&info);
	}

	/* get the stream to mount */
	if (pipe(pfd) < 0)
		return ABORT(errno, "out of pipes", (ipcinfo*)NULL);
	if (ioctl(pfd[1], FIOPUSHLD, &conn_ld) < 0) {
		close(pfd[0]);	
		close(pfd[1]);
		return ABORT(errno, "pushing line discipline", (ipcinfo*)NULL);
	}

	/* mount */
	if (fmount(3, pfd[1], path, 0) < 0) {
		close(pfd[0]);
		close(pfd[1]);
		return ABORT(errno, "can't mount", (ipcinfo*)NULL);
	}
	close(pfd[1]);
	return pfd[0];
}

/* listen for a connection */
ipcinfo *
ipclisten(fd)
	int fd;
{
	struct passfd pass;
	int pfd[2];
	static ipcinfo info;
	static char buf[BUFSIZE];
	static char user[32];
	int fd1= -1, fd2= -1;

	/* get a unique stream to the caller */
restart:
	if (_fd_read(fd, &pass)<0) {
		close(fd);
		return NULL;	/* nothing there */
	}
	info.uid = pass.uid;
	info.gid = pass.gid;
	info.rfd = pass.fd;
	strncpy(user, pass.logname, sizeof(pass.logname));
	user[sizeof(pass.logname)] = '\0';
	info.user = user;
	(void)ioctl(info.rfd, FIOACCEPT, &pass);

	/* get possible passed fds */
	if (_fd_read(info.rfd, &pass)>=0) {
		fd1 = pass.fd;
		if (_fd_read(info.rfd, &pass)>=0)
			fd2 = pass.fd;
	}

	/* get the request */
	if (_info_read(info.rfd, &info)<0) {
		/* requestor gave up */
		close(info.rfd);
		if(fd1>=0)
			close(fd1);
		if(fd2>=0)
			close(fd2);
		goto restart;
	}

	/* decode the request */
	if (info.flags & IPC_HANDOFF) {
		close(info.rfd);
		info.rfd = fd1;
		info.cfd = fd2;
		info.flags &= ~IPC_HANDOFF;
	} else {
		info.cfd = fd1;
		if (fd2>=0)
			close(fd2);
	}
	return &info;
}

/*
 *  Accept a connection.  Close all except ip->cfd.
 */
int
ipcaccept(ip)
	ipcinfo *ip;
{
	ipcdaccept(ip, -1, "who_cares");
}
/*
 *  Accept a connection, and supply a source address and communications fd
 */
int
ipcdaccept(ip, commfd, source)
	ipcinfo *ip;
	int commfd;
	char *source;
{
	if (commfd >= 0) {

		/* supply our own channel for communications */
		if (_fd_write(ip->rfd, commfd) < 0) {
			close(commfd);
			return ABORT(errno, "can't pass conection", ip);
		}
		_reply_write(ip->rfd, 0, source);
		ABORT(0, "", ip);
		ip->cfd = commfd;
	} else if (ip->cfd >= 0) {

		/* use client supplied channel for communications */
		_reply_write(ip->rfd, 0, "");
		close(ip->rfd);
		ip->rfd = -1;
	} else {

		/* use reply channel for communications */
		_reply_write(ip->rfd, 0, "");
		ip->cfd = ip->rfd;
		ip->rfd = -1;
	}
	return(ip->cfd);
}

/*  Reject a connection.
 */
int
ipcreject(ip, no, str)
	ipcinfo *ip;
	int no;		/* error number */
	char *str;	/* error string */
{
	_reply_write(ip->rfd, no, str);
	ABORT(no, str, ip);
	return 0;
}

unix.superglobalmegacorp.com

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