⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cc

📁 This Source-Navigator, an IDE for C/C++/Fortran/Java/Tcl/PHP/Python and a host of other languages.
💻 CC
📖 第 1 页 / 共 2 页
字号:
// $Header: /cvsroot/sourcenav/src/snavigator/demo/c++_demo/glish/Client.cc,v 1.1.1.1 2002/04/18 23:35:24 mdejong Exp $#include "system.h"#include <stdlib.h>#include <osfcn.h>#include <fcntl.h>#include <ctype.h>#include <string.h>#include <errno.h>#include <signal.h>#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endifextern "C" {#include <netinet/in.h>#ifndef HAVE_STRDUPchar* strdup( const char* );#endif}#include "Sds/sdsgen.h"#include "Glish/Client.h"#include "BuiltIn.h"#include "Reporter.h"#include "Socket.h"#include "glish_event.h"#include "system.h"typedef RETSIGTYPE (*SigHandler)(int);static Client* current_client;static const char* prog_name = "glish-interpreter";static int did_init = 0;inline streq( const char* s1, const char* s2 )	{	return ! strcmp( s1, s2 );	}void Client_signal_handler()	{	current_client->HandlePing();	}GlishEvent::GlishEvent( const char* arg_name, const Value* arg_value )	{	name = arg_name;	value = (Value*) arg_value;	flags = 0;	delete_name = delete_value = 0;	}GlishEvent::GlishEvent( const char* arg_name, Value* arg_value )	{	name = arg_name;	value = arg_value;	flags = 0;	delete_name = 0;	delete_value = 1;	}GlishEvent::GlishEvent( char* arg_name, Value* arg_value )	{	name = arg_name;	value = arg_value;	flags = 0;	delete_name = delete_value = 1;	}GlishEvent::~GlishEvent()	{	if ( delete_name )		delete (char*) name;	if ( delete_value )		Unref( (Value*) value );	}int GlishEvent::IsRequest() const	{	return flags & GLISH_REQUEST_EVENT;	}int GlishEvent::IsReply() const	{	return flags & GLISH_REPLY_EVENT;	}void GlishEvent::SetIsRequest()	{	flags |= GLISH_REQUEST_EVENT;	}void GlishEvent::SetIsReply()	{	flags |= GLISH_REPLY_EVENT;	}class EventLink {public:	EventLink( char* task_id, char* new_name, int initial_activity )		{		id = task_id;		name = new_name;		fd = -1;		active = initial_activity;		path = 0;		}	~EventLink()		{		delete id;		delete name;		delete path;		}	const char* ID() const		{ return id; }	int FD() const			{ return fd; }	int Active() const		{ return active; }	const char* Name() const	{ return name; }	const char* Path() const	{ return path; }	void SetActive( int activity )	{ active = activity; }	void SetFD( int new_fd )	{ fd = new_fd; }	void SetPath( const char* p )	{ path = strdup( p ); }private:	char* id;	char* name;	int fd;	int active;	char* path;	// if nil, indicates this is a non-local socket	};Client::Client( int& argc, char** argv )	{	char** orig_argv = argv;	prog_name = argv[0];	--argc, ++argv;	// remove program name from argument list	ClientInit();	int suspend = 0;	no_glish = 0;	interpreter_tag = "*no-interpreter*";	if ( argc < 2 || ! streq( argv[0], "-id" ) )		{		// We weren't invoked by the Glish interpreter.  Set things up		// so that we receive "events" from stdin and send them		// to stdout.		have_interpreter_connection = 0;		client_name = prog_name;		if ( argc == 0 || (argc >= 1 && !streq( argv[0], "-glish" )) )			{			no_glish = 1;			}		if ( argc >= 1 && streq( argv[0], "-noglish" ) )			{			no_glish = 1;			--argc, ++argv;			}		else			{			read_fd = fileno( stdin );			write_fd = fileno( stdout );			if ( argc >= 1 && streq( argv[0], "-glish" ) )				// Eat up -glish argument.				--argc, ++argv;			}		}	else		{		have_interpreter_connection = 1;		client_name = argv[1];		argc -= 2, argv += 2;		if ( argc < 2 ||		     (! streq( argv[0], "-host" ) &&		      ! streq( argv[0], "-pipes" )) )			fatal->Report(		"invalid Client argument list - missing connection arguments" );		if ( streq( argv[0], "-host" ) )			{ // Socket connection.			char* host = argv[1];			argc -= 2, argv += 2;			if ( argc < 2 || ! streq( argv[0], "-port" ) )				fatal->Report(			"invalid Client argument list - missing port number" );			int port = atoi( argv[1] );			argc -= 2, argv += 2;			int socket = get_tcp_socket();			if ( ! remote_connection( socket, host, port ) )				fatal->Report(		"could not establish Client connection to interpreter" );			read_fd = write_fd = socket;			}		else			{ // Pipe connection.			++argv, --argc;	// skip -pipes argument			if ( argc < 2 )				fatal->Report(			"invalid Client argument list - missing pipe fds" );			read_fd = atoi( argv[0] );			write_fd = atoi( argv[1] );			argc -= 2, argv += 2;			}		if ( argc > 1 && streq( argv[0], "-interpreter" ) )			{			interpreter_tag = argv[1];			argc -= 2, argv += 2;			}		if ( argc > 0 && streq( argv[0], "-suspend" ) )			{			suspend = 1;			--argc, ++argv;			}		}	if ( suspend )		{		int pid = int( getpid() );		fprintf( stderr, "%s @ %s, pid %d: suspending ...\n",			prog_name, local_host, pid );		while ( suspend )			sleep( 1 );	// allow debugger to attach		}	if ( have_interpreter_connection )		SendEstablishedEvent();	CreateSignalHandler();	for ( int i = 1; i <= argc; ++i )		orig_argv[i] = *(argv++);	orig_argv[i] = 0;	argv = orig_argv;	// Put argv[0] back into the argument count - it was removed	// near the top of this routine.	++argc;	}Client::Client( int client_read_fd, int client_write_fd, const char* name )	{	client_name = prog_name = name;	ClientInit();	no_glish = 0;	have_interpreter_connection = 1;	read_fd = client_read_fd;	write_fd = client_write_fd;	SendEstablishedEvent();	CreateSignalHandler();	}Client::~Client()	{	(void) install_signal_handler( SIGIO, former_handler );	if ( have_interpreter_connection )		PostEvent( "done", client_name );	if ( ! no_glish )		{		close( read_fd );		close( write_fd );		}	}GlishEvent* Client::NextEvent()	{	if ( no_glish )		return 0;	if ( input_links.length() == 0 )		// Only one input channel, okay to block reading it.		return GetEvent( read_fd );	fd_set input_fds;	FD_ZERO( &input_fds );	AddInputMask( &input_fds );	while ( select( FD_SETSIZE, &input_fds, 0, 0, 0 ) < 0 )		{		if ( errno != EINTR )			{			fprintf( stderr, "%s: ", prog_name );			perror( "error during select()" );			return 0;			}		}	return NextEvent( &input_fds );	}GlishEvent* Client::NextEvent( fd_set* mask )	{	if ( no_glish )		return 0;	if ( FD_ISSET( read_fd, mask ) )		return GetEvent( read_fd );	loop_over_list( input_links, i )		{		int fd = input_links[i];		if ( FD_ISSET( fd, mask ) )			return GetEvent( fd );		}	PostEvent( "error", "bad call to Client::NextEvent" );	return 0;	}void Client::Unrecognized()	{	if ( ! last_event )		return;	if ( last_event->name[0] == '*' )		// Internal event - ignore.		return;	PostEvent( "unrecognized", last_event->name );	}void Client::Error( const char* msg )	{	if ( last_event )		PostEvent( "error", "bad \"%s\" event: %s",				last_event->name, msg );	else		PostEvent( "error", msg );	}void Client::Error( const char* fmt, const char* arg )	{	char buf[8192];	sprintf( buf, fmt, arg );	Error( buf );	}void Client::PostEvent( const char* event_name, const Value* event_value )	{	GlishEvent e( event_name, event_value );	SendEvent( &e );	}void Client::PostEvent( const GlishEvent* event )	{	SendEvent( event );	}void Client::PostEvent( const char* event_name, const char* event_value )	{	Value val( event_value );	PostEvent( event_name, &val );	}void Client::PostEvent( const char* event_name, const char* event_fmt,    const char* event_arg )	{	char buf[8192];	sprintf( buf, event_fmt, event_arg );	PostEvent( event_name, buf );	}void Client::PostEvent( const char* event_name, const char* event_fmt,    const char* arg1, const char* arg2 )	{	char buf[8192];	sprintf( buf, event_fmt, arg1, arg2 );	PostEvent( event_name, buf );	}void Client::Reply( const Value* event_value )	{	if ( ! ReplyPending() )		error->Report( prog_name,	" issued Reply without having received a corresponding request" );	else		{		GlishEvent e( (const char*) pending_reply, event_value );		e.SetIsReply();		PostEvent( &e );		delete pending_reply;		pending_reply = 0;		}	}void Client::PostOpaqueSDS_Event( const char* event_name, int sds )	{	GlishEvent e( event_name, (const Value*) 0 );	SendEvent( &e, sds );	}int Client::AddInputMask( fd_set* mask )	{	if ( no_glish )		return 0;	int num_added = 0;	if ( ! FD_ISSET( read_fd, mask ) )		{		FD_SET( read_fd, mask );		++num_added;		}	// Now add in any fd's due to event links.	loop_over_list( input_links, i )		if ( ! FD_ISSET( input_links[i], mask ) )			{			FD_SET( input_links[i], mask );			++num_added;			}	return num_added;	}int Client::HasClientInput( fd_set* mask )	{	if ( no_glish )		return 0;	if ( FD_ISSET( read_fd, mask ) )		return 1;	loop_over_list( input_links, i )		{		if ( FD_ISSET( input_links[i], mask ) )			return 1;		}	return 0;	}void Client::ClientInit()	{	if ( ! did_init )		{		sds_init();		init_reporters();		init_values();		did_init = 1;		}	last_event = 0;	pending_reply = 0;	local_host = local_host_name();	}void Client::CreateSignalHandler()	{	current_client = this;	former_handler = install_signal_handler( SIGIO, Client_signal_handler );	}void Client::SendEstablishedEvent()	{	Value* r = create_record();	r->SetField( "name", client_name );	r->SetField( "protocol", GLISH_CLIENT_PROTO_VERSION );	PostEvent( "established", r );	Unref( r );	}GlishEvent* Client::GetEvent( int fd )	{	Unref( last_event );	if ( have_interpreter_connection )		{		last_event = recv_event( fd );		if ( ! last_event && fd != read_fd )			{			// A link has gone away; but don't return a nil			// event, that'll cause us to go away too.  Instead,			// remove this fd from the list of input links and			// cobble together a dummy event.			input_links.remove( fd );			FD_Change( fd, 0 );			last_event = new GlishEvent( (const char*) "*dummy*",							error_value() );			}		if ( last_event )			{			Value* v = last_event->value;			if ( v->FieldVal( "*reply*", pending_reply ) )				{ // Request/reply event; unwrap the request.				Value* request = v->Field( "*request*" );				if ( ! request )					fatal->Report(						"bad request/reply event" );				Ref( request );				Unref( v );				last_event->value = request;				}			}		}	else		{		char buf[512];		if ( ! fgets( buf, sizeof( buf ), stdin ) )			return 0;		// Nuke final newline, if present.		char* delim = strchr( buf, '\n' );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -