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

ipcstream.c

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

Click here to get the file

Size 5.8 kB - File type text/plain

File contents

/*ident	"@(#)ipc:ipcstream.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"

#ifdef __alpha
extern "C" int mknod(const char*, mode_t, int);
#endif
#ifndef FILNMLEN
#define FILNMLEN	14	/* Number of characters in a file name */
#endif

char ipcstream::ftok_id;
char ipc_attachment::ftok_id;

static String	next_string(const String& s);

/* To create an IPC_attachment, open the ipc main file */
ipc_attachment::ipc_attachment(const String& path, const char* /* param */)
: user_p(0), att_name(ipc_fix_name_ATTLC(path)), attached(0)
{
	initialize_attachment();
}

ipc_attachment::ipc_attachment(const char* path, const char* /* param */)
: user_p(0), att_name(ipc_fix_name_ATTLC(path)), attached(0)
{
	initialize_attachment();
}

void
ipc_attachment::initialize_attachment()
{
	xfd = ::open(att_name, O_WRONLY|O_CREAT|O_EXCL, 0666);
	if (xfd < 0) {
		okay = 0;
		return;
	}

	char*	p = new char[att_name.length()+1]; att_name.dump(p);
	key_t	key = ftok(p, ftok_id ? ftok_id : 'z');
	delete p;
	if (key == key_t(-1)) {
		okay = 0;
		::close(xfd); // wct
		return;
	}

	ofstream*	key_p = new ofstream(xfd);
	if (!key_p->good()) {
		okay = 0;
		::close(xfd); // wct
		return;
	}
	*key_p << "Key: " << key << "\n";
	delete key_p;
	::close(xfd);

	if (mknod((const char *)(String(att_name+'a')), 0010666, 0) != 0) {
		okay = 0;
		return;
	}

	if (mknod((const char *)(String(att_name+'b')), 0010666, 0) != 0) {
		okay = 0;
		return;
	}

	last_connection = att_name+'b';

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

	okay = 1;
}

ipc_attachment::~ipc_attachment()
{
	if (xfd < 0)
	    return;

	// the ordering here keeps multiple clients at bay
	unlink(att_name);	// new clients won't find the semaphore
	unlink(String(att_name+'b'));	// waiting clients won't open the reply channel
	int fd = ::open(String(att_name+'a'), O_RDONLY|O_NDELAY);	// un-block at-bat client
	unlink(String(att_name+'a'));	// on-deck client won't find request channel
	if (fd >= 0) ::close(fd);

	if (sema1) {
	    sema1->Close();
	    delete sema1;
	}

	if (sema2) {
	    sema2->Close();
	    delete sema2;
	}
}

void
ipc_attachment::listen()
{
	if (attached) return;

	sema2->P();

	attached = 1;

	// if (user_p) return;

	int	ifd;
	if ((ifd = ::open(String(att_name+'a'), O_RDONLY)) < 0) {
		okay = 0;
	 	return;
	}

	ifstream	ifs(ifd);
	String	temp;
	ifs >> temp >> uid_p >> gid_p;
	if (ifs.good()) {
		user_p = new char[temp.length()+1]; temp.dump(user_p);
	}
	ifs.close();
	::close(ifd);
}

void
ipc_attachment::reject(int err_no, const char* reason)
{
	if (user_p == 0) return;
	int	ofd;
	if ((ofd = ::open(String(att_name+'b'), O_WRONLY)) < 0) {
		okay = 0;
		return;
	}
	ofstream	ofs(ofd);
	ofs << "Reject " << err_no << " " << reason << "\n";
	ofs.close();
	::close(ofd);
	delete user_p;
	user_p = 0;
}

extern int errno;	
ipcstream
ipc_attachment::accept()
{
#ifdef __edg_att_40
	return (ipcstream&)ipcstream(*this);
#else
	return ipcstream(*this);
#endif
}

ipcbuf*
ipc_attachment::create_ipcbuf()
{
	ipcbuf *retval;
	if (!attached) 
	    listen();

	attached = 0;

	String	in_pipe = next_string(last_connection);

	while (mknod((const char *)in_pipe, 0010666, 0) != 0) {
		if (errno != EEXIST) return 0;
		in_pipe = next_string(in_pipe);
	}

	String	out_pipe = next_string(in_pipe);
	while (mknod((const char *)out_pipe, 0010666, 0) != 0) {
		if (errno != EEXIST) return 0;
		out_pipe = next_string(out_pipe);
	}

	last_connection = out_pipe;

	int	ofd;
	if ((ofd = ::open(String(att_name+'b'), O_WRONLY)) < 0) {
	 	retval=0;
	}
	else 
	{

	    ofstream	ofs(ofd);
	    if (ofs.good() == 0)
  		retval = NULL;

	    else
	    {
		ofs << "Accept " << ipc_basename_ATTLC(out_pipe) << " " << ipc_basename_ATTLC(in_pipe) << "\n";
		ofs.close();
		::close(ofd);
		retval = new ipcbuf(in_pipe, out_pipe);
	    }
	}

	return retval;
}

ipcstream::ipcstream(ipc_attachment& attach)
{
	init(attach.create_ipcbuf());
	verify(checkbuf());
}

ipcstream::ipcstream(const char* path, const char* param)
{
	init(new ipcbuf(path, param));
	verify(checkbuf());
}

ipcstream::ipcstream(const String& path, const char* param)
{
	init(new ipcbuf(path, param));
	verify(checkbuf());
}

void ipcstream::verify(int ok)
{
	if ( ok ) clear(ios::goodbit) ;
	else 	  setstate(ios::failbit|ios::badbit) ;
}

void ipcstream::open(const char* name, const char* param)
{
	verify(rdbuf()->open(name, param) != 0 ) ;
}

void ipcstream::open(const String& name, const char* param)
{
	verify(rdbuf()->open(name, param) != 0 ) ;
}


void ipcstream::setbuf(char* p, int len) 
{
	verify(rdbuf()->setbuf(p,len) != 0 ) ;
}

void ipcstream::close() 
{
	verify(rdbuf()->close() != EOF ) ;
}

ipcstream::~ipcstream()
{
#ifdef __GNUG__
	delete rdbuf();
#else
	delete bp;
#endif
}

/* count in base 62 */
static char
next_char(register char c)
{
	if ((c >= 'a' && c < 'z') ||
		(c >= 'A' && c < 'Z') ||
		(c >= '0' && c < '9')) return c+1;
	if (c == 'z') return 'A';
	if (c == 'Z') return '0';
	return 0;
}

static String
next_string(const String& s)
{
	String ans = s;
	char	c = next_char(ans[ans.length()-1]);
	if (c) {
		ans[ans.length()-1] = c;
		return ans;
	}
	ans[ans.length()-1] = 'a';
	int	ans_base = ans.strrchr('/') + 1;
	if (ans.length() - ans_base < FILNMLEN)
		return ans + 'a';
	int i = ans.length()-1;
	while ((c = next_char(ans[(unsigned)--i])) == 0) {
		ans[(unsigned)i] = 'a';
		if (i == ans_base)
			return ans;
	}
	ans[(unsigned)i] = c;
	return ans;
}

« 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: