Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source libSC ipc ipcbuf.c
Document Actions

ipcbuf.c

by Michael L Powell last modified 2007-01-26 03:23

Click here to get the file

Size 7.5 kB - File type text/plain

File contents

/*ident	"@(#)ipc:ipcbuf.c	3.1" */
/******************************************************************************
*
* C++ Standard Components, Release 3.0.
*
* Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc.
* Copyright (c) 1988, 1989, 1990 AT&T.  All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System
* Laboratories, Inc.  The copyright notice above does not evidence
* any actual or intended publication of such source code.
*
******************************************************************************/

#include "ipclib.h"

#ifndef O_RDONLY
#	include <fcntl.h>
#endif

#ifndef O_TRUNC
#	define O_TRUNC 0
#endif

#ifndef O_CREAT
#	define O_CREAT 0
#endif

#ifndef O_APPEND
#	define O_APPEND 0
#endif

#ifdef __GNUG__
#define zapeof(x) ((x)&0377)
#endif

static String  // includes trailing slash
dirname_plus(const String& arg)
{
	int	base = arg.strrchr('/') + 1;
	if (base == 0) return "./";
	else return arg.chunk(0, base);
}

extern int errno ;

inline void save_errno(int& orig)
{
	orig = ::errno ;
	::errno = 0 ;
}

inline int restore_errno(int& orig)
{
	if ( ::errno == 0 ) ::errno = orig ;
	return EOF ;
}

/*
 *	Open a ipc connection.
 *	Return:		NULL if failure
 *			this if success
 */
ipcbuf* ipcbuf::open (const String& path, const char* /* param */)
{
	int errno_orig ;
	save_errno(errno_orig) ;
	String	name = ipc_fix_name_ATTLC(path);
	char*	p = new char[name.length()+10]; name.dump(p);
	key_t	key = ftok(p, ipcstream::ftok_id ? ipcstream::ftok_id : 'z');
	delete p;
	if (key == key_t(-1)) return 0;

	Monitor* sema1 = new Monitor(key,1);
	sema1->Open();
	sema1->P();

	Monitor* sema2 = new Monitor(key+1,1);
	sema2->Open();
	sema2->V();

	int	fd;

	if ((fd = ::open(String(name+'a'), O_WRONLY)) < 0) {
		sema1->V();
		delete sema1;
		delete sema2;
		return 0;
	}

	if ((p = cuserid(0)) == 0) {
		::close(fd);
		sema1->V();
		delete sema1;
		delete sema2;
		return 0;
	}
	errno = 0;
	{// note no if
		ofstream	ofs(fd);
		ofs << p << " " << getuid() << " " << getgid() << "\n";
		ofs.close();
	}
	::close(fd);
	if ((fd = ::open(String(name+'b'), O_RDONLY)) < 0) {
		sema1->V();
		delete sema1;
		delete sema2;
		return 0;
	}
	{// note no if
		ifstream	ifs(fd);
		String	ans;
		ifs >> ans;
		if (ans == "Accept") {
			String	temp;
			String	dir = dirname_plus(name);
			ifs >> temp;
			String	in_pipe = dir + temp;
			ifs >> temp;
			String	out_pipe = dir + temp;
			out_xfd = ::open(out_pipe, O_WRONLY);
			in_xfd = ::open(in_pipe, O_RDONLY);
			if (in_xfd >= 0 && out_xfd >= 0)
			    opened = 1;
		} else if (ans == "Reject") {
			ifs >> remote_errno;
			remote_reason = sgets(ifs);
		} else {
			remote_errno = -1;
			remote_reason = "Lost synch";
		}
		ifs.close();
	}
	::close(fd);
	sema1->V();
	delete sema1;
	delete sema2;
	return opened ? this : 0;
}

ipcbuf* ipcbuf::open (const char* path, const char* param)
{
	return open(String(path), param);
}

	
/*
 *	Empty an output buffer.
 *	Returns:	EOF on error
 *			0 on success
 */
int ipcbuf::overflow(int c)
{
	int errno_orig ;
	save_errno(errno_orig) ;
	if ( !opened ) return restore_errno(errno_orig) ;
	if ( out_allocate() == EOF ) return restore_errno(errno_orig) ;

	register char* p = aux_base() ;
	register int count = pptr() - p;

	// pptr()==NULL does not imply p < pptr(),  so we need separate
	// test.
	if ( pptr() && count > 0 )  {
		if (count != write(out_xfd,p,count))
			return restore_errno(errno_orig) ;
	}

	setp(pbase(),epptr()) ;

        // cerr << "OverF:abase=" << (int)aux_base() << " pptr=" << (int)pptr() << endl;

	if ( c == EOF ) /* don't do anything */ ;
	else if ( pbase() == epptr() ) {	// unbuffered
		char ch = c;
                // cerr << "OverF:pbase=" << (int)pbase() << " epptr=" << (int)epptr() << endl;
                // cerr << "OverF:xfdout=" << out_xfd << " errno=" << errno_orig << endl;

		if ( write(out_xfd,&ch,1)!=1 ) return restore_errno(errno_orig) ;
		}
	else {
		sputc(c) ;
		}

	restore_errno(errno_orig) ;
	return zapeof(c) ;
}


/*
 *	Fill an input buffer.
 *	Returns:	EOF on error or end of input
 *			next character on success
 */
int ipcbuf::underflow()
{
	int count;

	if ( !opened ) return EOF ;
	if ( in_allocate() == EOF ) return EOF ;
	int orig_errno ;
	save_errno(orig_errno) ;
	if ( in_unbuffered() ) {
#ifdef __hpux
		count = read(in_xfd,(void*)&lahead[0],1) ;
#else
		count = read(in_xfd,&lahead[0],1) ;
#endif
		setg(&lahead[0],&lahead[0],&lahead[count]) ;
		if ( count <= 0 ) return EOF ;
		} 
	else {
		register int	rdsize ;
		if ( blen() > 2*sizeof(long) ) {
			/* gptr must be set greater than base to
			 * guarantee at least 1 char of pushback.
			 * putting it farther will tend in many common
			 * cases to keep things aligned. 
			 */
			in_start = base()+sizeof(long) ;
			rdsize = blen()-sizeof(long) ;
		} else {
			in_start = base()+1 ;
			rdsize = blen()-1 ;
		}
#ifdef __hpux
		count = read(in_xfd,(void*)in_start,rdsize) ;
#else
		count = read(in_xfd,in_start,rdsize) ;
#endif
		while ( count<=0 && ::errno==EINTR ) {
			/*
			 * Signal caught and returned before any data
			 * transfered. 	
			 */
			::errno = 0 ;
#ifdef __hpux
			count = read(in_xfd,(void*)in_start,rdsize) ;
#else
			count = read(in_xfd,in_start,rdsize) ;
#endif
		}

		if ( count <= 0 ) {
			setg(0,0,0) ;
			return restore_errno(orig_errno) ;
			}
		setg(base(),in_start,in_start+count) ;
	}
	
	restore_errno(orig_errno) ;	
	return zapeof(*gptr());
}

int ipcbuf::close()
{
	int f = in_xfd ;
	int g = out_xfd ;
	overflow();
	setg(0,0,0) ;
	setp(0,0) ;
	opened = 0 ;
	in_xfd = out_xfd = -1 ;
	int orig_errno ;
	save_errno(orig_errno) ;
	int ok = ::close(f) | ::close(g);
	restore_errno(orig_errno) ;
	return ok ;
}

int ipcbuf::sync() 
{
	return overflow() ;
}

ipcbuf::ipcbuf()
	: in_xfd(-1), out_xfd(-1), opened(0), x_get_unbuf(0), x_put_unbuf(0),
			aux_x_base(0), aux_alloc(0), owner(0)
{

}

ipcbuf::ipcbuf(const char* path, const char* param)
	: in_xfd(-1), out_xfd(-1), opened(0), x_get_unbuf(0), x_put_unbuf(0),
			aux_x_base(0), aux_alloc(0), owner(0)
{
	open(String(path), param);
}

ipcbuf::ipcbuf(const String& path, const char* param)
	: in_xfd(-1), out_xfd(-1), opened(0), x_get_unbuf(0), x_put_unbuf(0),
			aux_x_base(0), aux_alloc(0), owner(0)
{
	open(path, param);
}

ipcbuf::ipcbuf(int in_fd, int out_fd)
	: in_xfd(in_fd), out_xfd(out_fd), opened(1), x_get_unbuf(0),
			x_put_unbuf(0), aux_x_base(0), aux_alloc(0), owner(0)
{

}

ipcbuf::ipcbuf(String in_pipe, String out_pipe)
	: opened(1), x_get_unbuf(0),
			x_put_unbuf(0), aux_x_base(0), aux_alloc(0), owner(1),
			in_pip(in_pipe), out_pip(out_pipe)
{
	if ((in_xfd = ::open(in_pipe, O_RDONLY)) < 0 ||
			(out_xfd = ::open(out_pipe, O_WRONLY)) < 0)
		opened = 0;
}

ipcbuf::~ipcbuf() {
	close() ;
	if (owner) {
		unlink(in_pip);
		unlink(out_pip);
	}
}

streambuf* ipcbuf::setbuf(char*, int)
{
	return 0;
}

streambuf* ipcbuf::set_in_buf(char* p , int len)
{
	if ( base() ) return 0 ;
	if ( len <= 0 || p == 0 ) {
		// make it unbuffered
		setb(0,0,0) ;
		setg(0,0,0) ;
		in_unbuffered(1) ; 
		}
	else {
		setb(p,p+len,0) ;
		setg(p,p,p) ;
		in_unbuffered(0) ;
		} 
	return this;
}

streambuf* ipcbuf::set_out_buf(char* p , int len)
{
	if ( aux_base() ) return 0 ;
	if ( len <= 0 || p == 0 ) {
		// make it unbuffered
		aux_setb(0,0,0) ;
		setp(0,0) ;
		out_unbuffered(1) ; 
		}
	else {
		aux_setb(p,p+len,0) ;
		setp(p,p+len) ;
		out_unbuffered(0) ;
		} 
	return this;
}

/*
	Allocate some space for the buffer.
	Returns:	EOF on error
			0 on success
*/
int ipcbuf::do_out_allocate()
{
	char *buf = new char[STREAMBUFSIZE] ;
	if ( !buf ) return EOF ;
	aux_setb(buf,buf+STREAMBUFSIZE,1) ;
	return 0;
}
« December 2014 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: