Initial import of the CDE 2.1.30 sources from the Open Group.

This commit is contained in:
Peter Howkins
2012-03-10 18:21:40 +00:00
commit 83b6996daa
18978 changed files with 3945623 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
XCOMM $TOG: Imakefile /main/8 1999/08/30 10:52:07 mgreess $
#define DoNormalLib NormalLibTt
#define DoSharedLib SharedLibTt
#define DoDebugLib DebugLibTt
#define DoProfileLib ProfileLibTt
#define LibName tt
#define SoRev SOTTREV
#define LibHeaders NO
#define LibCreate NO
#define CplusplusSource YES
DEPEND_DEFINES = $(CXXDEPENDINCLUDES) $(ISAM_INCLUDES)
#include <Threads.tmpl>
#include "../../tooltalk.tmpl"
DEFINES =
INCLUDES = -I../../lib
ISAM_INCLUDES = -I../../mini_isam
/* Use BSD-compatible accept() call */
#ifdef RsArchitecture
CXXEXTRA_DEFINES = -DCOMPAT_43
#endif
/*** NOTE!
*** Every time a .o is added below it needs to be added to
*** the lib/tt/lib Imakefile in MP_OBJS and SHARED_MP_OBJS
***/
SRCS = mp_arg.C mp_arg_utils.C mp_auth.C \
mp_auth_functions.C mp_c_file.C \
mp_c_file_utils.C mp_c_message.C mp_c_message_utils.C \
mp_c_mp.C mp_c_msg_context.C mp_c_msg_context_utils.C \
mp_c_pattern.C mp_c_procid.C mp_c_procid_utils.C \
mp_c_session.C mp_c_session_prop.C mp_c_session_utils.C \
mp_context.C mp_context_utils.C mp_desktop.C \
mp_desktop_utils.C mp_file.C mp_file_utils.C \
mp_message.C mp_message_utils.C mp_mp.C \
mp_mp_utils.C mp_msg_context.C mp_msg_context_utils.C \
mp_pat_context.C mp_pat_context_utils.C mp_pattern.C \
mp_pattern_utils.C mp_procid.C mp_procid_utils.C \
mp_rpc_client.C mp_rpc_client_utils.C mp_rpc_fns.C \
mp_session.C mp_session_prop.C mp_session_prop_utils.C \
mp_session_utils.C mp_stream_socket.C mp_stream_socket_utils.C \
mp_trace.C mp_xdr_functions.C
OBJS = mp_arg.o mp_arg_utils.o mp_auth.o \
mp_auth_functions.o mp_c_file.o \
mp_c_file_utils.o mp_c_message.o mp_c_message_utils.o \
mp_c_mp.o mp_c_msg_context.o mp_c_msg_context_utils.o \
mp_c_pattern.o mp_c_procid.o mp_c_procid_utils.o \
mp_c_session.o mp_c_session_prop.o mp_c_session_utils.o \
mp_context.o mp_context_utils.o mp_desktop.o \
mp_desktop_utils.o mp_file.o mp_file_utils.o \
mp_message.o mp_message_utils.o mp_mp.o \
mp_mp_utils.o mp_msg_context.o mp_msg_context_utils.o \
mp_pat_context.o mp_pat_context_utils.o mp_pattern.o \
mp_pattern_utils.o mp_procid.o mp_procid_utils.o \
mp_rpc_client.o mp_rpc_client_utils.o mp_rpc_fns.o \
mp_session.o mp_session_prop.o mp_session_prop_utils.o \
mp_session_utils.o mp_stream_socket.o mp_stream_socket_utils.o \
mp_trace.o mp_xdr_functions.o
#include <Library.tmpl>
SubdirLibraryRule($(OBJS))
DependTarget()

23
cde/lib/tt/lib/mp/mp.h Normal file
View File

@@ -0,0 +1,23 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp.h /main/3 1995/10/23 10:18:24 rswiston $ */
/*
* mp.h -- public interface classes to the Message Passer
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef _MP_H
#define _MP_H
#include <mp/mp_global.h>
#include <mp/mp_arg.h>
#include <mp/mp_file.h>
#include <mp/mp_message.h>
#include <mp/mp_mp.h>
#include <mp/mp_procid.h>
#include <mp/mp_pattern.h>
#include <mp/mp_session.h>
#endif /* _MP_H */

381
cde/lib/tt/lib/mp/mp_arg.C Normal file
View File

@@ -0,0 +1,381 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_arg.C /main/3 1995/10/23 10:18:54 rswiston $
/*
*
* @(#)mp_arg.C 1.19 93/09/07
*
* Tool Talk Message Passer (MP) - mp_arg.C
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_arg & _Tt_arg_list classes representing
* arguments to a method or a procedure.
*/
#include "mp/mp_global.h"
#include "mp/mp_arg.h"
#include <stdlib.h>
#include <string.h>
#include "util/tt_enumname.h"
#include "util/tt_iostream.h"
#include "util/tt_xdr_utils.h"
#include "util/tt_global_env.h"
/*
* Construct a _Tt_arg with everything zeroed out
*/
_Tt_arg::
_Tt_arg()
{
constructor_common();
}
/*
* Copy constructor for _Tt_args.
*/
_Tt_arg::
_Tt_arg(const _Tt_arg &a)
{
_mode = a._mode;
_type = a._type;
_name = a._name;
_data_type = a._data_type;
_data_int = a._data_int;
_data_string = a._data_string;
}
/*
* Copy the _Tt_arg pointed to by a _Tt_arg_ptr.
*/
_Tt_arg::
_Tt_arg(const _Tt_arg_ptr &p)
{
_mode = p->_mode;
_type = p->_type;
_name = p->_name;
_data_type = p->_data_type;
_data_int = p->_data_int;
_data_string = p->_data_string;
}
_Tt_arg::
_Tt_arg(const _Tt_string &t)
{
constructor_common();
_type = t;
}
/*
* Constructs a _Tt_arg where the mode and type are known.
* No valid data is yet known.
*
*/
_Tt_arg::
_Tt_arg(Tt_mode m, _Tt_string &t)
{
constructor_common();
_mode = m;
_type = t;
}
_Tt_arg::
_Tt_arg(const char *t)
{
_Tt_string ts(t);
constructor_common();
_type = ts;
}
/*
* Constructs a _Tt_arg where the mode and type are known.
* No valid data is yet known.
*
*/
_Tt_arg::
_Tt_arg(Tt_mode m, const char *t)
{
_Tt_string ts(t);
constructor_common();
_mode = m;
_type = ts;
}
/*
* Destroys any memory associated with _Tt_arg
*/
_Tt_arg::
~_Tt_arg()
{
}
/*
* Sets the data associated with this arg as an integer
*/
Tt_status _Tt_arg::
set_data_int(int i)
{
_data_type = INT;
_data_int = i;
return TT_OK;
}
/*
* Sets the data associated with this arg as a byte string
*/
Tt_status _Tt_arg::
set_data_string(const _Tt_string &s)
{
_data_type = STRING;
_data_string = s;
return TT_OK;
}
/*
* Obtain the data for this arg as an int.
* Return TT_ERR_NUM if the value is a string.
*/
Tt_status _Tt_arg::
data_int(int &i) const
{
if (_data_type != INT) return TT_ERR_NUM;
i = _data_int;
return TT_OK;
}
/*
* Obtain the data for this arg as a string.
* Return TT_ERR_POINTER if the value is an int.
*/
Tt_status _Tt_arg::
data_string(_Tt_string &s) const
{
if (_data_type != STRING) return TT_ERR_POINTER;
s = _data_string;
return TT_OK;
}
/*
* Prints out a _Tt_arg. Mainly used for debugging purposes only.
*/
void _Tt_arg::
print(const _Tt_ostream &os) const
{
os << _tt_enumname(_mode) << " " << _type << ": ";
if (_name.len() > 0) {
os << "<" << _name << ">\n";
} else if (_data_type==INT) {
os << _data_int << "\n";
} else {
_data_string.print(os, _Tt_string_user_width, 1);
os << "\n";
}
}
/*
* XDR encodes and decodes a _Tt_arg object. Returns 1 if successful and
* 0 otherwise.
*/
bool_t _Tt_arg::
xdr(XDR *xdrs)
{
if (! xdr_int(xdrs, (int *)&_mode)) {
return(0);
}
if (! _type.xdr(xdrs)) {
return(0);
}
if (_tt_global->xdr_version() < TT_PUSH_ROTATE_XDR_VERSION) {
//
// Earlier versions of the XDR protocol included an
// a never-used _Tt_string called _matched_type.
//
_Tt_string _matched_type;
if (! _matched_type.xdr(xdrs)) {
return(0);
}
}
if (! _name.xdr(xdrs)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_data_type)) {
return(0);
}
if (_data_type==INT) {
if (! xdr_int(xdrs, &_data_int)) {
return(0);
}
} else {
if (! _data_string.xdr(xdrs)) {
return(0);
}
}
return(1);
}
/*
* update_value is used when merging a reply with the original message.
* The value cells of this arg are updated with the value cells in the
* given arg.
*/
Tt_status _Tt_arg::
update_value(const _Tt_arg &x)
{
_data_type = x._data_type;
_data_int = x._data_int;
_data_string = x._data_string;
return TT_OK;
}
/*
* Wrapper whose only purpose is to invoke the xdr method on the given
* pointer.
*/
bool_t
tt_xdr_arg(XDR *xdrs, _Tt_arg_ptr *ptr)
{
return((*ptr)->xdr(xdrs));
}
/*
* XDR encodes and decodes a list of _Tt_arg objects. p is assumed to
* point to the list on which to append/get the objects.
*/
bool_t
tt_xdr_arg_list(XDR *xdrs, _Tt_arg_list_ptr *p)
{
return((*p).xdr(xdrs));
}
void
_tt_arg_print(const _Tt_ostream &os, const _Tt_object *obj)
{
((_Tt_arg *)obj)->print(os);
}
/*
* Common initialization code for _Tt_arg constructors.
*/
void _Tt_arg::
constructor_common()
{
_mode = TT_MODE_UNDEFINED;
_type = (char *)0;
_name = (char *)0;
_data_type = UNSET;
_data_int = 0;
_data_string = (char *)0;
}
/*
* Returns non-zero score if \'this\', which must be a pattern arg, matches
* the given arg, which must be a message arg. Matching is
* less restrictive than equality, since the following exceptions
* apply:
* 1\) If the pattern type is ALL, it matches any type in the message.
* 2\) If the message type is ALL, it matches any type in the pattern.
* \[Somehow, the pattern type should get into the message, but
* I don\'t know how yet.\]
* 3\) If the pattern value is not set, it matches any value in the
* message.
* Although this method is only used in the server, it is too hard
* to figure out how to get messages and patterns un-XDRed in
* the server with args as a _Tt_s_arg instead of _Tt_arg.
*/
int _Tt_arg::
match_score(const _Tt_arg &msg_arg, int &used_wildcard) const
{
// Comparing args works because XDR is defined as always
// padding with zeroes.
int score = 1; // wildcard match scores only 1
used_wildcard = 0;
// match modes
if (_mode == msg_arg.mode()) {
score++;
} else if (_mode != TT_MODE_UNDEFINED) {
return 0;
}
// match types
if (_type == msg_arg.type()) {
// check equality first, in case both are "ALL"
score++;
} else if (_type == "ALL") {
used_wildcard = 1; // pattern ALL matches everything
} else if (msg_arg.type() == "ALL") {
used_wildcard = 1; // message ALL matches everything
} else {
return 0; // types mismatched
}
// match values
switch (_data_type) {
case INT:
case STRING:
default:
if (msg_arg.data_type() != _data_type) {
return 0;
}
switch (_data_type) {
case INT:
if (msg_arg.data_int() != _data_int) {
return 0;
}
break;
case STRING:
if (msg_arg.data_string() != _data_string) {
return 0;
}
break;
default:
return 0;
}
score++;
break;
case UNSET:
if (msg_arg.data_type() != _data_type) {
used_wildcard = 1;
}
break;
}
// everything matches
return score;
}
//
// Returns 1 if the typed values are equal, else 0. Ignores mode and
// vtype. Used by _Tt_pat_context::deleteValue().
//
int _Tt_arg::
operator==(const _Tt_arg &arg) const
{
if (_data_type != arg.data_type()) {
return 0;
}
switch (_data_type) {
case INT:
if (_data_int != arg.data_int()) {
return 0;
}
break;
case STRING:
if (_data_string != arg.data_string()) {
return 0;
}
}
return 1;
}

View File

@@ -0,0 +1,96 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_arg.h /main/3 1995/10/23 10:19:02 rswiston $ */
/* -*-C++-*-
* Tool Talk Message Passer (MP) - mp_arg.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
*
* _Tt_arg is an object that represents a positional argument in a
* _Tt_message. This object implements methods to do the XDR encoding
* and decoding of value types (which may be user-defined). This
* module also implements XDR encoding and decoding of _Tt_arg_list
* objects but this will eventually be integrated into the list
* package.
*/
#ifndef _MP_ARG_H
#define _MP_ARG_H
#include <mp/mp_global.h>
#include <mp/mp_arg_utils.h>
#include <rpc/rpc.h>
class _Tt_message;
class _Tt_arg : public _Tt_object {
public:
enum stored_data_type {UNSET,INT,STRING};
_Tt_arg();
_Tt_arg(const _Tt_arg &a);
_Tt_arg(const _Tt_arg_ptr &p);
_Tt_arg(const _Tt_string &t);
_Tt_arg(Tt_mode m, _Tt_string &type);
_Tt_arg(const char *t);
_Tt_arg(Tt_mode m, const char *type);
virtual ~_Tt_arg();
Tt_status set_data_int(int i);
Tt_status set_data_string(const _Tt_string &s);
Tt_status set_mode(Tt_mode m) {
_mode = m;
return TT_OK;
}
Tt_status set_type(const _Tt_string &type) {
_type = type;
return TT_OK;
}
Tt_status set_name(const _Tt_string &name) {
_name = name;
return TT_OK;
}
Tt_mode mode() const {
return _mode;
}
const _Tt_string &type() const {
return _type;
}
const _Tt_string &name() const {
return _name;
}
stored_data_type data_type() const {
return _data_type;
}
Tt_status data_int(int &i) const;
int data_int() const {
return _data_int;
}
Tt_status data_string(_Tt_string &s) const;
const _Tt_string &data_string() const {
return _data_string;
}
void print(const _Tt_ostream &os) const;
bool_t xdr(XDR *xdrs);
Tt_status update_value(const _Tt_arg &x);
int match_score(const _Tt_arg &arg,
int &used_wildcard) const;
int operator==(const _Tt_arg &arg) const;
protected:
Tt_mode _mode;
_Tt_string _type;
_Tt_string _name;
stored_data_type _data_type;
// Only one of the following two values will be set. This could
// be a union, with _data_type as the discriminant, but it is
// not worth the trouble.
int _data_int;
_Tt_string _data_string;
private:
void constructor_common();
};
void _tt_arg_print(const _Tt_ostream &os, const _Tt_object *obj);
bool_t tt_xdr_arg(XDR *xdrs, _Tt_arg_ptr *ptr);
bool_t tt_xdr_arg_list(XDR *xdrs, _Tt_arg_list_ptr *lptr);
#endif /* _MP_ARG_H */

View File

@@ -0,0 +1,14 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_arg_utils.C /main/3 1995/10/23 10:19:09 rswiston $
/*
*
* mp_arg_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_arg.h>
implement_list_of(_Tt_arg)

View File

@@ -0,0 +1,20 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_arg_utils.h /main/3 1995/10/23 10:19:16 rswiston $ */
/*
*
* mp_arg_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_ARG_UTILS_H
#define MP_ARG_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
class _Tt_arg;
declare_list_of(_Tt_arg)
#endif /* MP_ARG_UTILS_H */

329
cde/lib/tt/lib/mp/mp_auth.C Normal file
View File

@@ -0,0 +1,329 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_auth.C /main/2 1999/08/30 14:13:40 mgreess $
/*
* @(#)mp_auth.C 1.84 96/01/10
*
* Tool Talk Message Passer (MP) - mp_auth.cc
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_auth class.
*/
#include <unistd.h>
#include <sys/stat.h>
#include "mp/mp_auth.h"
#include "mp/mp_auth_functions.h"
#include "mp/mp_global.h"
#include "util/tt_port.h"
_Tt_auth::
_Tt_auth(_Tt_auth_level auth_level)
{
_auth_level = auth_level;
_auth_cookie = "";
}
_Tt_auth::
~_Tt_auth()
{
}
Tt_status _Tt_auth::
generate_auth_cookie()
{
static char *funcname = "_Tt_auth::make_auth_cookie()";
_tt_AuthFileEntry *entry;
int exists;
char *filename;
int original_umask;
int retval;
Tt_status status;
_entries_head = _entries_tail = NULL;
status = TT_OK;
_auth_cookie = _tt_GenerateMagicCookie(_TT_ICEAUTH_MAGIC_COOKIE_LEN);
if (! (filename = _tt_AuthFileName())) {
_tt_syslog(0, LOG_ERR, "%s: Missing TTAUTHORITY file.\n", funcname);
return TT_AUTHFILE_MISSING;
}
if (_tt_AuthLockSuccess !=
(retval = _tt_LockAuthFile(filename,
_TT_ICEAUTH_DEFAULT_RETRIES,
_TT_ICEAUTH_DEFAULT_TIMEOUT,
_TT_ICEAUTH_DEFAULT_DEADTIME))) {
char *reason = "unknown error";
_tt_UnlockAuthFile(filename);
if (retval == _tt_AuthLockTimeout) {
reason = "timeout";
status = TT_AUTHFILE_LOCK_TIMEOUT;
}
else {
reason = "lock error";
status = TT_AUTHFILE_LOCK;
}
_tt_syslog(0, LOG_ERR,
"%s: %s in locking authority file \"%s\".\n",
funcname, reason, filename);
return status;
}
original_umask = umask(077);
exists = (0 == access(filename, F_OK));
if (exists && (0 != access(filename, R_OK | W_OK)))
{
_tt_syslog(0, LOG_ERR,
"%s: \"%s\" not writable, auth entry not added.\n",
funcname, filename);
status = TT_AUTHFILE_ACCESS;
goto cleanup;
}
if (exists && TT_OK != (status = read_auth_file(filename))) {
_tt_syslog(0, LOG_ERR,
"%s: could not read \"%s\". New entry not written.\n",
funcname, filename);
goto cleanup;
}
entry = (_tt_AuthFileEntry*) malloc(sizeof(_tt_AuthFileEntry));
if (NULL == entry) {
_tt_syslog(0, LOG_ERR,
"%s: memory error. New entry not written.\n",
funcname);
status = TT_ERR_NOMEM;
goto cleanup;
}
entry->protocol_name = strdup(_TT_ICEAUTH_PROTOCOL_NAME);
entry->protocol_data_length = 0;
entry->protocol_data = strdup("");
entry->network_id = strdup((char*) _sessionid);
entry->auth_name = strdup(_TT_ICEAUTH_AUTH_NAME);
entry->auth_data_length = strlen((char*) _auth_cookie) + 1;
entry->auth_data = strdup((char*) _auth_cookie);
status = modify_auth_entry(entry, &_entries_head);
status = write_auth_file(filename);
if (TT_OK != status) {
_tt_syslog(0, LOG_ERR,
"%s: could not write \"%s\". New entry not written.\n",
funcname, filename);
goto cleanup;
}
cleanup:
(void) umask(original_umask);
_tt_UnlockAuthFile(filename);
return status;
}
Tt_status _Tt_auth::
read_auth_entries(FILE *fp, _tt_AuthFileEntryList **headp)
{
static char *funcname = "_Tt_auth::read_auth_entries()";
_tt_AuthFileEntry *entry;
_tt_AuthFileEntryList *head;
_tt_AuthFileEntryList *el_new;
_tt_AuthFileEntryList *tail;
int n;
entry = NULL;
head = tail = NULL;
n = 0;
while ((entry = _tt_ReadAuthFileEntry(fp)) != NULL) {
el_new = (_tt_AuthFileEntryList*) malloc(sizeof(_tt_AuthFileEntryList));
if (NULL == el_new) {
_tt_syslog(0, LOG_ERR,
"%s: memory error. New entry not written.\n",
funcname);
return TT_ERR_NOMEM;
}
el_new->next = NULL;
el_new->entry = entry;
if (tail) /* if not first time through append */
tail->next = el_new;
else
head = el_new; /* first time through, so assign */
tail = el_new;
n++;
}
*headp = head;
return TT_OK;
}
Tt_status _Tt_auth::
read_auth_file(char *filename)
{
static char *funcname = "Tt_auth::read_auth_file()";
FILE *authfp;
Tt_status status = TT_OK;
if (0 == (authfp = fopen (filename, "rb"))) {
_tt_syslog(0, LOG_ERR,
"%s: unable to read auth entries from file \"%s\"\n",
funcname, filename);
return TT_AUTHFILE_ACCESS;
}
status = read_auth_entries(authfp, &_entries_head);
if (TT_OK != status)
_tt_syslog(0, LOG_ERR,
"%s: unable to read auth entries from file \"%s\"\n",
funcname, filename);
(void) fclose (authfp);
return status;
}
Tt_status _Tt_auth::
modify_auth_entry(_tt_AuthFileEntry *entry, _tt_AuthFileEntryList **headp)
{
static char *funcname = "Tt_auth::modify_auth_entry()";
_tt_AuthFileEntryList *list, *prev, *el_new;
for (prev=NULL, list=*headp; list; list=list->next) {
if ((0 == strcmp(list->entry->protocol_name, entry->protocol_name)) &&
(list->entry->protocol_data_length==entry->protocol_data_length) &&
(0 == strncmp(list->entry->protocol_data, entry->protocol_data,
entry->protocol_data_length)) &&
(0 == strcmp(list->entry->network_id, entry->network_id)) &&
(0 == strcmp(list->entry->auth_name, entry->auth_name)) ) {
_tt_FreeAuthFileEntry(list->entry);
list->entry = entry;
return TT_OK;
}
prev = list;
}
el_new = (_tt_AuthFileEntryList*) malloc(sizeof(_tt_AuthFileEntryList));
if (NULL == el_new) {
_tt_syslog(0, LOG_ERR,
"%s: memory error. New entry not written.\n",
funcname);
return TT_ERR_NOMEM;
}
el_new->next = NULL;
el_new->entry = entry;
if (NULL == prev)
*headp = el_new;
else
prev->next = el_new;
return TT_OK;
}
Tt_status _Tt_auth::
write_auth_file(char *filename)
{
static char *funcname = "Tt_auth::write_auth_file()";
static char *suffix = "-n";
FILE *fp;
_tt_AuthFileEntryList *list;
char *tmpnam;
tmpnam = (char*) malloc(strlen(filename) + strlen(suffix) + 1);
if (NULL == tmpnam) {
_tt_syslog(0, LOG_ERR,
"%s: memory error. New entry not written.\n",
funcname);
return TT_ERR_NOMEM;
}
strcpy(tmpnam, filename);
strcat(tmpnam, "-n"); /* for new */
(void) unlink(tmpnam);
fp = fopen (tmpnam, "wb"); /* umask is still set to 0077 */
if (!fp) {
_tt_syslog(0, LOG_ERR,
"%s: unable to open tmp file \"%s\"\n",
funcname, tmpnam);
return TT_AUTHFILE_ACCESS;
}
for (list=_entries_head; list; list=list->next)
_tt_WriteAuthFileEntry (fp, list->entry);
(void) fclose (fp);
(void) unlink(filename);
if (link (tmpnam, filename) == -1)
_tt_syslog(0, LOG_ERR,
"%s: unable to link authority file %s, use %s\n",
funcname, filename, tmpnam);
else
(void) unlink(tmpnam);
return TT_OK;
}
Tt_status _Tt_auth::
retrieve_auth_cookie()
{
char *buff = NULL;
_tt_AuthFileEntry *entry = NULL;
entry = _tt_GetAuthFileEntry(_TT_ICEAUTH_PROTOCOL_NAME,
(char*) _sessionid,
_TT_ICEAUTH_AUTH_NAME);
if (NULL == entry)
return TT_AUTHFILE_ENTRY_MISSING;
buff = (char*) malloc(entry->auth_data_length + 1);
if (NULL == buff) return TT_ERR_NOMEM;
strncpy(buff, entry->auth_data, entry->auth_data_length);
buff[entry->auth_data_length] = '\0';
_auth_cookie = buff;
free(buff);
_tt_FreeAuthFileEntry(entry);
return TT_OK;
}
Tt_status _Tt_auth::
set_auth_level(_Tt_auth_level auth_level)
{
_auth_level = auth_level;
return TT_OK;
}
Tt_status _Tt_auth::
set_sessionid(
int rpc_program,
_Tt_auth_level auth_level,
_Tt_string hostaddr,
int rpc_version)
{
char strid[BUFSIZ];
const char *format = "%d/%d/%s/%d";
_rpc_program = rpc_program;
_auth_level = auth_level;
_hostaddr = hostaddr;
_rpc_version = rpc_version;
sprintf(strid,
format,
_rpc_program,
(int) _auth_level,
(char*) _hostaddr,
_rpc_version);
_sessionid = strid;
return TT_OK;
}

101
cde/lib/tt/lib/mp/mp_auth.h Normal file
View File

@@ -0,0 +1,101 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_auth.h /main/2 1999/09/10 15:01:41 mgreess $ */
/*
* @(#)mp_auth.h 1.36 95/01/25
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file contains the implementation of the _Tt_auth object which
* implements the MIT-MAGIC-COOKIE authentication for the _TT_AUTH_ICEAUTH
* authentication type. This class is simply a wrapper for calls to
* code copied out of the X11 libICE library. Alternatively, one can
* compile with the OPT_ICE define and call the ICE routines directly.
*/
#ifndef MP_AUTH_H
#define MP_AUTH_H
#include "tt_options.h"
#include "mp/mp_auth_functions.h"
#include "util/tt_object.h"
#include "util/tt_list.h"
#include "util/tt_string.h"
/*
* As of the CDE release of ToolTalk, _TT_AUTH_XAUTH is no longer supported.
* It has been removed along with all references in the TT code, but the
* value of _TT_AUTH_DES was not changed to the now-missing value of 1.
*/
/*
* As of 2.1.30, the libICE MIT-MAGIC-COOKIE authentication is added in
* place of _TT_AUTH_XAUTH. The code was inlined from libICE in such a
* way that it could be easily replaced by libICE itself.
*/
#define _TT_ICEAUTH_AUTH_NAME "MIT-MAGIC-COOKIE-1"
#define _TT_ICEAUTH_MAGIC_COOKIE_LEN 16
#define _TT_ICEAUTH_PROTOCOL_NAME "TT"
#define _TT_ICEAUTH_DEFAULT_RETRIES 10 /* num of competitors we expect */
#define _TT_ICEAUTH_DEFAULT_TIMEOUT 2 /* in seconds, be quick */
#define _TT_ICEAUTH_DEFAULT_DEADTIME 600L /* 10 minutes in seconds */
enum _Tt_auth_level {
_TT_AUTH_UNIX = 0, /* Unix "authentication" */
_TT_AUTH_ICEAUTH= 1, /* ICE MIT-COOKIE authentication (default) */
_TT_AUTH_DES = 2, /* Secure RPC (DES encryption) */
_TT_AUTH_NONE = 3 /* No authentication */
};
class _Tt_auth : public _Tt_object {
public:
_Tt_auth(_Tt_auth_level auth_level = _TT_AUTH_ICEAUTH);
virtual ~_Tt_auth();
_Tt_auth_level auth_level() {
return _auth_level;
}
const _Tt_string &auth_cookie() const {
return _auth_cookie;
}
Tt_status generate_auth_cookie();
Tt_status retrieve_auth_cookie();
Tt_status set_auth_level(_Tt_auth_level auth_level);
Tt_status set_sessionid(
int rpc_program,
_Tt_auth_level auth_level,
_Tt_string hostaddr,
int rpc_version);
protected:
//
// state variables
//
_Tt_auth_level _auth_level;
_Tt_string _auth_cookie;
_Tt_string _hostaddr;
int _rpc_program;
int _rpc_version;
_Tt_string _sessionid;
_Tt_string _ttauthfile;
private:
//
// variables associated with generating a .ttauthority file entry.
//
_tt_AuthFileEntryList *_entries_head;
_tt_AuthFileEntryList *_entries_tail;
Tt_status read_auth_file(char*);
Tt_status write_auth_file(char*);
Tt_status modify_auth_entry(_tt_AuthFileEntry*,
_tt_AuthFileEntryList**);
Tt_status read_auth_entries(FILE*,
_tt_AuthFileEntryList**);
};
#endif /* MP_AUTH_H */

View File

@@ -0,0 +1,535 @@
/* $TOG: mp_auth_functions.C /main/3 1999/10/14 18:43:11 mgreess $ */
/******************************************************************************
Copyright 1993, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Author: Ralph Mor, X Consortium
******************************************************************************/
/*
* This file was copied and altered from libICE/authutil.c
* The 'Ice' prefix has been replaced by tt_ for functions
* and by _tt_ for data types.
*/
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <X11/Xos.h>
#include "mp/mp_auth_functions.h"
#ifdef X_NOT_STDC_ENV
extern int errno;
extern long time ();
extern char *getenv();
#define Time_t long
#else
#include <time.h>
#define Time_t time_t
#endif
#ifndef X_NOT_POSIX
#include <unistd.h>
#else
#ifndef WIN32
extern unsigned sleep ();
#else
#define link rename
#endif
#endif
static int read_short(FILE *, unsigned short *);
static int read_string(FILE *, char **);
static int read_counted_string(FILE *, unsigned short *, char **);
static int write_short(FILE *, unsigned short);
static int write_string(FILE *, char *);
static int write_counted_string(FILE *, unsigned short, char *);
/*
* The following routines are for manipulating the .TTauthority file
*/
char *
_tt_AuthFileName ()
{
static char slashDotTTauthority[] = "/.TTauthority";
char *name;
static char *buf;
static int bsize;
int size;
#ifdef WIN32
#ifndef PATH_MAX
#define PATH_MAX 512
#endif
char dir[PATH_MAX];
#endif
if (name = getenv ("TTAUTHORITY"))
return (name);
name = getenv ("HOME");
if (!name)
{
#ifdef WIN32
register char *ptr1;
register char *ptr2;
int len1 = 0, len2 = 0;
if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
len1 = strlen (ptr1);
len2 = strlen (ptr2);
} else if (ptr2 = getenv("USERNAME")) {
len1 = strlen (ptr1 = "/users/");
len2 = strlen (ptr2);
}
if ((len1 + len2 + 1) < PATH_MAX) {
sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
name = dir;
}
if (!name)
#endif
return (NULL);
}
size = strlen (name) + strlen (&slashDotTTauthority[1]) + 2;
if (size > bsize)
{
if (buf)
free (buf);
buf = (char*) malloc ((unsigned) size);
if (!buf)
return (NULL);
bsize = size;
}
strcpy (buf, name);
strcat (buf, slashDotTTauthority + (name[1] == '\0' ? 1 : 0));
return (buf);
}
int
_tt_LockAuthFile(char *file_name, int retries, int timeout, long dead)
{
char creat_name[1025], link_name[1025];
struct stat statb;
Time_t now;
int creat_fd = -1;
if ((int) strlen (file_name) > 1022)
return (_tt_AuthLockError);
strcpy (creat_name, file_name);
strcat (creat_name, "-c");
strcpy (link_name, file_name);
strcat (link_name, "-l");
if (stat (creat_name, &statb) != -1)
{
now = time ((Time_t *) 0);
/*
* NFS may cause ctime to be before now, special
* case a 0 deadtime to force lock removal
*/
if (dead == 0 || now - statb.st_ctime > dead)
{
unlink (creat_name);
unlink (link_name);
}
}
while (retries > 0)
{
if (creat_fd == -1)
{
creat_fd = creat (creat_name, 0666);
if (creat_fd == -1)
{
if (errno != EACCES)
return (_tt_AuthLockError);
}
else
close (creat_fd);
}
if (creat_fd != -1)
{
if (link (creat_name, link_name) != -1)
return (_tt_AuthLockSuccess);
if (errno == ENOENT)
{
creat_fd = -1; /* force re-creat next time around */
continue;
}
if (errno != EEXIST)
return (_tt_AuthLockError);
}
sleep ((unsigned) timeout);
--retries;
}
return (_tt_AuthLockTimeout);
}
void
_tt_UnlockAuthFile(char *file_name)
{
#ifndef WIN32
char creat_name[1025];
#endif
char link_name[1025];
if ((int) strlen (file_name) > 1022)
return;
#ifndef WIN32
strcpy (creat_name, file_name);
strcat (creat_name, "-c");
#endif
strcpy (link_name, file_name);
strcat (link_name, "-l");
#ifndef WIN32
unlink (creat_name);
#endif
unlink (link_name);
}
_tt_AuthFileEntry *
_tt_ReadAuthFileEntry(FILE *auth_file)
{
_tt_AuthFileEntry local;
_tt_AuthFileEntry *ret;
local.protocol_name = NULL;
local.protocol_data = NULL;
local.network_id = NULL;
local.auth_name = NULL;
local.auth_data = NULL;
if (!read_string (auth_file, &local.protocol_name))
return (NULL);
if (!read_counted_string (auth_file,
&local.protocol_data_length, &local.protocol_data))
goto bad;
if (!read_string (auth_file, &local.network_id))
goto bad;
if (!read_string (auth_file, &local.auth_name))
goto bad;
if (!read_counted_string (auth_file,
&local.auth_data_length, &local.auth_data))
goto bad;
if (!(ret = (_tt_AuthFileEntry *) malloc (sizeof (_tt_AuthFileEntry))))
goto bad;
*ret = local;
return (ret);
bad:
if (local.protocol_name) free (local.protocol_name);
if (local.protocol_data) free (local.protocol_data);
if (local.network_id) free (local.network_id);
if (local.auth_name) free (local.auth_name);
if (local.auth_data) free (local.auth_data);
return (NULL);
}
void
_tt_FreeAuthFileEntry(_tt_AuthFileEntry *auth)
{
if (auth)
{
if (auth->protocol_name) free (auth->protocol_name);
if (auth->protocol_data) free (auth->protocol_data);
if (auth->network_id) free (auth->network_id);
if (auth->auth_name) free (auth->auth_name);
if (auth->auth_data) free (auth->auth_data);
free ((char *) auth);
}
}
int
_tt_WriteAuthFileEntry(FILE *auth_file, _tt_AuthFileEntry *auth)
{
if (!write_string (auth_file, auth->protocol_name))
return (0);
if (!write_counted_string (auth_file,
auth->protocol_data_length, auth->protocol_data))
return (0);
if (!write_string (auth_file, auth->network_id))
return (0);
if (!write_string (auth_file, auth->auth_name))
return (0);
if (!write_counted_string (auth_file,
auth->auth_data_length, auth->auth_data))
return (0);
return (1);
}
_tt_AuthFileEntry *
_tt_GetAuthFileEntry(char *protocol_name, char *network_id, char *auth_name)
{
FILE *auth_file;
char *filename;
_tt_AuthFileEntry *entry;
if (!(filename = _tt_AuthFileName ()))
return (NULL);
if (access (filename, R_OK) != 0) /* checks REAL id */
return (NULL);
if (!(auth_file = fopen (filename, "rb")))
return (NULL);
for (;;)
{
if (!(entry = _tt_ReadAuthFileEntry (auth_file)))
break;
if (strcmp (protocol_name, entry->protocol_name) == 0 &&
strcmp (network_id, entry->network_id) == 0 &&
strcmp (auth_name, entry->auth_name) == 0)
{
break;
}
_tt_FreeAuthFileEntry (entry);
}
fclose (auth_file);
return (entry);
}
/*
* MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
* the SI. It is not part of standard ICElib.
*/
char *
_tt_GenerateMagicCookie(int len)
{
char *auth;
long ldata[2];
int seed;
int value;
int i;
if ((auth = (char *) malloc (len + 1)) == NULL)
return (NULL);
#ifdef ITIMER_REAL
{
struct timeval now;
X_GETTIMEOFDAY (&now);
ldata[0] = now.tv_sec;
ldata[1] = now.tv_usec;
seed = (int) ((ldata[0] << 11) ^ ldata[1]);
}
#else
{
long time ();
ldata[0] = time ((long *) 0);
ldata[1] = getpid ();
seed = (int) (ldata[0]) + (ldata[1] << 16);
}
#endif
srand (seed);
for (i = 0; i < len; i++)
{
value = rand ();
auth[i] = (
( (value & 0xff000000) >> 24) ^
( (value & 0xff0000) >> 16) ^
( (value & 0xff00) >> 8) ^
( (value & 0xff) )
) & 0xff;
}
auth[len] = '\0';
return (auth);
}
/*
* local routines
*/
static int
read_short(FILE *file, unsigned short *shortp)
{
unsigned char file_short[2];
if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
return (0);
*shortp = file_short[0] * 256 + file_short[1];
return (1);
}
static int
read_string(FILE *file, char **stringp)
{
unsigned short len;
char *data;
if (!read_short (file, &len))
return (0);
if (len == 0)
{
data = 0;
}
else
{
data = (char*) malloc ((unsigned) len + 1);
if (!data)
return (0);
if (fread (data, (int) sizeof (char), (int) len, file) != len)
{
free (data);
return (0);
}
data[len] = '\0';
}
*stringp = data;
return (1);
}
static int
read_counted_string(FILE *file, unsigned short *countp, char **stringp)
{
unsigned short len;
char *data;
if (!read_short (file, &len))
return (0);
if (len == 0)
{
data = 0;
}
else
{
data = (char*) malloc ((unsigned) len);
if (!data)
return (0);
if (fread (data, (int) sizeof (char), (int) len, file) != len)
{
free (data);
return (0);
}
}
*stringp = data;
*countp = len;
return (1);
}
static int
write_short(FILE *file, unsigned short s)
{
unsigned char file_short[2];
file_short[0] = (s & (unsigned) 0xff00) >> 8;
file_short[1] = s & 0xff;
if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
return (0);
return (1);
}
static int
write_string(FILE *file, char *string)
{
unsigned short count = strlen (string);
if (!write_short (file, count))
return (0);
if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
return (0);
return (1);
}
static int
write_counted_string(FILE *file, unsigned short count, char *string)
{
if (!write_short (file, count))
return (0);
if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
return (0);
return (1);
}

View File

@@ -0,0 +1,117 @@
/* $TOG: mp_auth_functions.h /main/1 1999/08/30 10:55:06 mgreess $ */
/******************************************************************************
Copyright 1993, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Author: Ralph Mor, X Consortium
******************************************************************************/
/*
* This file was copied and altered from libICE/ICEutil.h
* The 'Ice' prefix has been replaced by tt_ for functions
* and by _tt_ for data types.
*/
#ifndef MP_AUTH_FUNCTIONS_H
#define MP_AUTH_FUNCTIONS_H
#include <stdio.h>
/*
* Data structure for entry in ICE authority file
*/
typedef struct _tt_AuthFileEntry {
char *protocol_name;
unsigned short protocol_data_length;
char *protocol_data;
char *network_id;
char *auth_name;
unsigned short auth_data_length;
char *auth_data;
} _tt_AuthFileEntry;
typedef struct _tt_AuthFileEntryList {
struct _tt_AuthFileEntryList *next;
_tt_AuthFileEntry *entry;
} _tt_AuthFileEntryList;
/*
* Authentication data maintained in memory.
*/
typedef struct {
char *protocol_name;
char *network_id;
char *auth_name;
unsigned short auth_data_length;
char *auth_data;
} _tt_AuthDataEntry;
/*
* Return values from tt_LockAuthFile
*/
#define _tt_AuthLockSuccess 0 /* lock succeeded */
#define _tt_AuthLockError 1 /* lock unexpectely failed, check errno */
#define _tt_AuthLockTimeout 2 /* lock failed, timeouts expired */
/*
* Function Prototypes
*/
extern char *_tt_AuthFileName (void);
extern int _tt_LockAuthFile (
char * /* file_name */,
int /* retries */,
int /* timeout */,
long /* dead */
);
extern void _tt_UnlockAuthFile (
char * /* file_name */
);
extern _tt_AuthFileEntry *_tt_ReadAuthFileEntry (
FILE * /* auth_file */
);
extern void _tt_FreeAuthFileEntry (
_tt_AuthFileEntry * /* auth */
);
extern int _tt_WriteAuthFileEntry (
FILE * /* auth_file */,
_tt_AuthFileEntry * /* auth */
);
extern _tt_AuthFileEntry *_tt_GetAuthFileEntry (
char * /* protocol_name */,
char * /* network_id */,
char * /* auth_name */
);
extern char *_tt_GenerateMagicCookie (
int /* len */
);
#endif /* MP_AUTH_FUNCTIONS_H */

23
cde/lib/tt/lib/mp/mp_c.h Normal file
View File

@@ -0,0 +1,23 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c.h /main/3 1995/10/23 10:19:25 rswiston $ */
/*
* mp_c.h -- public interface classes to the client side of the Message Passer
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef _MP_C_H
#define _MP_C_H
#include <mp/mp_c_global.h>
#include <mp/mp_arg.h>
#include <mp/mp_c_file.h>
#include <mp/mp_c_message.h>
#include <mp/mp_c_procid.h>
#include <mp/mp_c_session.h>
#include <mp/mp_c_mp.h>
#include <mp/mp_pattern.h>
#endif /* _MP_C_H */

View File

@@ -0,0 +1,208 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_file.C /main/3 1995/10/23 10:19:32 rswiston $
/*
* Tool Talk Message Passer (MP) - mp_c_file.cc
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_file class representing a document.
*/
#include <stdio.h>
#include <unistd.h>
#include "mp/mp_c_file.h"
#include "mp/mp_c_mp.h"
#include "mp/mp_c_global.h"
#include "mp/mp_rpc_interface.h"
#include "mp/mp_c_session.h"
#include "mp/mp_c_procid.h"
#include "mp/mp_c_message.h"
#include "api/c/api_error.h"
#include "util/tt_port.h"
//
// Use parent class (_Tt_file) for construction and destruction.
//
_Tt_c_file::_Tt_c_file()
{
}
_Tt_c_file::_Tt_c_file(
_Tt_string path
) :
_Tt_file( path )
{
}
_Tt_c_file::~_Tt_c_file()
{
}
//
// Joins the indicated file on behalf of the default procid. Joining a file
// means that any file-scoped patterns for this procid are updated to
// contain this file. It also means we have to indicated to procids in
// other sessions that this procid is interested in messages addressed to
// this file. This is done by storing the session for this procid in a
// persistent property on this file. The details of that are in
// _Tt_file::add_joined_file. Another responsibility of this method is to
// process any queued messages that are destined for any ptype declared
// by p. This client/server division in the way file-scope queued
// messages are implemented reflects a goal of offloading any
// computation from the server to its clients. This is specially true
// of any computation that involves communicating with the database
// servers.
//
// XXX: it's misleading to have a _Tt_procid_ptr input arg here when
// in fact the default procid joins the file, not the specified
// procid. Either figure out how to join the specified procid or
// remove the parameter.
//
Tt_status
_Tt_c_file::c_join(
_Tt_procid_ptr &
)
{
Tt_status status;
Tt_status rs;
_Tt_db_results dbStatus;
_Tt_file_join_args args;
_Tt_session_ptr d_session;
_Tt_c_procid *sp;
sp = (_Tt_c_procid *)_tt_c_mp->default_procid().c_pointer();
args.procid = _tt_c_mp->default_procid();
args.path = getNetworkPath();
d_session = sp->default_session();
rs = d_session->call(TT_RPC_JOIN_FILE,
(xdrproc_t)tt_xdr_file_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (status == TT_WRN_NOTFOUND) {
// No file patterns updated on the server side.
status = TT_OK;
} else {
sp->add_joined_file(getNetworkPath());
// add our session to the list of sessions
// interested in this file.
if (status == TT_WRN_STALE_OBJID) {
dbStatus = addSession(d_session->process_tree_id());
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::addSession(): %d",
dbStatus );
}
}
if (status != TT_OK) {
return status;
}
// process any queued messages on this file
// for any of the ptypes we've declared.
process_message_queue();
}
return((rs == TT_OK) ? status : rs);
}
//
// Removes the session for the given procid from the list of interested
// sessions in this file. This method also invokes an rpc on the server
// session to remove this file from the patterns registered by this
// procid. The rpc call to the session will return a special status code
// TT_WRN_STALE_OBJID if this method is to actually remove the session
// from the file property of interested sessions. This is because the
// server session keeps a counter of how many procids are interested in
// each file.
//
Tt_status
_Tt_c_file::c_quit(
_Tt_procid_ptr &p
)
{
_Tt_file_join_args args;
Tt_status rs;
Tt_status status;
_Tt_session_ptr d_session;
if (p.is_null()) {
return(TT_ERR_PROCID);
}
d_session = ((_Tt_c_procid *)p.c_pointer())->default_session();
if (d_session.is_null()) {
return(TT_ERR_SESSION);
}
args.procid = p;
args.path = getNetworkPath();
rs = d_session->call(TT_RPC_QUIT_FILE,
(xdrproc_t)tt_xdr_file_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (status == TT_WRN_NOTFOUND) {
status = TT_OK;
} else if (status == TT_WRN_STALE_OBJID) {
_Tt_db_results dbStatus;
dbStatus = deleteSession( d_session->process_tree_id() );
if (dbStatus == TT_DB_ERR_NO_SUCH_PROPERTY) {
status = TT_OK;
} else {
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
}
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::deleteSession(): %d",
dbStatus );
status = TT_ERR_INTERNAL;
}
}
p->del_joined_file(getNetworkPath());
return((status == TT_OK) ? rs : status);
}
//
// Proces any queued messages in this file. If so, then for each
// message destined for a ptype declared by the current default
// procid, retrieve the message and dispatch it to our current
// session. Note that messages are stored only once even if they're
// destined for multiple ptypes so we only de-queue the message if
// there are no destination ptypes once we're done dispatching the
// message.
//
// The exact layout of how messages are stored is described in
// _Tt_file::q_message below.
//
Tt_status
_Tt_c_file::process_message_queue(
int dispatch_msgs
)
{
_Tt_message_list_ptr msgs;
Tt_status status;
_Tt_db_results dbStatus;
dbStatus = dequeueMessages( _tt_c_mp->default_procid()->ptypes(),
msgs );
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status != TT_OK) {
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::dequeueMessages(): %d",
dbStatus );
}
return status;
}
if (! dispatch_msgs) {
return TT_OK;
}
_Tt_message_list_cursor msg( msgs );
while (msg.next()) {
msg->set_state( TT_QUEUED );
(void)((_Tt_c_message *)(*msg).c_pointer())->dispatch( 1 );
}
return TT_OK;
}

View File

@@ -0,0 +1,38 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_file.h /main/3 1995/10/23 10:19:40 rswiston $ */
/*
* Tool Talk Message Passer (MP) - mp_c_file.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of the _Tt_c_file class.
*/
#ifndef _MP_C_FILE_H
#define _MP_C_FILE_H
#include <mp/mp_file.h>
#include <mp/mp_c_file_utils.h>
class _Tt_c_file : public _Tt_file {
public:
_Tt_c_file();
_Tt_c_file(
_Tt_string path
);
virtual ~_Tt_c_file();
Tt_status c_join(
_Tt_procid_ptr &p
);
Tt_status c_quit(
_Tt_procid_ptr &p
);
Tt_status process_message_queue(
int dispatch = 1
);
};
#endif /* _MP_C_FILE_H */

View File

@@ -0,0 +1,14 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_file_utils.C /main/3 1995/10/23 10:19:48 rswiston $
/*
*
* mp_c_file_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_c_file.h>
implement_ptr_to(_Tt_c_file)

View File

@@ -0,0 +1,20 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_file_utils.h /main/3 1995/10/23 10:19:55 rswiston $ */
/*
*
* mp_c_file_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_c_file
*/
#ifndef MP_C_FILE_UTILS_H
#define MP_C_FILE_UTILS_H
#include <mp/mp_file_utils.h>
class _Tt_c_file;
declare_derived_ptr_to(_Tt_c_file,_Tt_file)
#endif /* MP_C_FILE_UTILS_H */

View File

@@ -0,0 +1,24 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_global.h /main/3 1995/10/23 10:20:03 rswiston $ */
/*
*
* mp_c_global.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
*
* _tt_c_mp and _tt_mp always point to the same object, but client-only
* functions can use _tt_c_mp in order to access client-only functions.
*/
#if !defined(_MP_C_GLOBAL_H)
#define _MP_C_GLOBAL_H
class _Tt_c_mp;
extern _Tt_c_mp *_tt_c_mp;
#include "mp/mp_global.h"
#endif

View File

@@ -0,0 +1,615 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_c_message.C /main/5 1999/10/14 18:40:53 mgreess $
/*
* @(#)mp_c_message.C 1.46 95/04/27
*
* @(#)mp_c_message.C 1.36 93/09/07
*
* Tool Talk Message Passer (MP) - mp_c_message.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include "api/c/api_spec_map_ref.h"
#include "api/c/api_error.h"
#include "mp/mp_c_global.h"
#include "mp/mp_arg.h"
#include "mp/mp_c_file.h"
#include "mp/mp_c_message.h"
#include "mp/mp_c_mp.h"
#include "mp/mp_c_procid.h"
#include "mp/mp_rpc_interface.h"
#include "mp/mp_c_session.h"
#include "util/tt_enumname.h"
#include "mp/mp_trace.h"
#include "util/tt_gettext.h"
#include "util/tt_port.h"
//
// The methods in this file implement the client-only functionality
// required for messages.
//
_Tt_c_message::
_Tt_c_message()
{
}
_Tt_c_message::
~_Tt_c_message()
{
}
//
// Will return 1 if this message has the update xdr flag turned on
// indicating it is a reply to an old message rather than an entirely new
// message.
//
int _Tt_c_message::
is_a_diff()
{
return(_flags&(1<<_TT_MSG_UPDATE_XDR_MODE));
}
//
// Dispatches a message. If observers_only is 1 then the only observer
// patterns will be matched for this message. One of the important
// responsibilities of this method is to fill in any fields in the
// message that require database lookups. For example, if it is an
// object-oriented message then this method will fill in the otype field
// in the message by asking the right database for the type field of the
// given object field. This is done to free ttsession from ever having to
// do any database lookups. For file-scope messages, this method will
// also append the list of remote sessions that have procids joined to
// the file mentioned in this message. This is used by ttsession when
// routing the message.
//
// A somewhat tricky case of freeing ttsession from invoking database
// operations arises in message-queueing. When a file-scope message
// requires queueing the return argument from the rpc call to dispatch
// the message will indicate what ptypes the message should be queued
// for. It is then this method which then goes ahead and queues the
// message on the file.
Tt_status _Tt_c_message::
dispatch(int observers_only)
{
Tt_status status;
_Tt_db_results dbStatus;
Tt_status resolve_status = TT_OK;
Tt_status rpc_status;
_Tt_message_ptr mptr;
_Tt_file_ptr fptr;
// The following two pointers are not smart ptrs, to save
// two trips into constructor and destructor per message send.
// This doesn\'t mess up ref counting since the default procid
// and session never change while in this method.
_Tt_c_session *d_session;
_Tt_c_procid *d_procid;
_Tt_dispatch_reply_args args;
if (_message_class == TT_CLASS_UNDEFINED ||
_message_class == TT_CLASS_LAST) {
return(TT_ERR_CLASS);
}
if (_state != TT_CREATED && _state != TT_QUEUED) {
// we shouldn't be re-sending a message whose state
// isn't created or queued
return(TT_ERR_STATE);
}
d_procid = _tt_c_mp->default_c_procid().c_pointer();
d_session = d_procid->default_session().c_pointer();
// take any necessary actions according to the message
// paradigm (as well as check for legitimate paradigm
// fields).
switch (_paradigm) {
case TT_HANDLER:
if (handler().is_null()) {
// Point-to-point messages must have a handler.
return TT_ERR_PROCID;
}
// fall through to check scope
case TT_PROCEDURE:
if (_scope == TT_SCOPE_NONE) {
return(TT_ERR_SCOPE);
}
break;
case TT_OBJECT:
if (_object.is_null()) {
return TT_ERR_OBJID;
}
resolve_status = resolve();
switch (resolve_status) {
case TT_OK:
case TT_WRN_STALE_OBJID:
break;
default:
return(resolve_status);
}
break;
case TT_OTYPE:
if (_otype.is_null()) {
return TT_ERR_OTYPE;
}
break;
case TT_ADDRESS_LAST:
default:
return(TT_ERR_ADDRESS);
}
if ((_message_class == TT_OFFER) && (_paradigm != TT_PROCEDURE)) {
return TT_ERR_ADDRESS;
}
//
// Since we know the server's RPC version, we only try the
// call if we know it will work, else we generate our own
// TT_ERR_UNIMP. Prior to 1.2, we let RPC_PROCUNAVAIL become
// TT_ERR_UNIMP. Now we use classic RPC versioning.
//
if ( (message_class() == TT_OFFER)
&& (d_session->rpc_version() < TT_OFFER_RPC_VERSION))
{
return TT_ERR_UNIMP;
}
if (_file.len() &&
(_scope == TT_FILE || _scope == TT_BOTH ||
_paradigm==TT_OTYPE || _paradigm == TT_OBJECT)) {
// If the message is file-scoped then we append the
// list of remote sessions to send the message to.
// XXX: For object-oriented msgs we don't know the
// scope yet so we append the sessions anyway if the
// file attribute is filled in. Probably need to
// refine the protocol so that we first ask if the
// message is file-scoped (pure dispatch) and then we
// deliver accordingly. This is mostly just
// performance-tuning.
if (_tt_mp->find_file(_file, fptr, 1) == TT_OK) {
_rsessions = fptr->getSessions();
dbStatus = fptr->getDBResults();
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_WARNING,
"_Tt_db_file::getSessions(): %d",
dbStatus );
}
if (status != TT_OK) {
_rsessions = (_Tt_string_list *)0;
return status;
}
// we set the msg guard bit for the _rsessions
// field to 1 if it is non-empty.
SET_GUARD(_full_msg_guards,
(!_rsessions.is_null()),
_TT_MSK_RSESSIONS);
} else {
return(TT_ERR_FILE);
}
}
if (! _rsessions.is_null() && _rsessions->count()) {
// now we dispatch file scope notifications to remote
// sessions, this is done here to minimize the amount
// of inter-server communication done.
// If the message is handler-addressed, don\'t bother
// doing this as pattern matching doesn\'t work on point-
// to-point messages anyway, and sending it to the foreign
// ttsession just seems to confuse it.
if (_paradigm!=TT_HANDLER &&
(_scope == TT_FILE || _scope == TT_BOTH)) {
_tt_mp->check_if_sessions_alive();
_flags |= (1<<_TT_MSG_OBSERVERS_ONLY);
(void)dispatch_file_scope_notification(fptr);
}
}
// send the message to the default session
if (!observers_only) {
_flags &= ~(1<<_TT_MSG_OBSERVERS_ONLY);
}
mptr = this;
args.status = TT_OK;
args.qmsg_info = (_Tt_qmsg_info *)0;
switch (d_session->rpc_version()) {
case 1:
// version 1 (tooltalk version 1.0) dispatch routine
// expects to return arguments
rpc_status = d_session->call(_rpc_dispatch(),
(xdrproc_t)tt_xdr_message,
(char *)&mptr,
(xdrproc_t)tt_xdr_dispatch_reply_args,
(char *)&args);
break;
case 2:
default:
// Only send _session field if scope is TT_FILE or TT_BOTH
SET_GUARD(_full_msg_guards,
(_scope==TT_FILE || _scope==TT_BOTH),
_TT_MSK_SESSION);
// version 2 (tooltalk version 1.0.1) uses a one-way
// rpc if the scope of the message doesn't imply
// file-scope or if the message is already in queued
// state.
rpc_status = d_session->call(((_scope == TT_SESSION ||
_scope == TT_FILE_IN_SESSION ||
_state == TT_QUEUED) ?
_rpc_dispatch_2() :
_rpc_dispatch()),
(xdrproc_t)tt_xdr_message,
(char *)&mptr,
(xdrproc_t)tt_xdr_dispatch_reply_args,
(char *)&args);
break;
}
//
// _Tt_s_message::dispatch() has set the state to TT_SENT
//
Tt_state old_state = state();
set_state( TT_SENT );
switch (_message_class) {
case TT_REQUEST:
case TT_OFFER:
set_awaiting_reply();
}
_Tt_msg_trace trace( *this, old_state );
if (args.status == TT_ERR_FILE) {
//
// TT_ERR_FILE is used to indicate that the session
// doesn't contain any processes joined to the file
// contained in the message. But in this case, we
// do not want to try to delete the default session
// from the interest list, because we do not even know
// if it is *on* the interest list.
//
args.status = TT_OK;
}
// queue the message if necessary. XXX what to do if queueing fails?
if (!(args.qmsg_info).is_null()) {
if (_tt_mp->find_file(_file, fptr, 1) == TT_OK) {
dbStatus = fptr->queueMessage(args.qmsg_info->ptypes,
mptr);
if (dbStatus != TT_DB_OK) {
_tt_syslog( 0, LOG_WARNING,
catgets( _ttcatd, 1, 18,
"could not queue a message"
" on file \"%s\" because "
"of internal error %d" ),
(char *)fptr->getLocalPath(),
dbStatus );
}
}
}
if (rpc_status != TT_OK) {
return rpc_status;
}
if (args.status != TT_OK) {
return args.status;
}
return resolve_status;
}
// Sends a message to the server for dispatching if this process exits
// without calling tt_close.
Tt_status _Tt_c_message::
dispatch_on_exit()
{
Tt_status rpc_status;
_Tt_message_ptr mptr;
_Tt_c_session_ptr d_session;
_Tt_c_procid_ptr d_procid;
_Tt_dispatch_reply_args args;
d_procid = _tt_c_mp->default_c_procid();
d_session = d_procid->default_session();
// take any necessary actions according to the message
// paradigm (as well as check for legitimate paradigm
// fields).
switch (_paradigm) {
case TT_PROCEDURE:
case TT_HANDLER:
if (_scope != TT_SESSION) {
return(TT_ERR_SCOPE);
}
break;
case TT_OBJECT:
case TT_OTYPE:
case TT_ADDRESS_LAST:
default:
return(TT_ERR_ADDRESS);
}
mptr = this;
args.status = TT_OK;
args.qmsg_info = (_Tt_qmsg_info *)0;
rpc_status = d_session->call(TT_RPC_DISPATCH_ON_EXIT,
(xdrproc_t)tt_xdr_message,
(char *)&mptr,
(xdrproc_t)tt_xdr_dispatch_reply_args,
(char *)&args);
if (rpc_status != TT_OK) {
return rpc_status;
} else if (args.status != TT_OK) {
return args.status;
}
//
// _Tt_s_message::dispatch() will set the state to TT_SENT
// if we die. This is our only chance to trace it.
//
Tt_state old_state = state();
set_state( TT_SENT );
// Do not set_awaiting_reply().
_Tt_msg_trace trace( *this, old_state );
return TT_OK;
}
//
// Set up special flags to optimize xdr'ing the message when it the
// current client replies to it. See _Tt_message::xdr for a
// description of the message xdr'ing scheme.
//
void _Tt_c_message::
set_return_handler_flags()
{
const int req_fields = _TT_MSK_ID |
_TT_MSK_MESSAGE_CLASS |
_TT_MSK_SENDER |
_TT_MSK_STATUS |
_TT_MSK_FLAGS;
// turning on this flag means that when xdr'ed the _out_args
// arglist (which holds only TT_OUT/TT_INOUT args) is sent
// rather than the normal _args arglist. (see _Tt_message::xdr)
_flags |= (1<<_TT_MSG_UPDATE_XDR_MODE);
// turn on the required fields
_ptr_guards = req_fields;
if (is_start_message()) {
// if this message was a start message then we need to
// send the handler_ptype field because the
// _Tt_s_procid::update_message method needs to make
// use of the field before it has matched up this
// message with its server-side copy.
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_HANDLER_PTYPE,
_TT_MSK_HANDLER_PTYPE);
}
// set up _out_arg list by adding any arguments that are
// TT_OUT or TT_INOUT.
SET_GUARD(_full_msg_guards, 0, _TT_MSK_ARGS);
if (_out_args.is_null() && !_args.is_null() && _args->count()) {
_Tt_arg_list_cursor argc(_args);
_out_args = new _Tt_arg_list();
while (argc.next()) {
add_out_arg(*argc);
}
}
// An optimization assumes that we normally sent SESSION
// scoped messages, so we don't update the guards for
// the message scope. If this message isn't SESSION
// scoped, we set the guard anyhow.
if (_scope != TT_SESSION) {
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_SCOPE, _TT_MSK_SCOPE);
}
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_HANDLER, _TT_MSK_HANDLER);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_STATUS_STRING,
_TT_MSK_STATUS_STRING);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_FILE, _TT_MSK_FILE);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OBJECT, _TT_MSK_OBJECT);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_ARGS, _TT_MSK_ARGS);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_CONTEXTS, _TT_MSK_CONTEXTS);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OFFEREES, _TT_MSK_OFFEREES);
SET_PTR_GUARD(_full_msg_guards&_TT_MSK_OPNUM, _TT_MSK_OPNUM);
}
//
// Looks up the otype of the object field of the message. If the lookup
// fails then an error code is returned. If the otype of the message is
// already filled in then the resolve succeeds (issue: should it check to
// make sure the otype is valid for this object id?)
//
Tt_status _Tt_c_message::
resolve()
{
if (_otype.len() == 0) {
_Tt_api_spec_map_ref spec_map;
_Tt_objid_spec_ptr spec;
_Tt_string fresh_objid;
Tt_status val2return = TT_OK;
// look up oid in object database;
if (_object.len() == 0) {
return(TT_ERR_OBJID);
}
spec = spec_map.getSpec(_object);
if (spec.is_null()) {
return(TT_ERR_OBJID);
}
switch (spec->getDBResults()) {
case TT_DB_OK:
val2return = TT_OK;
break;
case TT_DB_WRN_FORWARD_POINTER:
fresh_objid = spec->getObjectID();
set_object(fresh_objid);
val2return = TT_WRN_STALE_OBJID;
break;
default:
return(TT_ERR_OBJID);
}
// fill in otype and file field for oid;
_otype = spec->getType();
if (spec->getDBResults() != TT_DB_OK) {
return(TT_ERR_OBJID);
}
SET_GUARD(_full_msg_guards, _otype.len(), _TT_MSK_OTYPE);
// fill in file field in message
// --> what if get_path fails?
_file = spec->getFile();
if (spec->getDBResults() != TT_DB_OK) {
_file = (char *)0;
}
SET_GUARD(_full_msg_guards, _file.len(), _TT_MSK_FILE);
return(val2return);
}
return(TT_OK);
}
//
// This function dispatches in observer-only mode this message to all the
// remote file-scope sessions interested in the file in this message. The
// reason this is done here is to minimize inter-ttsession communication.
// A side-benefit is that if message sending to a remote session fails
// here, the remote session is removed from the _rsessions list and
// ttsession won't try to contact the failed remote session. This method
// also handles removing stale sessions from the file object (where a
// stale session is one that is still listed in the file object's session
// list because the client that was joined to the file in that session
// didn't exit cleanly).
//
// XXX: what is the status that should be returned from this function?
// Ideally one would want to know if every remote session got the
// message or all of them failed? What about partial failures?
Tt_status _Tt_c_message::
dispatch_file_scope_notification(_Tt_file_ptr &fp)
{
_Tt_string sid;
_Tt_string_list_cursor rc(_rsessions);
_Tt_session_ptr rs;
_Tt_message_ptr mptr = this;
_Tt_dispatch_reply_args args;
_Tt_db_results dbStatus;
while (rc.next()) {
sid = *rc;
if (_session->has_id(sid)) {
rc.remove();
continue;
}
if (TT_OK != _tt_c_mp->find_session(sid, rs, 1)) {
//
// stale session id on the file
//
dbStatus = fp->deleteSession(sid);
rc.remove();
if ( (dbStatus != TT_DB_OK)
&& (dbStatus != TT_DB_ERR_NO_SUCH_PROPERTY))
{
_tt_syslog( 0, LOG_WARNING,
catgets( _ttcatd, 1, 19,
"could not delete stale "
"session <%s> from "
"interest list of file "
"\"%s\" because of "
"internal error %d" ),
(char *)sid,
(char *)fp->getLocalPath(),
dbStatus );
}
continue;
}
// XXX: optimization: maybe we should have two
// DISPATCH rpc calls, one that replies with just a
// status and the other that replies with a
// _Tt_dispatch_reply_args (which is only needed once
// to know if the message needs to be queued).
if (rs->call(_rpc_dispatch(),
(xdrproc_t)tt_xdr_message, (char *)&mptr,
(xdrproc_t)tt_xdr_dispatch_reply_args,
(char *)&args)
!= TT_OK)
{
// remove this session from message list to
// minimize the chances of the server doing
// bad rpc calls when looking for handlers.
continue;
}
if (args.status == TT_ERR_FILE) {
// indication from remote session that it
// shouldn't be listed in this file's scope
dbStatus = fp->deleteSession(sid);
rc.remove();
//
// If the client that registered the file-scoped
// pattern quits the file after the sender
// does a getSessions call, then the session may
// show up as stale, but will not be in the
// database any more. This is why
// TT_DB_ERR_NO_SUCH_PROPERPTY is an OK
// return code.
//
if ( (dbStatus != TT_DB_OK)
&& (dbStatus != TT_DB_ERR_NO_SUCH_PROPERTY))
{
_tt_syslog( 0, LOG_WARNING,
catgets( _ttcatd, 1, 20,
"could not delete "
"uninterested session "
"<%s> from interest list "
"of file \"%s\" because "
"of internal error %d" ),
(char *)sid,
(char *)fp->getLocalPath(),
dbStatus );
}
}
}
return(TT_OK);
}
_Tt_rpc_procedure_number _Tt_c_message::
_rpc_dispatch() const
{
if (_contexts.is_null()) {
return TT_RPC_DISPATCH;
}
if (_contexts->count() <= 0) {
return TT_RPC_DISPATCH;
}
return TT_RPC_DISPATCH_WITH_CONTEXT;
}
_Tt_rpc_procedure_number _Tt_c_message::
_rpc_dispatch_2() const
{
if (_contexts.is_null()) {
return TT_RPC_DISPATCH_2;
}
if (_contexts->count() <= 0) {
return TT_RPC_DISPATCH_2;
}
return TT_RPC_DISPATCH_2_WITH_CONTEXT;
}

View File

@@ -0,0 +1,37 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_message.h /main/3 1995/10/23 10:20:18 rswiston $ */
/*
* mp_c_message.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file implements the client side of the _Tt_message object.
*/
#ifndef _MP_C_MESSAGE_H
#define _MP_C_MESSAGE_H
#include <mp/mp_message.h>
#include <mp/mp_rpc_interface.h>
#include <mp/mp_c_message_utils.h>
class _Tt_c_message : public _Tt_message {
public:
_Tt_c_message();
~_Tt_c_message();
void set_return_handler_flags();
Tt_status dispatch(int observers_only = 0);
Tt_status dispatch_on_exit();
int is_a_diff();
private:
Tt_status dispatch_file_scope_notification(_Tt_file_ptr &f);
Tt_status resolve();
_Tt_rpc_procedure_number
_rpc_dispatch() const;
_Tt_rpc_procedure_number
_rpc_dispatch_2() const;
// See _Tt_c_procid::next_message() before adding data members!
};
#endif /* _MP_C_MESSAGE_H */

View File

@@ -0,0 +1,14 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_message_utils.C /main/3 1995/10/23 10:20:25 rswiston $
/*
*
* mp_c_message_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_c_message.h>
implement_ptr_to(_Tt_c_message)

View File

@@ -0,0 +1,20 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_message_utils.h /main/3 1995/10/23 10:20:32 rswiston $ */
/*
*
* mp_c_message_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_s_message
*/
#ifndef MP_C_MESSAGE_UTILS_H
#define MP_C_MESSAGE_UTILS_H
#include <mp/mp_message_utils.h>
class _Tt_c_message;
declare_derived_ptr_to(_Tt_c_message,_Tt_message)
#endif /* MP_C_MESSAGE_UTILS_H */

420
cde/lib/tt/lib/mp/mp_c_mp.C Normal file
View File

@@ -0,0 +1,420 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_c_mp.C /main/6 1999/10/14 18:41:09 mgreess $
/*
*
* mp_c_mp.cc
*
* Implementations of client-only members of _Tt_mp object.
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include "mp/mp_c_global.h"
#include "mp/mp_c_mp.h"
#include "mp/mp_c_session.h"
#include "mp/mp_c_procid.h"
#include "mp/mp_rpc_interface.h"
#include "util/tt_global_env.h"
#include "util/tt_port.h"
#include "util/tt_threadspecific.h"
_Tt_c_mp *_tt_c_mp = (_Tt_c_mp *)0;
_Tt_c_mp::
_Tt_c_mp() : _Tt_mp()
{
_flags &= ~(1<<_TT_MP_IN_SERVER);
initial_session = initial_c_session =
default_c_session = new _Tt_c_session;
}
_Tt_c_mp::
~_Tt_c_mp()
{
}
//
// Initializes the _Tt_c_mp object. This initializes all the caches
// maintained by this object as well as the "initial" session which is
// the "default" session for a ToolTalk client.
//
// Returns:
// TT_OK
// TT_ERR_NOMP - the initial session could not be initialised.
Tt_status _Tt_c_mp::
c_init()
{
Tt_status status;
if (_flags&(1<<_TT_MP_INIT_DONE)) {
return(TT_OK);
}
_file_cache = new _Tt_file_table( _Tt_file::networkPath_ );
// initialize "initial" session which is the server session in
// server mode and the "default" session in client mode.
status = initial_c_session->c_init();
if (status == TT_ERR_NOMP) {
if (default_c_session.is_eq(initial_c_session)) {
default_c_session = 0;
}
#ifdef OPT_XTHREADS
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(default_c_session,
_default_c_procid);
xthread_set_specific(_tt_global->threadkey, tss);
}
_Tt_c_session_ptr cs = tss->thread_c_session();
_Tt_c_session_ptr nullsess = (_Tt_c_session *) 0;
if (!cs.is_null() && cs.is_eq(initial_c_session)) {
tss->set_thread_c_session(nullsess);
}
#endif
initial_session = initial_c_session = 0;
}
if (status == TT_OK && !in_server()) {
// enter session object in session table
_session_cache->insert(initial_session);
}
_flags |= (1<<_TT_MP_INIT_DONE);
return(status);
}
_Tt_procid_ptr & _Tt_c_mp::
default_procid()
{
// XXX: (futures) For clients using multi-threading, this
// function should index the default procid off the current
// thread id so that there are no conflicts with other
// threads.
return(default_c_procid());
}
_Tt_c_procid_ptr & _Tt_c_mp::
default_c_procid()
{
#ifdef OPT_XTHREADS
// Return a thread-specific procid if one is set and libthread
// has actually been linked in
if (_tt_global->multithreaded()) {
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(default_c_session,
_default_c_procid);
xthread_set_specific(_tt_global->threadkey, tss);
}
if (tss->thread_c_procid().is_null()) {
tss->set_thread_c_procid(_default_c_procid);
}
return tss->thread_c_procid();
}
#endif
return(_default_c_procid);
}
Tt_status _Tt_c_mp::
set_default_procid(
_Tt_string id,
int
#ifdef OPT_XTHREADS
thread_only
#endif
)
{
_Tt_procid_ptr p;
if (id.len() == 0) {
return(TT_ERR_PROCID);
}
p = active_procs->lookup(id);
if (p.is_null()) {
return(TT_ERR_PROCID);
}
_Tt_c_procid_ptr pp = (_Tt_c_procid *) p.c_pointer();
#ifdef OPT_XTHREADS
if (thread_only) {
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(default_c_session, pp);
xthread_set_specific(_tt_global->threadkey, tss);
} else {
tss->set_thread_c_procid(pp);
}
}
else // fall through to set _default_c_procid
#endif
_default_c_procid = pp;
return(TT_OK);
}
//
// A client-only method that removes a procid from the active procid
// cache and also deallocates any resources/network connections held by
// the procid. If this is the last active procid to be removed then the
// default session is also shut down. This method operates in this
// fashion in order for it to be suitable for the semantics of the
// "tt_close" api call which overloads the call to mean "close the last
// procid" and "deallocate tooltalk resources (if no more procids left)".
//
Tt_status _Tt_c_mp::
c_remove_procid(_Tt_procid_ptr &proc)
{
_Tt_session_ptr d_session;
Tt_status rstatus;
Tt_status status = TT_OK;
_Tt_procid_table_cursor procs;
int remove_session;
_Tt_c_procid *cp;
if (proc.is_null()) {
return(TT_ERR_INVALID);
}
cp = (_Tt_c_procid *)proc.c_pointer();
cp->close();
// remove from list of active procs
active_procs->remove(proc->id());
d_session = cp->default_session();
if (d_session.is_null()) {
return(TT_ERR_SESSION);
}
rstatus = d_session->call(TT_RPC_CLOSE_PROCID,
(xdrproc_t)tt_xdr_procid,
(char *)&proc,
(xdrproc_t)xdr_int,
(char *)&status);
if (!d_session.is_eq(initial_session)) {
// check to see if this is the last procid to
// reference this session (this could be done quicker
// by just checking the _refcount_ on the session but
// then we'd have to be careful not to have any other
// references to this session or else we'd fail to
// remove it from the session cache)
procs.reset(active_procs);
remove_session = 1;
while (procs.next()) {
cp = (_Tt_c_procid *)(*procs).c_pointer();
if (cp->default_session()->address_string() ==
d_session->address_string()) {
remove_session = 0;
break;
}
}
// unlink d_session and remove from session cache if
// this is the last procid to be using it.
if (remove_session) {
_session_cache->remove(d_session->address_string());
}
}
// this should cause the session to be disconnected if
// remove_session is set since the last remaining
// pointer to the session should be _default_session.
// unless it's the initial session in which case it
// should stay around.
_Tt_string nullprocid = (char*)0;
cp->set_default_session(nullprocid);
// Zero out the default procid if it matches the passed-in -- i.e.
// thread-specific -- procid.
if (proc.is_eq(_default_c_procid)) {
_default_c_procid = (_Tt_c_procid *)0;
}
#ifdef OPT_XTHREADS
// Free the storage for the thread-specific procid
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (tss) {
tss->free_procid();
}
#endif
if (rstatus != TT_OK) {
status = rstatus;
}
return(status);
}
//
// Creates a new procid. If this is the first procid to be created then
// we need to check for the start token being set which indicates this
// procid was activated in response to a tooltalk start message. If this
// is the case then this procid is "commited" to the default session.
//
Tt_status _Tt_c_mp::
create_new_procid()
{
Tt_status status;
const char *start_token;
int commit = 0;
_Tt_string session;
_Tt_c_procid *cp = new _Tt_c_procid();
_Tt_c_procid_ptr cpp = cp;
// initialize default procid
_default_c_procid = cp;
#ifdef OPT_XTHREADS
if (_tt_global->multithreaded()){
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(default_c_session, cpp);
xthread_set_specific(_tt_global->threadkey, tss);
} else {
tss->set_thread_c_procid(cpp);
}
}
#endif
//
// Check if there is a START_MESSAGE for us.
//
start_token = _tt_get_first_set_env_var(2, TT_CDE_START_TOKEN, TT_START_TOKEN);
session = _tt_get_first_set_env_var(2, TT_CDE_XATOM_NAME, TT_XATOM_NAME);
if ((start_token != 0 && *start_token != 0 )
&& default_c_session->has_id(session)) {
cp->set_start_token(start_token);
commit = 1;
//
// now clear the value of this environment variable so
// that subsequent children of this process don't get
// confused.
//
// This is done in a really ugly fashion, because older
// versions of the ToolTalk library on Sun assumed that the
// token was there if the _TT_TOKEN environment variable
// existed, even if the value (after the '=') was null.
// Unfortunately there is no portable way to completely
// remove a environment variable from the environment. The
// best we can do is change the environment variable name.
// Since we're already being ugly, we do this in the brutal
// fashion of just backing up from the environment variable
// value into the name and punching over one of the
// characters. In particular, we change the 4th character
// in front of the equals sign (the 5th character in front
// of the value) to an "A". This changes _TT_TOKEN to
// _TT_TAKEN and _SUN_TT_TOKEN to _SUN_TT_TAKEN. This looks
// OK enough (the token's been taken) that maybe people
// looking in the environment won't be upset.
char *p;
p = getenv(TT_CDE_START_TOKEN);
if (p) {
*(p-5) = 'A';
}
p = getenv(TT_START_TOKEN);
if (p) {
*(p-5) = 'A';
}
}
status = cp->init();
if (commit) {
// we should check for TT_CDE_START_TOKEN or
// TT_START_TOKEN to be set. If
// so then we commit this procid which is required to
// join the session which caused this process to be
// started.
(void)cp->commit();
}
if (status != TT_OK) {
_default_c_procid = (_Tt_c_procid *)0;
#ifdef OPT_XTHREADS
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(default_c_session,
(_Tt_c_procid *) 0);
xthread_set_specific(_tt_global->threadkey, tss);
}
else {
tss->free_procid();
}
#endif
return(status);
}
active_procs->insert(default_c_procid());
return(TT_OK);
}
//
// Returns a count of how many procids are in the active procid cache.
//
int _Tt_c_mp::
procid_count()
{
if (active_procs.is_null()) {
return(0);
} else {
return(active_procs->count());
}
}
#ifdef OPT_XTHREADS
//
// Initializes structures needed for multithreading
//
void _Tt_c_mp::
set_multithreaded()
{
if (_tt_global->multithreaded()) {
_Tt_threadspecific* tss =
new _Tt_threadspecific(default_c_session,
(_Tt_c_procid *) 0);
xthread_set_specific(_tt_global->threadkey, tss);
}
}
#endif

View File

@@ -0,0 +1,46 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_mp.h /main/5 1995/11/28 19:27:40 cde-sun $ */
/*
* mp_c_mp.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* This file declares the _Tt_c_mp object which represents the client-only
* global information for the MP component. There should only be one instance
* of a _Tt_mp object in either server or client mode.
*/
#ifndef _MP_C_MP_H
#define _MP_C_MP_H
#include "mp/mp.h"
#include "mp/mp_c_session_utils.h"
#include "mp/mp_c_procid_utils.h"
class _Tt_c_mp : public _Tt_mp {
public:
_Tt_c_mp();
virtual ~_Tt_c_mp();
Tt_status c_init();
Tt_status set_default_procid(_Tt_string id,
int thread_only = 0);
_Tt_procid_ptr &default_procid();
_Tt_c_procid_ptr &default_c_procid();
Tt_status create_new_procid();
Tt_status c_remove_procid(_Tt_procid_ptr &proc);
_Tt_c_session_ptr initial_c_session;
int procid_count();
#ifdef OPT_XTHREADS
void set_multithreaded();
#endif
_Tt_c_session_ptr default_c_session;
protected:
_Tt_c_procid_ptr _default_c_procid;
};
#endif /* _MP_C_MP_H */

View File

@@ -0,0 +1,68 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_msg_context.C /main/3 1995/10/23 10:20:54 rswiston $
/*
*
* @(#)mp_c_msg_context.C 1.4 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_c_msg_context.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* _Tt_c_msg_context knows the client side of the context RPC interface.
*/
#include <mp/mp_arg.h>
#include <mp/mp_c_msg_context.h>
#include <mp/mp_rpc_interface.h>
#include <mp/mp_xdr_functions.h>
_Tt_c_msg_context::_Tt_c_msg_context()
{
}
_Tt_c_msg_context::~_Tt_c_msg_context()
{
}
Tt_status
_Tt_c_msg_context::c_join(
_Tt_session &session,
_Tt_procid_ptr &procID
)
{
Tt_status status;
Tt_status rstatus;
_Tt_context_join_args args;
args.procid = procID;
args.context = this;
rstatus = session.call( TT_RPC_JOIN_CONTEXT,
(xdrproc_t)tt_xdr_context_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status );
return (rstatus == TT_OK) ? status : rstatus;
}
Tt_status
_Tt_c_msg_context::c_quit(
_Tt_session &session,
_Tt_procid_ptr &procID
)
{
Tt_status status;
Tt_status rstatus;
_Tt_context_join_args args;
args.procid = procID;
args.context = this;
rstatus = session.call( TT_RPC_QUIT_CONTEXT,
(xdrproc_t)tt_xdr_context_join_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status );
return (rstatus == TT_OK) ? status : rstatus;
}

View File

@@ -0,0 +1,40 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_msg_context.h /main/3 1995/10/23 10:21:02 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_c_msg_context.h 1.4 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_c_msg_context.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* _Tt_c_msg_context knows the client side of the context RPC interface.
*/
#ifndef _MP_C_MSG_CONTEXT_H
#define _MP_C_MSG_CONTEXT_H
#include <mp/mp_msg_context.h>
#include <mp/mp_c_msg_context_utils.h>
#include <mp/mp_session.h>
#include <mp/mp_procid_utils.h>
class _Tt_c_msg_context : public _Tt_msg_context {
public:
_Tt_c_msg_context();
virtual ~_Tt_c_msg_context();
Tt_status c_join(
_Tt_session &session,
_Tt_procid_ptr &procID
);
Tt_status c_quit(
_Tt_session &session,
_Tt_procid_ptr &procID
);
};
#endif /* _MP_C_MSG_CONTEXT_H */

View File

@@ -0,0 +1,18 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_msg_context_utils.C /main/3 1995/10/23 10:21:09 rswiston $
/* -*-C++-*-
*
* @(#)mp_c_msg_context_utils.C 1.2 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_c_msg_context_utils.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include <mp/mp_c_msg_context.h>
#include <mp/mp_c_msg_context_utils.h>
implement_list_of(_Tt_c_msg_context)

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_msg_context_utils.h /main/3 1995/10/23 10:21:16 rswiston $ */
/*
* @(#)mp_c_msg_context_utils.h 1.2 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_c_msg_context_utils.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#ifndef MP_C_MSG_CONTEXT_UTILS_H
#define MP_C_MSG_CONTEXT_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
class _Tt_c_msg_context;
declare_list_of(_Tt_c_msg_context)
#endif /* MP_C_MSG_CONTEXT_UTILS_H */

View File

@@ -0,0 +1,93 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_pattern.C /main/3 1995/10/23 10:21:24 rswiston $
/*
*
* mp_c_pattern.cc
*
* _Tt_pattern member functions called only on client side. Since there are
* so few, I didn't bother making a _Tt_c_pattern class, but by breaking
* this out into a separate file we can avoid defining _tt_c_mp in the
* main mp_pattern.cc file, so that inadvertent references to it get
* caught at compile time.
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include "mp/mp_c.h"
#include "mp/mp_pattern.h"
#include "api/c/api_error.h"
#include "util/tt_port.h"
//
// Constructor for a _Tt_pattern. Calls the base constructor and in
// client-mode, sets the id of the pattern.
//
_Tt_pattern::
_Tt_pattern()
{
if (! _tt_mp->in_server()) {
set_id(_tt_c_mp->default_procid()->id());
}
base_constructor();
}
//
// Called by _Tt_procid::add_pattern only in client mode.
//
// Sets the id for this pattern which is unique. The uniqueness of the id
// is guaranteed by giving the procid of the "sender" which is the procid
// which is registering this pattern. To further distinguish among
// different patterns registered by the same sender, there is a counter
// maintainted by _Tt_mp and returned by generate_pattern_id. Thus the id
// consists of <counter>:<sender_id>
//
// XXX: note that _Tt_procid::sender has a dependency on the format of
// this message.
//
void _Tt_pattern::
set_id(const _Tt_string &sender)
{
char id[256];
sprintf(id,"%d:%s",_tt_mp->generate_pattern_id(),(char *)sender);
_pattern_id = id;
}
//
// If this pattern is file scoped, record this session on this pattern's
// files.
//
Tt_status _Tt_pattern::
join_files(const _Tt_string &sessID) const
{
if (! ((scopes() & (1<<TT_FILE)) || (scopes() & (1<<TT_BOTH)))) {
// Not file-scoped
return TT_OK;
}
Tt_status worstErr = TT_OK;
_Tt_db_results dbStatus;
Tt_status status;
_Tt_c_file_ptr file;
_Tt_string_list_cursor fileC( _files );
while (fileC.next()) {
status = _tt_mp->find_file( *fileC, file, 1 );
if (status != TT_OK) {
worstErr = status;
continue;
}
dbStatus = file->addSession( sessID );
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_ERR,
"_Tt_db_file::addSession(): %d", dbStatus);
}
if (status != TT_OK) {
worstErr = status;
continue;
}
}
return worstErr;
}

View File

@@ -0,0 +1,819 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_c_procid.C /main/5 1999/09/17 18:27:38 mgreess $
/*
* @(#)mp_c_procid.C 1.30 93/07/30
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
#include <unistd.h>
#include <fcntl.h>
#include <tt_options.h>
#include <util/tt_global_env.h>
#include <util/tt_host.h>
#include <util/tt_threadspecific.h>
#include <mp/mp_c_file.h>
#include <mp/mp_c_message.h>
#include <mp/mp_c_mp.h>
#include <mp/mp_c_global.h>
#include <mp/mp_pattern.h>
#include <mp/mp_c_procid.h>
#include <mp/mp_rpc_interface.h>
#include <mp/mp_c_session.h>
#include <mp/mp_stream_socket.h>
#include <util/tt_int_rec.h>
#include <arpa/inet.h>
//
// This file contains client-side only methods for procids.
//
_Tt_c_procid::
_Tt_c_procid()
{
}
_Tt_c_procid::
~_Tt_c_procid()
{
}
_Tt_c_procid::
_Tt_c_procid(const _Tt_string &id)
{
_id = id;
}
//
// Used by the client library to register a new pattern. The real work is
// done on the server-side.
//
Tt_status _Tt_c_procid::
add_pattern(_Tt_pattern_ptr &p)
{
Tt_status status;
Tt_status rstatus;
_Tt_add_pattern_args args;
if (p->category() == TT_CATEGORY_LAST) {
// category needs to be set
return(TT_ERR_CATEGORY);
}
args.procid = this;
args.pattern = p;
rstatus = default_session()->call( p->contextsCount()
? TT_RPC_ADD_PATTERN_WITH_CONTEXT
: TT_RPC_ADD_PATTERN,
(xdrproc_t)tt_xdr_add_pattern_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (rstatus != TT_OK) {
return rstatus;
}
if (status != TT_OK) {
return status;
}
return p->join_files( default_session()->process_tree_id() );
}
//
// Invokes the right rpc call to cause this procid to be recognized as an
// instance of the given ptype. The server-side does most of the work
// here. The only subtlety here is that we keep a list of the ptypes that
// this procid has declared itself as so that file-scope message queueing
// can work properly.
//
Tt_status _Tt_c_procid::
declare_ptype(_Tt_string &ptid)
{
Tt_status status;
Tt_status rstatus;
_Tt_declare_ptype_args args;
args.procid = this;
args.ptid = ptid;
rstatus = default_session()->call(TT_RPC_DECLARE_PTYPE,
(xdrproc_t)tt_xdr_declare_ptype_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (rstatus == TT_OK && status == TT_OK) {
if (_declared_ptypes.is_null()) {
_declared_ptypes = new _Tt_string_list();
}
_declared_ptypes->push(ptid);
}
return((rstatus == TT_OK) ? status : rstatus);
}
//
// Invokes the right rpc call to cause this procid to stop being recognized
// as an instance of the given ptype. The server-side does most of the work
// here. The only subtlety here is that we keep a list of the ptypes that
// this procid has declared itself as so that file-scope message queueing
// can work properly, and that has to be updated too. We also use
// this local list to return a bad error code if the ptype was never
// declared \(I suppose it would be a optimization to only make the
// RPC call if the ptype\'s in the list...\)
//
Tt_status _Tt_c_procid::
undeclare_ptype(_Tt_string &ptid)
{
Tt_status status;
Tt_status rstatus;
_Tt_declare_ptype_args args;
args.procid = this;
args.ptid = ptid;
rstatus = default_session()->call(TT_RPC_UNDECLARE_PTYPE,
(xdrproc_t)tt_xdr_declare_ptype_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
if (rstatus == TT_OK && status == TT_OK) {
if (!_declared_ptypes.is_null()) {
_Tt_string_list_cursor c(_declared_ptypes);
int was_declared = 0;
while (c.next()) {
if (*c == ptid) {
c.remove();
was_declared = 1;
}
}
if (!was_declared) {
status = TT_ERR_PTYPE;
}
}
}
return((rstatus == TT_OK) ? status : rstatus);
}
//
// Invokes the right rpc call to test if a ptype is known by the current
// ttsession.
//
Tt_status _Tt_c_procid::
exists_ptype(_Tt_string &ptid)
{
Tt_status status;
Tt_status rstatus;
_Tt_declare_ptype_args args;
args.procid = this;
args.ptid = ptid;
rstatus = default_session()->call(TT_RPC_EXISTS_PTYPE,
(xdrproc_t)tt_xdr_declare_ptype_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
//
// Invokes the right rpc call to unblock any messages being held for
// this ptype until this process is intialized.
//
Tt_status _Tt_c_procid::
unblock_ptype(const _Tt_string &ptid)
{
Tt_status status;
Tt_status rstatus;
_Tt_declare_ptype_args args;
args.procid = this;
args.ptid = ptid;
rstatus = default_session()->call(TT_RPC_UNBLOCK_PTYPE,
(xdrproc_t)tt_xdr_declare_ptype_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
//
// Unregister a pattern for this procid. The pattern is identified by its
// id which is matched up on the server-side to the real pattern object.
//
Tt_status _Tt_c_procid::
del_pattern(const _Tt_string &id)
{
Tt_status status;
Tt_status rstatus;
_Tt_del_pattern_args args;
if (id.len() == 0) {
return(TT_ERR_INVALID);
}
args.procid = this;
args.pattern_id = id;
rstatus = default_session()->call(TT_RPC_DEL_PATTERN,
(xdrproc_t)tt_xdr_del_pattern_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
// Invokes the right rpc call to load a set of types, contained in a
// string which is the image of an XDR types file, into the ttsession.
//
Tt_status _Tt_c_procid::
load_types(_Tt_string &typebuffer)
{
Tt_status status;
Tt_status rstatus;
_Tt_load_types_args args;
args.xdrtypes = typebuffer;
rstatus = default_session()->call(TT_RPC_LOAD_TYPES,
(xdrproc_t)tt_xdr_load_types_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
_Tt_c_session_ptr& _Tt_c_procid::
default_session()
{
#ifdef OPT_XTHREADS
if (_tt_global->multithreaded()) {
// Use the thread-specific session if there is one
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey, (void **) &tss);
if (!tss) {
// thread-specific storage not yet initialized -- do it
tss = new _Tt_threadspecific(_tt_c_mp->default_c_session,
this);
xthread_set_specific(_tt_global->threadkey, tss);
}
_Tt_c_session_ptr sptr = tss->thread_c_session();
if (!sptr.is_null()) {
return tss->thread_c_session();
}
else {
tss->set_thread_c_session(_default_session);
return _default_session;
}
}
else {
return _default_session;
}
#else
return _default_session;
#endif
}
//
// In a multiple-procid, multiple-session usage this method means that
// the current procid has done some action that requires it to be bound
// to the current session. This method just turns on a flag in the procid
// object that means it is now bound to the current session.
//
Tt_status _Tt_c_procid::
commit()
{
if (default_session().is_null()) {
return(TT_ERR_NOMP);
}
_flags |= (1<<_TT_PROC_COMMITTED);
return(TT_OK);
}
//
// Initializes a procid for use. The main duties are to set the id of a
// procid and to initialize a signalling channel. Setting the id involves
// asking the server for a unique prefix to make the procid's id unique
// among all procids currently registered with the session. (see set_id
// method). The signalling channel is initialized here because it is the
// main mechanism for the server to know if this procid has exited (since
// breaking the signalling channel will wake up the server).
//
Tt_status _Tt_c_procid::
init()
{
int rpc_version = TT_RPC_VERSION;
Tt_status status;
if (_default_session.is_null()) {
// set the default session to the initial session.
#ifdef OPT_XTHREADS
if (_tt_global->multithreaded()) {
// Use the thread-specific session if there is one
_Tt_threadspecific* tss = (_Tt_threadspecific *) 0;
xthread_get_specific(_tt_global->threadkey,
(void **) &tss);
if (!tss) {
// thread-specific storage not yet
// initialized -- do it
tss = new _Tt_threadspecific(_tt_c_mp->
default_c_session,
this);
xthread_set_specific(_tt_global->threadkey, tss);
}
_Tt_c_session_ptr sptr = tss->thread_c_session();
if (!sptr.is_null()) {
_default_session = sptr;
}
else {
tss->set_thread_c_session(_tt_c_mp->
default_c_session);
_default_session = _tt_c_mp->default_c_session;
}
}
else {
_default_session = _tt_c_mp->default_c_session;
}
#else
_default_session = _tt_c_mp->default_c_session;
#endif
if (_default_session.is_null()) {
return(TT_ERR_NOMP);
}
}
_version = TT_RPC_VERSION;
_pid = getpid();
if (! _tt_global->get_local_host(_proc_host)) {
return(TT_ERR_NOMP);
}
_proc_host_ipaddr = _proc_host->addr();
status = _default_session->call(TT_RPC_ALLOC_PROCID_KEY,
(xdrproc_t)xdr_void, 0,
(xdrproc_t)tt_xdr_string,
(char *)&_id);
if (status != TT_OK) {
return(status);
}
if (!_id.len()) {
return(TT_ERR_INTERNAL);
}
_id = _id.cat(" ").cat(_default_session->address_string());
// now set up an fd channel which is used by the
// server side to notify this procid of new messages
// as well as a notification mechanism of this procid
// going away (by breaking the fd channel).
if (set_fd_channel() && fd() != -1) {
return(TT_OK);
} else {
return(TT_ERR_PROCID);
}
}
//
// Retrieves the next message for this procid. Conceptually, this means
// retrieving the next message from the queue of undelivered messages
// (the _undelivered field). This field is mainly kept on the server-side
// so it involves an rpc call to the server to dequeue the next message
// for this procid. For optimization's sake, this method is coded so the
// rpc call actually returns a list of messages. This allows batching of
// message delivery. The list is assigned to our local copy of
// _undelivered and messages are consumed from this list until it is
// exhausted at which time we invoke the rpc call again.
//
// If OPT_ADDMSG_DIRECT is defined then it will read the message directly
// from the signalling socket.
//
Tt_status _Tt_c_procid::
next_message(_Tt_c_message_ptr &msg)
{
_Tt_procid_ptr proc = this;
if (! _unvoted.is_null()) {
update_message( _unvoted, TT_ABSTAINED );
_unvoted = 0;
}
#ifdef OPT_ADDMSG_DIRECT
if (default_session()->rpc_version() >= TT_ADDMSG_VERS) {
if (_mxdr_stream == (XDR *)0) {
_mxdr_stream = (XDR *)malloc(sizeof(XDR));
xdrrec_create(_mxdr_stream, 0, 0,
(char *)_socket.c_pointer(),
(int (*)())_tt_xdr_readit,
(int (*)())_tt_xdr_writeit);
_mxdr_stream->x_op = XDR_DECODE;
}
msg = (_Tt_message *)0;
(void)xdrrec_skiprecord(_mxdr_stream);
if (! msg.xdr(_mxdr_stream)) {
msg = (_Tt_message *)0;
if (_flags&(1<<_TT_PROC_FD_CHANNEL_ON)) {
dup2(_socket->sock(), _socket->fd());
_flags &= ~(1<<_TT_PROC_FD_CHANNEL_ON);
}
return(TT_ERR_NOMP);
}
if (! msg.is_null()) {
if (msg->state() == TT_STARTED && handling(msg)) {
msg->set_state(TT_SENT);
msg->set_start_message();
}
// We need to notify the server that we've
// read the message. Otherwise, it would never
// know that it should send us messages
// through the fd again. This notification
// also tells the server to reset the timer
// for this message.
// XXX: it would be nice to find a protocol
// that didn't need this extra rpc call.
default_session()->call(TT_RPC_MSGREAD_2,
(xdrproc_t)tt_xdr_procid,
(char *)&proc,
(xdrproc_t)xdr_void,
(char *)0);
return(TT_OK);
}
}
#endif // OPT_ADDMSG_DIRECT
// We're here if we're talking to a version 1 server or if a
// null message ptr was sent down the signalling fd. This
// means that we are to use an rpc call to get the message for
// us.
Tt_status rstatus = TT_OK;
if (_undelivered.is_null() || _undelivered->count() == 0) {
_Tt_next_message_args args;
rstatus = default_session()->call(TT_RPC_NEXT_MESSAGE,
(xdrproc_t)tt_xdr_procid,
(char *)&proc,
(xdrproc_t)tt_xdr_next_message_args,
(char *)&args);
switch (rstatus) {
case TT_OK:
_undelivered = args.msgs;
// set the signalled flag to tell us whether we should
// clear the new message signal when all messages have
// been retrieved from the local _undelivered queue.
if (args.clear_signal) {
_flags &= ~(1<<_TT_PROC_SIGNALLED);
} else {
_flags |= (1<<_TT_PROC_SIGNALLED);
}
break;
case TT_ERR_NOMP:
// server got disconnected either because it
// was killed or because of network errors.
// We now dup the previous fd so that it won't
// stay active.
if (_flags&(1<<_TT_PROC_FD_CHANNEL_ON)) {
dup2(_socket->sock(), _socket->fd());
_flags &= ~(1<<_TT_PROC_FD_CHANNEL_ON);
}
break;
default:
break;
}
}
switch (rstatus) {
case TT_OK:
case TT_WRN_NOTFOUND:
break;
default:
return(rstatus);
}
if (_undelivered.is_null() || _undelivered->count() == 0) {
msg = 0;
} else {
msg = (_Tt_c_message *)_undelivered->bot().c_pointer();
_undelivered->dequeue();
if (msg->queue() && msg->scope() == TT_FILE) {
_Tt_file_ptr fptr;
if (_tt_mp->find_file(msg->file(), fptr, 1) == TT_OK) {
((_Tt_c_file *)fptr.c_pointer())->
process_message_queue(0);
}
}
if (msg->state() == TT_STARTED && processing(*msg)) {
msg->set_state(TT_SENT);
msg->set_start_message();
}
#ifdef OPT_ADDMSG_DIRECT
if (default_session()->rpc_version() >= TT_ADDMSG_VERS) {
return(rstatus);
}
#endif
// unless we're getting messages through the
// signalling fd, we have to clear the input from the
// fd if there are no more messages.
if ((! (_flags&(1<<_TT_PROC_SIGNALLED))) &&
(_undelivered.is_null()
|| _undelivered->count() == 0)) {
clear_signal();
}
if ((msg->message_class() == TT_OFFER) && processing(*msg)) {
_unvoted = msg;
}
}
return(rstatus);
}
//
// Quits out of any joined files.
//
void _Tt_c_procid::
close()
{
_Tt_string_list_cursor filec(_joined_files);
_Tt_c_file_ptr fp;
_Tt_procid_ptr pptr = this;
while (filec.next()) {
if (_tt_mp->find_file(*filec, fp, 0) == TT_OK) {
(void)fp->c_quit(pptr);
}
filec.remove();
}
}
//
// Sets the default session for this procid. If a zero-length string is
// passed in as the session id then the procid is detached from the
// current session.
//
Tt_status _Tt_c_procid::
set_default_session(_Tt_string &sid)
{
_Tt_c_session_ptr session;
Tt_status status;
if (sid.len() == 0) { // detach from default session
default_session() = (_Tt_c_session *)0;
_flags &= ~(1<<_TT_PROC_COMMITTED);
status = TT_OK;
} else { // set default session
// can only join one session for now. If a session is
// "committed" then we can't switch sessions for this procid.
_Tt_string this_id = default_session()->id();
if (_flags&(1<<_TT_PROC_COMMITTED)) {
if (sid != this_id) {
return(TT_ERR_SESSION);
}
}
// initialize session from sid
status = _tt_c_mp->find_session(sid, default_session(), 1, 1);
}
return(status);
}
//
// Updates the message with the same id as "msg" that is presumed to be in
// the queue of delivered messages for this procid on the server-side.
// (see _Tt_s_procid::update_message for details). This method is
// invoked when a handler is replying, failing, or rejecting a message.
// It is also involved in the special case of an observer replying to its
// start message.
//
Tt_status _Tt_c_procid::
update_message(const _Tt_c_message_ptr &msg, Tt_state newstate)
{
Tt_status rstatus;
_Tt_update_args args;
int clr_obs = 0;
if (msg.is_null()) {
return TT_ERR_POINTER;
}
switch (newstate) {
case TT_HANDLED:
if (msg->is_start_message()) {
// OK to reply() instead of accept()
break;
}
if (msg->message_class() != TT_REQUEST) {
return TT_ERR_CLASS;
}
if (msg->handler().is_null()) {
return TT_ERR_NOTHANDLER;
}
if (! is_equal( msg->handler())) {
return TT_ERR_NOTHANDLER;
}
break;
case TT_ABSTAINED:
if (msg->message_class() != TT_OFFER) {
return TT_ERR_CLASS;
}
break;
case TT_REJECTED:
if ((msg->state() != TT_SENT) && (msg->state() != TT_STARTED)) {
return TT_ERR_STATE;
}
}
// if this message is already in a "final" state then
// don't allow the state change
switch (msg->state()) {
case TT_FAILED:
case TT_HANDLED:
case TT_RETURNED:
return TT_ERR_STATE;
}
msg->add_voter( this, newstate );
// optimize message xdr'ing for this case
msg->set_return_handler_flags();
args.message = msg;
args.newstate = newstate;
// invoke the appropiate rpc procedure depending on the
// version of the server we're connected with
switch (default_session()->rpc_version()) {
case 1:
Tt_status status;
rstatus = default_session()->call(TT_RPC_UPDATE_MSG,
(xdrproc_t)tt_xdr_update_args,
(char *)&args,
(xdrproc_t)xdr_int,
(char *)&status);
msg->set_state(newstate);
return((rstatus == TT_OK) ? status : rstatus);
case 2:
default:
if (msg->is_start_message() && msg->handler().is_null()) {
//
// If this procid is an observer replying to
// its start message then we have to
// temporarily set its handler procid in order
// to tell ttsession which procid we are.
// See _tt_update_msg() for more details.
//
msg->set_observer_procid(this);
clr_obs = 1;
}
rstatus = default_session()->call(TT_RPC_UPDATE_MSG_2,
(xdrproc_t)tt_xdr_update_args,
(char *)&args,
(xdrproc_t)xdr_void,
(char *)0);
if (clr_obs) {
// clear the handler procid if it was just set
// for the special case of an observer
// replying to a start message.
msg->clr_observer_procid();
}
// update the state of the message to the new state
msg->set_state(newstate);
return(rstatus);
}
}
//
// Sets the signalling channel for this procid to an fd which is
// implemented here by opening a TCP socket so signal the procid. It is
// desirable to use a TCP socket because it is "reliable" which means
// that when signalling the procid fails, it's a good bet the procid has
// gone away.
//
// This method is somewhat tricky because it has to open a socket and
// leave the socket in a state ready to accept connections (the details
// of this are in _Tt_stream_socket::init). Then it invokes an rpc call
// telling the server the port number of the socket. At this point the
// server-side method _Tt_s_procid::set_fd_channel will attempt to
// connect to this socket. The _Tt_c_procid::fd method will complete this
// socket connection (by invoking the _Tt_stream_socket::fd method) so
// it should be called after this method is called. This is done above
// in _Tt_c_procid::init.
//
// XXX: It seems like the code in _Tt_c_procid::fd should have just been
// included before returning in this method.
//
int _Tt_c_procid::
set_fd_channel(int p)
{
_Tt_fd_args fd_args;
Tt_status rstatus;
Tt_status status;
if (_flags&(1<<_TT_PROC_FD_CHANNEL_ON)) {
return(1);
}
_socket = new _Tt_stream_socket(_proc_host, p);
if (! _socket->init(1)) {
_socket = (_Tt_stream_socket *)0;
return(-1);
}
fd_args.procid = this;
fd_args.start_token = _start_token;
fd_args.fd = port();
rstatus = default_session()->call(TT_RPC_SET_FD_CHANNEL,
(xdrproc_t)tt_xdr_fd_args,
(char *)&fd_args,
(xdrproc_t)xdr_int,
(char *)&status);
if (rstatus != TT_OK || status != TT_OK) {
return(0);
}
// clear the start token so the server won't attempt
// to issue a proc_started event on the ptype each
// time we contact it.
_start_token = (char *)0;
_flags |= (1<<_TT_PROC_FD_CHANNEL_ON);
return(1);
}
//
// Clears the signalling socket by reading the byte that gets sent to it
// by the server to notify the arrival of new messages. A read is avoided
// if it would block.
//
void _Tt_c_procid::
clear_signal()
{
char sig[2];
if (_flags&(1<<_TT_PROC_FD_CHANNEL_ON)) {
sig[1] = 0;
if (_socket->read_would_block() != 1) {
return;
}
if (_socket->recv(sig, 1) < 0) {
}
}
}
//
// Sets the default ptype for this procid.
//
void _Tt_c_procid::
set_default_ptype(_Tt_string &ptid)
{
_default_ptype = ptid;
}
//
// Sets the default file for this procid.
//
void _Tt_c_procid::
set_default_file(const _Tt_string &file)
{
_default_file = file;
}

View File

@@ -0,0 +1,68 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_procid.h /main/4 1995/11/21 19:25:50 cde-sun $ */
/* @(#)mp_c_procid.h 1.11 93/07/30
*
* Copyright (c) 1990, 1992 by Sun Microsystems, Inc.
*
* This file implements the client side of the _Tt_procid object.
*/
#ifndef _MP_C_PROCID_H
#define _MP_C_PROCID_H
#include <mp/mp_procid.h>
#include <mp/mp_c_session.h>
#include <mp/mp_c_message_utils.h>
#include "api/c/api_typecb_utils.h"
class _Tt_c_procid : public _Tt_procid {
public:
_Tt_c_procid();
~_Tt_c_procid();
_Tt_c_procid(const _Tt_string &id);
Tt_status add_pattern(_Tt_pattern_ptr &p);
Tt_status api_in(_Tt_string &s);
_Tt_string api_out();
void clear_signal();
void close();
Tt_status commit();
Tt_status declare_ptype(_Tt_string &ptid);
Tt_status undeclare_ptype(_Tt_string &ptid);
Tt_status exists_ptype(_Tt_string &ptid);
Tt_status unblock_ptype(const _Tt_string &ptid);
Tt_status load_types(_Tt_string &typebuffer);
_Tt_string &default_file() {
return _default_file;
}
_Tt_string &default_ptype() {
return _default_ptype;
}
_Tt_c_session_ptr &default_session();
Tt_status del_pattern(const _Tt_string &id);
Tt_status init();
Tt_status next_message(_Tt_c_message_ptr &m);
void set_default_ptype(_Tt_string &ptid);
void set_default_file(const _Tt_string &file);
Tt_status set_default_session(_Tt_string &id);
int set_fd_channel(int port = 0);
Tt_status update_message(const _Tt_c_message_ptr &msg,
Tt_state newstate);
_Tt_typecb_table_ptr & ptype_callbacks() {
return _ptype_callbacks;
}
_Tt_typecb_table_ptr & otype_callbacks() {
return _otype_callbacks;
}
private:
_Tt_string _default_file;
_Tt_string _default_ptype;
_Tt_c_session_ptr _default_session;
_Tt_message_list_ptr _undelivered;
_Tt_c_message_ptr _unvoted;
_Tt_typecb_table_ptr _ptype_callbacks;
_Tt_typecb_table_ptr _otype_callbacks;
};
#endif /* _MP_C_PROCID_H */

View File

@@ -0,0 +1,19 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_procid_utils.C /main/3 1995/10/23 10:21:47 rswiston $
/*
*
* mp_c_procid_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of auxiliary data structures for the _Tt_c_procid class
*/
#include "mp/mp_c_procid.h"
#include "mp/mp_c_procid_utils.h"
implement_derived_ptr_to(_Tt_c_procid,_Tt_procid)
implement_table_of(_Tt_c_procid)

View File

@@ -0,0 +1,23 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_procid_utils.h /main/3 1995/10/23 10:21:54 rswiston $ */
/*
*
* mp_c_procid_utils.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_procid_utils
*/
#ifndef _MP_C_PROCID_UTILS_H
#define _MP_C_PROCID_UTILS_H
#include "util/tt_object.h"
#include "mp/mp_procid_utils.h"
class _Tt_c_procid;
declare_derived_ptr_to(_Tt_c_procid,_Tt_procid)
declare_table_of(_Tt_c_procid)
#endif /* MP_PROCID_UTILS_H */

View File

@@ -0,0 +1,316 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_c_session.C /main/5 1999/10/14 18:41:24 mgreess $
/*
* @(#)mp_c_session.C 1.23 94/10/03
*
* Copyright (c) 1990,1992,1993 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_session class.
*/
#include "util/tt_global_env.h"
#include "util/tt_host.h"
#include "util/tt_enumname.h"
#include "mp/mp_global.h"
#include "mp/mp_c_message.h"
#include "mp/mp_mp.h"
#include "mp/mp_pattern.h"
#include "mp/mp_rpc_client.h"
#include "mp/mp_rpc_interface.h"
#include "mp/mp_c_session.h"
#include "mp/mp_desktop.h"
#include "mp/mp_xdr_functions.h"
#include "util/tt_port.h"
#include <unistd.h>
#include <signal.h>
#ifdef OPT_UNIX_SOCKET_RPC
# include <sys/socket.h>
# include <sys/un.h>
#endif // OPT_UNIX_SOCKET_RPC
// Use the parent class (_Tt_session) for construction and destruction.
_Tt_c_session::_Tt_c_session () {}
_Tt_c_session::~_Tt_c_session () {}
//
// Initializes a session object. This means that we initialize our
// desktop connection if this is a desktop session and find the address
// of a server session. If none is found or if an address is found but we
// are unable to connect to the session then we attempt to auto-start a
// server session.
//
// Returns:
// TT_OK
// TT_ERR_ACCESS Could not init desktop (diagnostic emitted)
// TT_ERR_NO_MATCH Advertised address's version is too new
// (diagnostic emitted)
// TT_ERR_INVALID Authorization error
// TT_ERR_NOMP No server running or startable
//
Tt_status _Tt_c_session::
c_init()
{
_Tt_string start_ttcmd;
int tried = 0;
int done = 0;
Tt_status status;
if (env() == _TT_ENV_X11) {
if (_displayname.len() == 0) {
_displayname = _tt_global->xdisplayname;
}
}
while (tried < 10) {
_is_dead = 0;
status = client_session_init();
switch (status) {
int pings;
case TT_OK:
// We try to ping the session to give it
// reasonable time to start up.
for (pings = 1; pings <= OPT_PING_TRIES; pings++) {
status = ping();
if (status != TT_ERR_NOMP) {
// Fatal error or TT_OK
return status;
}
sleep(OPT_PING_SLEEP);
}
// Session could not be pinged. If this is an
// X11 session, handle the case where there is
// an invalid TT_CDE_XATOM_NAME xprop and a valid
// TT_XATOM_NAME xprop, because in that case we
// were trying to ping the dead TT_CDE_XATOM_NAME
// session.
if (env() == _TT_ENV_X11) {
_Tt_string desktop_addr;
if (_desktop->get_prop(TT_CDE_XATOM_NAME,
desktop_addr) &&
desktop_addr == _address_string) {
// Bogus session xprop found -- re-initialize
// trying the TT_XATOM_NAME xprop.
if (_desktop->get_prop(TT_XATOM_NAME,
_address_string)) {
// Continue the initialization
// loop WITHOUT attempting to start
// a new ttsession
tried++;
continue;
}
}
}
else {
// If we\'re here, a session was found but could
// not be pinged. Force re-initialization.
_address_string = (char *) 0;
break;
}
case TT_ERR_ACCESS:
case TT_ERR_NO_MATCH:
// Can't recover from these
return status;
case TT_WRN_NOTFOUND:
case TT_ERR_INVALID:
case TT_ERR_NOMP:
// No ttsession.
// If we haven\'t tried to start one already, do
// so. If we have tried but failed, force
// client_session_init to re-initialize.
if (tried > 0) _address_string = (char *) 0;
break;
case TT_AUTHFILE_ACCESS:
case TT_AUTHFILE_LOCK:
case TT_AUTHFILE_LOCK_TIMEOUT:
case TT_AUTHFILE_UNLOCK:
case TT_AUTHFILE_MISSING:
case TT_AUTHFILE_ENTRY_MISSING:
case TT_AUTHFILE_WRITE:
return TT_ERR_AUTHORIZATION;
default:
_tt_syslog( 0, LOG_ERR,
"_Tt_session::client_session_init(): %s",
_tt_enumname(status));
return TT_ERR_INTERNAL;
}
//
// Attempt to start a new server
//
if (env() != _TT_ENV_X11) {
// can't auto-start anything other than an X
// tooltalk session
return TT_ERR_NOMP;
}
if (tried == 0) {
int sysStat = startup_ttsession(start_ttcmd);
int exitStat;
if (WIFEXITED(sysStat)) {
exitStat = WEXITSTATUS(sysStat);
} else if (WIFSIGNALED(sysStat)) {
_tt_syslog( 0, LOG_ERR,
"libtt: system(\"%s\"): signal %d",
(char *)start_ttcmd,
WTERMSIG(sysStat) );
exitStat = 11;
} else {
_tt_syslog( 0, LOG_ERR,
"libtt: system(\"%s\"): %d",
(char *)start_ttcmd, sysStat );
exitStat = 11;
}
switch (exitStat) {
case 1:
// Race condition -- no ttsession was
// found in the above code, but by the time
// we got around to trying to start one,
// another had appeared, so this one exited
// normally.
// Fall through.
case 2:
// another ttsession discovered.
// Either way, loop around and connect to it
// after nulling _address_string to make sure
// we pick the address off the X server again
// since the new server will have a new
// address.
_address_string = (char *)0;
// Since the other ttsession was just started,
// let it have a chance to initialize
sleep(2);
// fall through
case 0:
// ttsession started.
break;
default:
return TT_ERR_NOMP;
}
} else {
sleep(1);
}
tried++;
}
return TT_ERR_NOMP;
}
// Starts ttsession by executing either the hardcoded
// default command "ttsession -s -d <displayname>"
// or the command specified in TTSESSION_CMD or SUN_TTSESSION_CMD.
// TTSESSION_CMD and SUN_TTSESSION_CMD provide a way of overriding the
// standard options specified when tools auto-start
// ttsession. For example, to switch from Classing
// Engine format to xdr format for auto-start set
// TTSESSION_CMD or SUN_TTSESSION_CMD to "ttsession -X".
// The string used is returned in a parameter so c_init can use it in
// error messages.
int _Tt_c_session::
startup_ttsession(_Tt_string &start_ttcmd)
{
// If TTSESSION_CMD or SUN_TTSESSION_CMD is specified, we use system() to run the
// command since it might have shell metacharacters (a common
// thing to do is TTSESSION_CMD or SUN_TTSESSION_CMD=truss ttsession >/tmp/trace
// in order to truss ttsession startup)
char* pc_env_value = _tt_get_first_set_env_var(2, "TTSESSION_CMD", "SUN_TTSESSION_CMD");
if (pc_env_value) {
start_ttcmd = pc_env_value;
start_ttcmd = start_ttcmd.cat(" -d ");
start_ttcmd = start_ttcmd.cat(_displayname);
return system((char *)start_ttcmd);
}
// start_ttcmd is not really used but we set it so it can be used
// in messages
start_ttcmd = "ttsession -s -d ";
start_ttcmd = start_ttcmd.cat(_displayname);
// This is basically a stripped down and specialized system() call...
int status;
pid_t pid, w;
#if defined(__GNUG__)
typedef void (*SIG_PF)(int);
#endif
SIG_PF istat, qstat, cstat;
#if defined(_AIX) || defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
#define vfork fork
#endif
if((pid = vfork()) == 0) {
fflush(stdout);
(void) execlp("ttsession", "ttsession",
"-s",
"-d",
(char *)_displayname,
(char *)0);
_exit(127);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
cstat = signal(SIGCLD, SIG_DFL);
w = waitpid(pid, &status, 0);
(void) signal(SIGINT, istat);
(void) signal(SIGQUIT, qstat);
(void) signal(SIGCLD, cstat);
return((w == -1)? w: status);
}
//
// Invokes an rpc call on the server session that causes all of the
// given procid's patterns to have a session id for the current
// session (this allows them to begin matching messages).
//
// See _Tt_s_session::s_join for the server-side of this method.
//
Tt_status _Tt_c_session::
c_join(_Tt_procid_ptr &procid)
{
Tt_status status;
Tt_status rstatus;
rstatus = call(TT_RPC_JOIN_SESSION,
(xdrproc_t)tt_xdr_procid,
(char *)&procid,
(xdrproc_t)xdr_int,
(char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
//
// Invokes an rpc call on the server session that causes all of the
// given procid's patterns to not have a session id for the current
// session (this prevents them from matching messages).
//
// See _Tt_s_session::s_quit for the server-side of this method.
//
Tt_status _Tt_c_session::
c_quit(_Tt_procid_ptr &procid)
{
Tt_status status;
Tt_status rstatus;
rstatus = call(TT_RPC_QUIT_SESSION,
(xdrproc_t)tt_xdr_procid, (char *)&procid,
(xdrproc_t)xdr_int, (char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}

View File

@@ -0,0 +1,38 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_session.h /main/3 1995/10/23 10:22:09 rswiston $ */
/*
* mp_c_session.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file contains the implementation of the client side of
* the _Tt_session object.
*/
#ifndef MP_C_SESSION_H
#define MP_C_SESSION_H
#include <mp/mp_session.h>
#include <mp/mp_c_session_utils.h>
class _Tt_c_session : public _Tt_session {
public:
_Tt_c_session();
virtual ~_Tt_c_session();
Tt_status c_addprop(_Tt_string prop, _Tt_string val);
Tt_status c_getprop(_Tt_string prop, int i,
_Tt_string &value);
Tt_status c_init();
Tt_status c_join(_Tt_procid_ptr &procid);
Tt_status c_propcount(_Tt_string prop, int &cnt);
Tt_status c_propname(int i, _Tt_string &prop);
Tt_status c_propnames_count(int &cnt);
Tt_status c_quit(_Tt_procid_ptr &procid);
Tt_status c_setprop(_Tt_string prop, _Tt_string val);
private:
int startup_ttsession(_Tt_string &command);
};
#endif /* MP_C_SESSION_H */

View File

@@ -0,0 +1,189 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_session_prop.C /main/3 1995/10/23 10:22:16 rswiston $
/*
*
* mp_c_session_prop.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_global.h>
#include <mp/mp_mp.h>
#include <mp/mp_rpc_client.h>
#include <mp/mp_rpc_interface.h>
#include <mp/mp_c_session.h>
#include <mp/mp_xdr_functions.h>
/*
* Set the session property to the value
*/
Tt_status _Tt_c_session::
c_setprop(_Tt_string prop, _Tt_string val)
{
Tt_status status;
Tt_status rstatus;
_Tt_prop_args args;
if (prop.len() == 0) {
return TT_ERR_INVALID;
}
args.prop = prop;
args.value = val;
args.num = 0;
rstatus = call(TT_RPC_SET_PROP,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)xdr_int, (char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
/*
* Add the value to the session property
*/
Tt_status _Tt_c_session::
c_addprop(_Tt_string prop, _Tt_string val)
{
Tt_status status;
Tt_status rstatus;
_Tt_prop_args args;
if (prop.len() == 0) {
return TT_ERR_INVALID;
}
args.prop = prop;
args.value = val;
args.num = 0;
rstatus = call(TT_RPC_ADD_PROP,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)xdr_int, (char *)&status);
return((rstatus == TT_OK) ? status : rstatus);
}
/*
* Get the ith value of the session property
*/
Tt_status _Tt_c_session::
c_getprop(_Tt_string prop, int i, _Tt_string &value)
{
_Tt_prop_args args;
_Tt_rpc_result result;
Tt_status rstatus;
if (prop.len() == 0) {
return TT_ERR_INVALID;
}
if (i < 0) {
return TT_ERR_INVALID;
}
args.prop = prop;
args.value = "";
args.num = i;
rstatus = call(TT_RPC_GET_PROP,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)tt_xdr_rpc_result, (char *)&result);
if (rstatus != TT_OK) {
return(rstatus);
}
if (result.status == TT_OK) {
value = result.str_val;
return(TT_OK);
} else {
return result.status;
}
}
/*
* Return the number of values on the session property
*/
Tt_status _Tt_c_session::
c_propcount(_Tt_string prop, int &cnt)
{
_Tt_prop_args args;
_Tt_rpc_result result;
Tt_status rstatus;
if (prop.len() == 0) {
return TT_ERR_INVALID;
}
args.prop = prop;
args.value = "";
args.num = 0;
rstatus = call(TT_RPC_PROP_COUNT,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)tt_xdr_rpc_result, (char *)&result);
if (rstatus != TT_OK) {
return(rstatus);
}
if (result.status != TT_OK) {
return result.status;
}
cnt = result.int_val;
return TT_OK;
}
/*
* Return the ith session property name
*/
Tt_status _Tt_c_session::
c_propname(int i, _Tt_string &prop)
{
_Tt_prop_args args;
_Tt_rpc_result result;
Tt_status rstatus;
if (i < 0) {
return TT_ERR_INVALID;
}
args.prop = "";
args.value = "";
args.num = i;
rstatus = call(TT_RPC_PROP_NAME,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)tt_xdr_rpc_result, (char *)&result);
if (rstatus != TT_OK) {
return(rstatus);
}
prop = result.str_val;
return result.status;
}
/*
* Return the number of session properties
*/
Tt_status _Tt_c_session::
c_propnames_count(int &cnt)
{
_Tt_prop_args args;
_Tt_rpc_result result;
Tt_status rstatus;
args.prop = "";
args.value = "";
args.num = 0;
rstatus = call(TT_RPC_PROP_NAMES_COUNT,
(xdrproc_t)tt_xdr_prop_args, (char *)&args,
(xdrproc_t)tt_xdr_rpc_result,(char *)&result);
if (rstatus != TT_OK) {
return(rstatus);
}
if (result.status != TT_OK) {
return result.status;
} else {
cnt = result.int_val;
return TT_OK;
}
}

View File

@@ -0,0 +1,16 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_c_session_utils.C /main/3 1995/10/23 10:22:23 rswiston $
/*
*
* mp_c_session_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of auxilliary data structures for the _Tt_c_session class
*/
#include <mp/mp_c_session.h>
implement_ptr_to(_Tt_c_session)

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_c_session_utils.h /main/3 1995/10/23 10:22:30 rswiston $ */
/*
*
* mp_c_session_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of auxilliary data structures for the _Tt_c_session class
*/
#ifndef MP_C_SESSION_UTILS_H
#define MP_C_SESSION_UTILS_H
#include <mp/mp_session_utils.h>
class _Tt_c_session;
declare_derived_ptr_to(_Tt_c_session,_Tt_session)
#endif /* MP_C_SESSION_UTILS_H */

View File

@@ -0,0 +1,72 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_context.C /main/3 1995/10/23 10:22:37 rswiston $
/*
*
* @(#)mp_context.C 1.5 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_context.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_context: a context slotname.
*/
#include <ctype.h>
#include <mp/mp_context.h>
_Tt_context::
_Tt_context()
{
}
_Tt_context::
_Tt_context(const _Tt_context &c)
{
_slotName = c._slotName;
}
_Tt_context::
~_Tt_context()
{
}
Tt_status _Tt_context::
setName(
const char *slotname
)
{
if (slotname == 0) {
return TT_ERR_SLOTNAME;
}
const char *pc = slotname;
if (*pc == '$') {
pc++;
}
while (*pc != 0) {
if ((! isalnum(*pc)) && (*pc != '_')) {
return TT_ERR_SLOTNAME;
}
pc++;
}
_slotName = slotname;
return TT_OK;
}
void _Tt_context::
print(
const _Tt_ostream &os
) const
{
_slotName.print( os );
}
bool_t _Tt_context::
xdr(
XDR *xdrs
)
{
return _slotName.xdr( xdrs );
}

View File

@@ -0,0 +1,49 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_context.h /main/3 1995/10/23 10:22:44 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_context.h 1.5 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_context.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
*
* _Tt_context is an object that represents a keyword.
*/
#ifndef _MP_CONTEXT_H
#define _MP_CONTEXT_H
#include <util/tt_object.h>
#include <util/tt_string.h>
#include <api/c/tt_c.h>
#include <rpc/rpc.h>
class _Tt_context : public _Tt_object {
public:
_Tt_context();
_Tt_context(const _Tt_context &);
virtual ~_Tt_context();
Tt_status setName(
const char *slotname
);
void print(
const _Tt_ostream &os
) const;
bool_t xdr(
XDR *xdrs
);
const _Tt_string &slotName() const { return _slotName; }
protected:
_Tt_string _slotName;
};
#endif /* _MP_CONTEXT_H */

View File

@@ -0,0 +1,60 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_context_utils.C /main/3 1995/10/23 10:22:52 rswiston $
/* -*-C++-*-
*
* @(#)mp_context_utils.C 1.4 @(#)
*
* Tool Talk Message Passer (MP) - mp_context_utils.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include <mp/mp_context.h>
#include <mp/mp_context_utils.h>
#include <stdio.h>
implement_list_of(_Tt_context)
// _Tt_context_list supports the append_ordered method. Contexts
// are ordered by slotname.
_Tt_context_list& _Tt_context_list::
append_ordered(const _Tt_context_ptr &e)
{
// Application programmers are either going to insert contexts in
// alphabetical order or at random. So we start at the end,
// find the last element less than the new one and insert after that.
// If an equal element is found, replace the old one with this one.
// No indication is returned if replacement is done; if you really care,
// check the count before and after to see if it changed.
_Tt_context_list_ptr this_ptr = this;
_Tt_context_list_cursor c(this_ptr);
while (c.prev()) {
int t= c->slotName().cmp(e->slotName());
if (t==0) {
// c->slotName == e->slotName
c.remove().insert(e);
return *this;
} else if (t<0) {
// c->slotName < e->slotName
// insert after here.
c.insert(e);
return *this;
} else {
// c->slotName > e->slotName
// this element greater than new one, look further.
}
}
// There are no elements in the list smaller than this one, so
// put the new one at the beginning.
push(e);
return *this;
}

View File

@@ -0,0 +1,20 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_context_utils.h /main/3 1995/10/23 10:22:59 rswiston $ */
/* @(#)mp_context_utils.h 1.2 @(#)
*
* mp_context_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_CONTEXT_UTILS_H
#define MP_CONTEXT_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
class _Tt_context;
declare_list_of(_Tt_context)
#endif /* MP_CONTEXT_UTILS_H */

View File

@@ -0,0 +1,492 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_desktop.C /main/7 1998/04/09 17:52:01 mgreess $
/*
*
* @(#)mp_desktop.C 1.34 93/09/07
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
//
// This file contains method for dealing with a "desktop" connection.
// Typically this desktop is an X11 session but this way the interface
// to the desktop is relatively free of Xisms allowing for more
// independence from X11 in the future.
//
#include "tt_options.h"
// Defining BSD_COMP gets us FIONREAD on SunOS 5.x, and shouldn\'t
// hurt in other places.
#define BSD_COMP
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#if defined(__STDC__) && !defined(linux)
extern "C" { extern int ioctl (int, int, ...) ; };
#endif
#include "util/tt_global_env.h"
#include "util/tt_ldpath.h"
#include "util/tt_host.h"
#include "util/tt_port.h"
#include "util/tt_Xlib.h"
#include "mp/mp_desktop.h"
#include "mp/mp_mp.h"
#include <unistd.h>
#include <malloc.h>
#include "util/tt_gettext.h"
static int parse_Xdisplay_string(_Tt_string display,
_Tt_string &host,
pid_t &svnum,
_Tt_string &hostname);
jmp_buf _Tt_desktop::io_exception;
// The following private class data is declared and allocated here
// so that everybody that includes mp_desktop.h doesn't have to
// also include X11/Xlib.h.
struct _Tt_desktop_private {
Display *xd;
};
_Tt_desktop::
_Tt_desktop()
{
priv = (_Tt_desktop_private *)malloc(sizeof(_Tt_desktop_private));
priv->xd = (Display *)0;
}
_Tt_desktop::
~_Tt_desktop()
{
// Ungrab the server, in case the user
// interrupted us during a grab.
unlock();
close();
free((MALLOCTYPE *)priv);
}
//
// Initializes a desktop object. This has the effect of connecting to the
// appropiate X11 server. "dt_handle" is a string identifying which
// desktop we want to talk to. For X11, this string will be the same as
// what would be specified in the DISPLAY variable.
//
int _Tt_desktop::
init(_Tt_string dt_handle, _Tt_dt_type /* t */)
{
char buf[32];
_Tt_string h, hostname;
pid_t s;
int parse_status;
int ret_val;
if (priv->xd != (Display *)0) {
return(1);
}
// initialize our access to Xlib
if (! _tt_load_xlib()) {
return(0);
}
_Tt_string display;
// parse the dt_handle string to extract the host and server
// number information.
parse_status = parse_Xdisplay_string(dt_handle, h, s, hostname);
// Now we examine the parse status to determine if this is a
// local host or remote host and if we should use a unix
// connection or not. We also enforce the use of screen 0 for
// all connections.
switch (parse_status) {
case 1: // non-local host
case 2: // local host
// important to always use screen 0 for the case where
// multiple displays are used.
sprintf(buf,":%d.0",s);
if (dt_handle[0] == ':') {
display = buf;
} else {
display = hostname.cat(buf);
}
break;
case 3: // local host and unix connection specified
sprintf(buf,"unix:%d.0", s);
display = buf;
break;
case 0:
_tt_syslog( 0, LOG_ERR,
catgets( _ttcatd, 1, 17,
"could not parse X display name: \"%s\"" ),
(char *)dt_handle );
return(0);
default:
break;
}
ret_val = 1;
int retries = 20;
set_error_handler(_Tt_desktop::io_error_proc);
if (0 == setjmp(io_exception)) {
// now connect to the indicated X11 server
while (retries--) {
if (priv->xd = (Display *)
CALLX11(XOpenDisplay)((char *)display)) {
// Xlib has already emitted diagnostic
break;
}
sleep(1);
}
if (!priv->xd) ret_val = 0;
} else {
ret_val = 0;
}
restore_user_handler();
return(ret_val);
}
// I/O error handler. Longjmp back to before the error occured.
int _Tt_desktop::
io_error_proc(void *)
{
longjmp(io_exception, 1);
return(0);
}
// Sets the error handler function which will get invoked on any I/O
// errors received from the X11 connection
void _Tt_desktop::
set_error_handler(_Tt_dt_errfn efn)
{
user_io_handler = (int *)
CALLX11(XSetIOErrorHandler)((XIOErrorHandler)efn);
}
// Restore the users I/O error handler.
void _Tt_desktop::
restore_user_handler()
{
CALLX11(XSetIOErrorHandler)((XIOErrorHandler)user_io_handler);
}
// Closes the connection to the X11 server.
int _Tt_desktop::
close()
{
int ret_val = 1;
set_error_handler(_Tt_desktop::io_error_proc);
if (0 == setjmp(io_exception)) {
// delete all properties set and close connection to desktop
if (priv->xd != (Display *)0) {
CALLX11(XCloseDisplay)(priv->xd);
}
} else {
ret_val = 0;
}
restore_user_handler();
return(ret_val);
}
// Returns the fd to poll on when new events come from the desktop
// connection.
int _Tt_desktop::
notify_fd()
{
return ConnectionNumber(priv->xd);
}
//
// Method to call when an event comes in from the desktop connection.
// This method will return 0 if the connection is broken indicating
// either a network partition or the X11 server going down.
//
int _Tt_desktop::
process_event()
{
XEvent xev;
XMappingEvent *xm;
int pending;
int iostat;
if (priv->xd == (Display *)0) {
return(0);
}
CALLX11(XFlush)(priv->xd);
xev.type = 0;
iostat=ioctl(notify_fd(), FIONREAD, (char *)&pending);
if (iostat == -1 || pending == 0) {
// X server went down
return(0);
}
if (priv->xd != (Display *)0) {
CALLX11(XNextEvent)(priv->xd, &xev);
if (xev.type == MappingNotify) {
xm = (XMappingEvent *)&xev;
CALLX11(XRefreshKeyboardMapping)(xm);
}
}
return(1);
}
int _Tt_desktop::
lock()
{
if (priv->xd != 0) {
CALLX11(XGrabServer)(priv->xd);
CALLX11(XFlush)(priv->xd);
}
return 1;
}
int _Tt_desktop::
unlock()
{
if (priv->xd != 0) {
CALLX11(XUngrabServer)(priv->xd);
CALLX11(XFlush)(priv->xd);
}
return 1;
}
//
// Sets the value of the indicated property name to val.
//
int _Tt_desktop::
set_prop(_Tt_string pname, _Tt_string &val)
{
Window rootw;
Atom patom;
char *v1;
const unsigned char *v;
if (priv->xd == (Display *)0) {
return(0);
}
patom = CALLX11(XInternAtom)(priv->xd, (char *)pname, False);
if (patom == None) {
return(0);
}
rootw = DefaultRootWindow(priv->xd);
v1 = (char *)val;
v = (const unsigned char *)v1;
CALLX11(XChangeProperty)(priv->xd, rootw,
patom, XA_STRING, 8,
PropModeReplace,
v, val.len());
CALLX11(XFlush)(priv->xd);
return(1);
}
//
// Deletes the indicated property from the desktop.
//
int _Tt_desktop::
del_prop(_Tt_string pname)
{
Window rootw;
Atom patom;
if (priv->xd == (Display *)0) {
return(0);
}
patom = CALLX11(XInternAtom)(priv->xd, (char *)pname, False);
if (patom == None) {
return(0);
}
rootw = DefaultRootWindow(priv->xd);
CALLX11(XDeleteProperty)(priv->xd, rootw, patom);
CALLX11(XFlush)(priv->xd);
return(1);
}
//
// Gets the value of the indicated property from the desktop.
//
int _Tt_desktop::
get_prop(_Tt_string pname, _Tt_string &pval)
{
Atom anatom;
int format;
/* X11 requires these to longs and not ints */
unsigned long items;
unsigned long left_to_read;
unsigned char *val = (unsigned char *)0;
Atom tt_xatom;
if (priv->xd == (Display *)0) {
return(0);
}
tt_xatom = CALLX11(XInternAtom)(priv->xd, (char *)pname, False);
if (tt_xatom == None) {
return(0);
}
CALLX11(XGetWindowProperty)(priv->xd, DefaultRootWindow(priv->xd),
tt_xatom,
0, 20, False, XA_STRING,
&anatom, &format, &items, &left_to_read,
&val);
if (val == (unsigned char *)0) {
return(0);
}
pval = (char *)val;
CALLX11(XFree)((caddr_t)val);
return(1);
}
//
// Parse a string in X11 "display" format and return the host and server
// number found. If parse errors occur return 0, else return 1 if the
// host is not the local host and 2 if the host is the local host. If the
// host is specified as "unix" which means use the local host with a Unix
// socket connection then return 3.
//
// XXX - the "hostname" paramater is an artifact of the fix for bug 1118012.
// if/when session IDs are re-worked to use only the process tree
// format internally, instead of the additional use of X session IDs,
// the parse_Xdisplay_string() function should be re-written to
// remove this.
//
static int
parse_Xdisplay_string(_Tt_string display, _Tt_string &host, pid_t &svnum,_Tt_string &hostname)
{
int status = 1;
int offset;
_Tt_host_ptr h;
_Tt_host_ptr localh;
char *dstr;
offset = display.index(':');
if (offset == -1) {
return(0);
}
if (offset == 0) {
// use local host
(void)_tt_global->get_local_host(h);
host = h->stringaddr();
hostname = h->name();
status = 2;
} else {
// Get the hostid portion of an X display of the
// format "hostid:X"
//
host = display.mid(0, offset);
if (host == "unix") {
(void)_tt_global->get_local_host(h);
host = h->stringaddr();
hostname = h->name();
status = 3;
} else {
if (! _tt_global->find_host_byname(host, h)) {
if (! _tt_global->find_host(host, h, 1)) {
return(0);
}
}
host = h->stringaddr();
hostname = h->name();
if (_tt_global->get_local_host(localh)) {
if (localh->stringaddr() == host) {
status = 2;
}
}
}
}
// now get the server number
dstr = (char *)display + offset + 1;
if (*dstr == ':') {
// ugh, a decnet connection
dstr++;
}
long long_svnum;
if (1 != sscanf(dstr, "%ld", &long_svnum)) {
svnum = (pid_t)long_svnum;
return(0);
} else {
svnum = (pid_t)long_svnum;
}
return(status);
}
//
// Returns a suitable name for this desktop session. Changing the value
// returned from this method should be done with care because it could
// compromise older versions of tooltalk clients/servers from
// communicating since a canonical name for a tooltalk desktop session
// contains the desktop session name in it and tooltalk session names
// indicate to clients how to contact the session.
//
_Tt_string _Tt_desktop::
session_name(_Tt_string dt_handle)
{
char cid[BUFSIZ];
_Tt_string h, hostname;
pid_t s;
_Tt_string name = (char *)0;
if (0==parse_Xdisplay_string(dt_handle, h, s, hostname)) {
return((char *)0);
}
sprintf(cid, "X %s %d", (char *)h, s);
name = cid;
return(name);
}
_Tt_desktop_lock::
_Tt_desktop_lock()
{
}
_Tt_desktop_lock::
_Tt_desktop_lock( const _Tt_desktop_ptr &dt )
{
_dt = dt;
if (! _dt.is_null()) {
_dt->lock();
}
}
_Tt_desktop_lock::
~_Tt_desktop_lock()
{
if (! _dt.is_null()) {
_dt->unlock();
}
}

View File

@@ -0,0 +1,73 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_desktop.h /main/3 1995/10/23 10:23:14 rswiston $ */
/*
* mp_desktop.h 1.6 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_desktop.h
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
#ifndef MP_DESKTOP_H
#define MP_DESKTOP_H
#include <setjmp.h>
#include <mp/mp_global.h>
#include <util/tt_object.h>
#if defined(ultrix)
extern "C"
{ extern struct XSizeHints;
extern struct XStandardColormap;
extern struct XTextProperty;
extern struct XWMHints;
extern struct XClassHint;
};
#endif
enum _Tt_dt_type {
_TT_DESKTOP_X11,
_TT_DESKTOP_LAST
};
typedef int (*_Tt_dt_errfn)(void *);
struct _Tt_desktop_private;
class _Tt_desktop : public _Tt_object {
public:
_Tt_desktop();
virtual ~_Tt_desktop();
int init(_Tt_string dt_handle, _Tt_dt_type t);
int notify_fd();
int process_event();
int lock();
int unlock();
int set_prop(_Tt_string pname, _Tt_string &val);
int del_prop(_Tt_string pname);
int get_prop(_Tt_string pname, _Tt_string &val);
_Tt_string session_name(_Tt_string dt_handle);
void set_error_handler(_Tt_dt_errfn efn);
private:
int close();
void restore_user_handler();
static int io_error_proc(void *);
int *user_io_handler;
static jmp_buf io_exception;
_Tt_desktop_private *priv;
};
#include <mp/mp_desktop_utils.h>
class _Tt_desktop_lock : public _Tt_object {
public:
_Tt_desktop_lock();
_Tt_desktop_lock( const _Tt_desktop_ptr &dt );
virtual ~_Tt_desktop_lock();
private:
_Tt_desktop_ptr _dt;
};
#endif /* MP_DESKTOP_H */

View File

@@ -0,0 +1,16 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_desktop_utils.C /main/3 1995/10/23 10:23:20 rswiston $
/*
*
* mp_desktop_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_desktop.h>
#include <mp/mp_desktop_utils.h>
implement_ptr_to(_Tt_desktop)
implement_ptr_to(_Tt_desktop_lock)

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_desktop_utils.h /main/3 1995/10/23 10:23:27 rswiston $ */
/*
*
* mp_desktop_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_DESKTOP_UTILS_H
#define MP_DESKTOP_UTILS_H
class _Tt_desktop;
declare_ptr_to(_Tt_desktop)
declare_ptr_to(_Tt_desktop_lock)
#endif /* MP_DESKTOP_UTILS_H */

118
cde/lib/tt/lib/mp/mp_file.C Normal file
View File

@@ -0,0 +1,118 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_file.C /main/3 1995/10/23 10:23:33 rswiston $
/*
*
* @(#)mp_file.C 1.40 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_file.cc
*
* Copyright (c) 1990, 1991, 1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_file class representing a document.
*/
#include <stdio.h>
#include <unistd.h>
#include "api/c/api_api.h"
#include "mp/mp_file.h"
#include "mp/mp_mp.h"
#include "util/tt_string.h"
#include "util/tt_xdr_version.h"
_Tt_qmsg_info::_Tt_qmsg_info()
{
categories = new _Tt_int_rec_list;
ptypes = new _Tt_string_list;
version = TT_QMSG_INFO_VERSION;
}
_Tt_qmsg_info::~_Tt_qmsg_info()
{
}
bool_t
_Tt_qmsg_info::xdr(
XDR *xdrs
)
{
_Tt_xdr_version xvers(1);
return xdr_int( xdrs, &version )
&& xdr_int( xdrs, &id )
&& xdr_int( xdrs, &nparts )
&& xdr_int( xdrs, &size )
&& categories.xdr( xdrs )
&& ptypes.xdr( xdrs )
&& xdr_int( xdrs, &m_id )
&& sender.xdr( xdrs );
}
_Tt_file::_Tt_file()
{
}
_Tt_file::_Tt_file(
const _Tt_string &path
) :
_Tt_db_file( path )
{
}
_Tt_file::~_Tt_file()
{
}
//
// query - iterate through each node in this file and apply the given filter
// to it. Returns one of the following codes:
// TT_OK - successful
// TT_ERR_DBAVAIL error occurred while accessing database
// TT_WRN_STOPPED filter returns TT_FILTER_STOP
// TT_ERR_INTERNAL
//
Tt_status
_Tt_file::query(
_Tt_file_callback callback,
Tt_filter_function filter,
void *context,
void *accumulator
)
{
// Apply 'filter' function to each node belonging to this
// file. If Filter returns FILTER_STOP then the query
// function should return immediately.
_Tt_string_list_ptr specIDs = getObjects();
_Tt_db_results dbStatus = getDBResults();
switch (dbStatus) { // XXX
case TT_DB_OK:
break;
case TT_DB_ERR_ILLEGAL_FILE:
default:
return TT_ERR_INTERNAL;
}
_Tt_string_list_cursor specID( specIDs );
while (specID.next()) {
if ( (*callback)( filter,
(*specID).quote_nulls(),
context,
accumulator)
== TT_FILTER_STOP)
{
return TT_WRN_STOPPED;
}
}
return TT_OK;
}
_Tt_string
_Tt_file::networkPath_(
_Tt_object_ptr &obj
)
{
return ((_Tt_file *)obj.c_pointer())->getNetworkPath();
}

View File

@@ -0,0 +1,66 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_file.h /main/3 1995/10/23 10:23:40 rswiston $ */
/*
* Tool Talk Message Passer (MP) - mp_file.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
*/
#ifndef _MP_FILE_H
#define _MP_FILE_H
#include <mp/mp_global.h>
#include <mp/mp_file_utils.h>
#include <mp/mp_procid_utils.h>
#include <mp/mp_message_utils.h>
#include <mp/mp_session_utils.h>
#include <db/tt_db_file.h>
#include <util/tt_int_rec.h>
#define TT_QMSG_INFO_VERSION 1
#define TT_FSCOPE_INFO_VERSION 1
typedef Tt_filter_action (*_Tt_file_callback)(
Tt_filter_function fn,
_Tt_string nodeid,
void *context,
void *accumulator
);
class _Tt_qmsg_info : public _Tt_object {
public:
_Tt_qmsg_info();
virtual ~_Tt_qmsg_info();
int id;
int nparts;
int size;
_Tt_int_rec_list_ptr categories;
_Tt_string_list_ptr ptypes;
bool_t xdr(XDR *xdrs);
int version;
int m_id; // message id
_Tt_string sender; // message sender procid
};
class _Tt_file : public _Tt_db_file {
public:
_Tt_file();
_Tt_file( const _Tt_string &path );
virtual ~_Tt_file();
Tt_status query(
_Tt_file_callback fn,
Tt_filter_function filter,
void *context,
void *accumulator
);
static _Tt_string networkPath_(
_Tt_object_ptr &obj
);
};
#endif /* _MP_FILE_H */

View File

@@ -0,0 +1,16 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_file_utils.C /main/3 1995/10/23 10:23:49 rswiston $
/*
*
* mp_file_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_file.h>
implement_list_of(_Tt_file)
implement_table_of(_Tt_file)
implement_ptr_to(_Tt_qmsg_info)

View File

@@ -0,0 +1,26 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_file_utils.h /main/3 1995/10/23 10:23:55 rswiston $ */
/*
*
* mp_file_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_file
*/
#ifndef MP_FILE_UTILS_H
#define MP_FILE_UTILS_H
#include <util/tt_object.h>
#include <util/tt_string.h>
#include <util/tt_list.h>
#include <util/tt_table.h>
class _Tt_file;
declare_list_of(_Tt_file)
declare_table_of(_Tt_file)
class _Tt_qmsg_info;
declare_ptr_to(_Tt_qmsg_info)
#endif /* MP_FILE_UTILS_H */

View File

@@ -0,0 +1,47 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_global.h /main/3 1995/10/23 10:24:02 rswiston $ */
/*
* mp.h -- public interface classes to the Message Passer
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef _MP_GLOBAL_H
#define _MP_GLOBAL_H
#include <stdio.h>
#include <string.h>
#include "util/tt_object.h"
#include "util/tt_list.h"
#include "util/tt_string.h"
#include "mp/mp_xdr_functions.h"
#include "api/c/tt_c.h"
#define _TT_TYPES_CE_VERSION 1
#define _TT_XATOM_VERSION 1
class _Tt_mp;
extern _Tt_mp *_tt_mp;
enum _Tt_mp_status {
_MP_OK = TT_OK,
_MP_ERR = TT_ERR_INTERNAL,
_MP_NO_NODE = TT_ERR_OBJID,
_MP_NO_VALUE = TT_ERR_NO_VALUE,
_MP_STALE_NODEID = TT_WRN_STALE_OBJID,
_MP_NODE_LOCKED = TT_STATUS_LAST + 1,
_MP_ERR_TYPE = TT_ERR_OTYPE,
_MP_ERR_DB = TT_ERR_DBAVAIL,
_MP_ERR_DBOPEN = TT_ERR_DBAVAIL,
_MP_ERR_ACCESS = TT_ERR_ACCESS
};
void dbg(char *fmt, char *f, int l, char *arg1 = (char *)0);
#define DBG(msg) (dbg(msg, __FILE__, __LINE__))
#define DBG1(fmt, arg1) (dbg(fmt, __FILE__, __LINE__, arg1))
#define TRACE(msg) ((_tt_mp->trace) || ((msg) && (msg)->trace))
#endif /* _MP_GLOBAL_H */

View File

@@ -0,0 +1,6 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_lock_utils.C /main/3 1995/10/23 10:24:09 rswiston $
/* this file is obsolete and should be removed when convenient */

View File

@@ -0,0 +1,6 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_lock_utils.h /main/3 1995/10/23 10:24:16 rswiston $ */
/* this file is obsolete and should be removed when convenient */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,256 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_message.h /main/3 1995/10/23 10:24:32 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_message.h 1.28 93/09/07
*
* Tool Talk Message Passer (MP) - mp_message.h
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* This file implements the _Tt_message object which represents the
* message that is being sent and received by a process. The message
* object in server mode implements the methods that are responsible for
* delivering the message. Thus this is the heart of the message server.
*/
#ifndef _MP_MESSAGE_H
#define _MP_MESSAGE_H
#include <sys/types.h>
#include "mp/mp_global.h"
#include "mp/mp_arg_utils.h"
#include "mp/mp_msg_context_utils.h"
#include "mp/mp_message_utils.h"
#include "mp/mp_pattern_utils.h"
#include "mp/mp_procid_utils.h"
#include "mp/mp_session_utils.h"
#include "util/tt_iostream.h"
/*
* The following enum defines bit masks used in xdr'ing a _Tt_message
* structure. Since there are important cases where less fields need
* to be transmitted (for example, whenever it is known that the
* recipient has seen the message before, the entire structure need
* not be transmitted) these bit fields control whether the relevant
* piece of the _Tt_message struct is xdr'ed or not. For example, if
* _TT_MSK_ID is off then the _id field of the _Tt_message isn't
* transmitted.
*/
enum _Tt_message_ptr_masks {
_TT_MSK_ID = (1<<0),
_TT_MSK_MESSAGE_CLASS = (1<<1),
_TT_MSK_STATE = (1<<2),
_TT_MSK_PARADIGM = (1<<3),
_TT_MSK_SCOPE = (1<<4),
_TT_MSK_RELIABILITY = (1<<5),
_TT_MSK_OPNUM = (1<<6),
_TT_MSK_UID = (1<<7),
_TT_MSK_GID = (1<<8),
_TT_MSK_STATUS = (1<<9),
_TT_MSK_FLAGS = (1<<10),
_TT_MSK_SESSION = (1<<11),
_TT_MSK_SENDER = (1<<12),
_TT_MSK_HANDLER = (1<<13),
_TT_MSK_FILE = (1<<14),
_TT_MSK_OBJECT = (1<<15),
_TT_MSK_OP = (1<<16),
_TT_MSK_ARGS = (1<<17),
_TT_MSK_OTYPE = (1<<18),
_TT_MSK_SENDER_PTYPE = (1<<19),
_TT_MSK_HANDLER_PTYPE = (1<<20),
_TT_MSK_PATTERN_ID = (1<<21),
_TT_MSK_RSESSIONS = (1<<22),
_TT_MSK_STATUS_STRING = (1<<23),
_TT_MSK_CONTEXTS = (1<<24),
_TT_MSK_OFFEREES = (1<<25)
};
#define SET_PTR_GUARD(test, msk)\
if (test) (_ptr_guards) |= msk; else (_ptr_guards) &= ~(msk)
#define SET_GUARD(guard, test, msk)\
if (test) (guard) |= msk; else (guard) &= ~(msk)
enum _Tt_message_flagbits {
_TT_MSG_IS_REMOTE, /* message sender not in current session */
_TT_MSG_OBSERVERS_ONLY, /* only attempt observer patterns */
_TT_MSG_IS_SUPER, /* method invocation to parent class */
_TT_MSG_UPDATE_XDR_MODE, /* message is being sent as an update */
/* (used by the xdr method) */
_TT_MSG_OBSERVERS_MATCH,
_TT_MSG_IS_START_MSG,
_TT_MSG_OBSERVER,
_TT_MSG_AWAITING_REPLY
};
class _Tt_message : public _Tt_object {
public:
void base_constructor();
_Tt_message();
virtual ~_Tt_message();
/* getting message fields */
Tt_class message_class() const {
return _message_class;
}
Tt_state state() const {
return _state;
}
Tt_scope scope() const {
return _scope;
}
int opnum() const {
return _opnum;
}
const _Tt_string &handler_ptype() const {
return _handler_ptype;
}
Tt_disposition reliability() const {
return _reliability;
}
Tt_address paradigm() const {
return _paradigm;
}
const _Tt_string &file() const {
return _file;
}
const _Tt_session_ptr &session() const {
return _session;
}
const _Tt_string &op() const {
return _op;
}
const _Tt_arg_list_ptr &args() const {
return _args;
}
_Tt_msg_context_ptr context(const char *slotname) const;
_Tt_msg_context_ptr context(int i) const;
int contextsCount() const;
const _Tt_string &object() const {
return _object;
}
const _Tt_string &otype() const {
return _otype;
}
const _Tt_procid_ptr &sender() const {
return _sender;
}
const _Tt_procid_ptr &handler() const {
return _handler;
}
const _Tt_procid_list_ptr &abstainers() const {
return _abstainers;
}
const _Tt_procid_list_ptr &accepters() const {
return _accepters;
}
const _Tt_procid_list_ptr &rejecters() const {
return _rejecters;
}
const _Tt_string &sender_ptype() const {
return _sender_ptype;
}
int queue() const {
return reliability() & TT_QUEUE;
}
int start() const {
return reliability() & TT_START;
}
int id() const;
const _Tt_string &api_id() const;
uid_t uid() const;
gid_t gid() const;
int status() const {
return _status;
}
_Tt_string &status_string();
/* setting message fields */
Tt_status set_message_class(Tt_class mclass);
Tt_status set_state(Tt_state state);
Tt_status set_paradigm(Tt_address p);
Tt_status set_scope(Tt_scope s);
Tt_status set_file(_Tt_string file);
Tt_status set_session(_Tt_session_ptr &s);
Tt_status set_session(_Tt_string sessid);
Tt_status set_op(_Tt_string op);
Tt_status set_opnum(int o);
Tt_status add_arg(_Tt_arg_ptr &arg);
Tt_status add_context(_Tt_msg_context_ptr &context);
Tt_status set_object(_Tt_string oid);
Tt_status set_otype(_Tt_string ot);
Tt_status set_sender(_Tt_procid_ptr &s);
Tt_status set_handler_procid(const _Tt_procid_ptr &h);
Tt_status unset_handler_procid(void);
Tt_status add_voter(const _Tt_procid_ptr &p,
Tt_state vote);
Tt_status add_accepter(const _Tt_procid_ptr &p);
Tt_status add_rejecter(const _Tt_procid_ptr &p);
Tt_status set_sender_ptype(_Tt_string s);
Tt_status set_handler_ptype(_Tt_string h);
Tt_status set_reliability(Tt_disposition r);
void set_super();
Tt_status set_status(int st);
Tt_status set_status_string(_Tt_string st);
void set_start_message(int flag = 1);
int is_start_message() const;
void set_awaiting_reply(int flag = 1);
int is_awaiting_reply() const;
void print(const _Tt_ostream &sink) const;
void update_message(const _Tt_message_ptr &m);
int is_equal(const _Tt_message_ptr &m);
void set_observer_procid(const _Tt_procid_ptr &h);
void clr_observer_procid();
int is_observer() {
return(_flags&(1<<_TT_MSG_OBSERVER));
}
bool_t xdr(XDR *xdrs);
_Tt_string &pattern_id();
void set_pattern_id(_Tt_string id);
Tt_status set_id();
protected:
void add_out_arg(_Tt_arg_ptr &arg);
_Tt_string _pattern_id;
Tt_state _state;
int _status;
Tt_address _paradigm;
Tt_scope _scope;
Tt_disposition _reliability;
int _opnum;
_Tt_string _object;
_Tt_string _file;
_Tt_string _op;
_Tt_string _otype;
_Tt_session_ptr _session;
_Tt_procid_ptr _sender;
_Tt_procid_ptr _handler;
_Tt_procid_list_ptr _abstainers;
_Tt_procid_list_ptr _accepters;
_Tt_procid_list_ptr _rejecters;
_Tt_string _sender_ptype;
_Tt_string _handler_ptype;
_Tt_string_list_ptr _rsessions;
int _id;
_Tt_string _api_id;
_Tt_arg_list_ptr _args;
_Tt_arg_list_ptr _out_args;
_Tt_msg_context_list_ptr _contexts;
int _flags;
int _ptr_guards;
uid_t _uid;
gid_t _gid;
int _full_msg_guards;
Tt_class _message_class;
_Tt_string _status_string;
private:
Tt_status _set_id(int id);
};
bool_t tt_xdr_message(XDR *xdrs, _Tt_message_ptr *msgp);
#endif /* _MP_MESSAGE_H */

View File

@@ -0,0 +1,14 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_message_utils.C /main/3 1995/10/23 10:24:39 rswiston $
/*
*
* mp_message_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_message.h>
implement_list_of(_Tt_message)

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_message_utils.h /main/3 1995/10/23 10:24:47 rswiston $ */
/*
*
* mp_message_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_message
*/
#ifndef MP_MESSAGE_UTILS_H
#define MP_MESSAGE_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
class _Tt_message;
declare_list_of(_Tt_message)
#endif /* MP_MESSAGE_UTILS_H */

293
cde/lib/tt/lib/mp/mp_mp.C Normal file
View File

@@ -0,0 +1,293 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_mp.C /main/7 1999/09/21 08:43:02 mgreess $
/*
*
* mp_mp.cc -- Server and client state object for the Message Passer
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
#include "mp/mp_global.h"
#include "mp/mp_mp.h"
#include "mp/mp_file.h"
#include "mp/mp_session.h"
#include "mp/mp_c_session.h"
#include "mp/mp_procid.h"
#include "mp/mp_rpc_client.h"
#include "mp/mp_xdr_functions.h"
#include "util/tt_base64.h"
#include "util/tt_port.h"
#include "util/tt_path.h"
#include "api/c/api_error.h"
#include <errno.h>
#include <sys/resource.h>
#include <malloc.h>
#include "tt_options.h"
#if defined(_AIX)
/* AIX's FD_ZERO macro uses bzero() without declaring it. */
#include <strings.h>
#endif
//
// This file contains methods for the _Tt_mp object which is an object
// whose only function is to serve as a placeholder for global
// data/objects relevant to the message-passer routines. Another major
// use is to hold the various object caches that map object ids to a
// single object of the given class.
//
// Really, the _Tt_mp object as we see it here should go away, being
// replaced by _Tt_c_mp, which should represent the client's idea
// of the ttsession server it's connected to, and _Tt_s_mp, which
// represents the global state of a ttsession server.
//
//
// Global pointer to *the* _Tt_mp object. There should only be one
// _Tt_mp object per tooltalk client.
//
_Tt_mp *_tt_mp = (_Tt_mp *)0;
//
// Constructs a _Tt_mp object in the indicated mode.
//
_Tt_mp::
_Tt_mp()
{
_flags = 0;
FD_ZERO(&_session_fds);
_session_cache = new _Tt_session_table(_tt_session_address);
active_messages = 0;
_current_message_id = _current_pattern_id = 0;
active_procs = new _Tt_procid_table(_tt_procid_id, 50);
}
_Tt_mp::
~_Tt_mp()
{
}
//
// Returns the value of a counter and then increments the counter. Used
// to make different messages sent by the same sender unique.
//
int _Tt_mp::
generate_message_id()
{
return(_current_message_id++);
}
//
// Returns the value of a counter and then increments the counter. Used
// to make different patterns registered by the same sender unique.
//
int _Tt_mp::
generate_pattern_id()
{
return(_current_pattern_id++);
}
//
// Finds the _Tt_file object associated with the network pathname <path>.
// Optionally creates the _Tt_file object. Returns:
// TT_OK but: if (! createIfNot), then fp.is_null() is possible
// TT_ERR_FILE
// TT_ERR_PATH
// TT_ERR_DBAVAIL
// TT_ERR_DBEXIST
// TT_ERR_INTERNAL can mean ENOMEM
//
Tt_status
_Tt_mp::find_file(
_Tt_string path,
_Tt_file_ptr &file,
int createIfNot
)
{
_Tt_string network_path;
if (_tt_is_network_path(path)) {
network_path = path;
}
else {
network_path = _Tt_db_file::getNetworkPath(path);
}
if (_file_cache.is_null()) {
if (!createIfNot) {
return TT_OK;
}
else {
_file_cache = new _Tt_file_table(_Tt_file::networkPath_);
if (_file_cache.is_null()) {
return TT_ERR_NOMEM;
}
}
}
else {
file = _file_cache->lookup( network_path );
if (! file.is_null()) {
return TT_OK;
}
}
// If we get to this point, the file is not in the cache
Tt_status status = TT_OK;
if (createIfNot) {
file = new _Tt_file( path );
if (file.is_null()) {
return TT_ERR_NOMEM;
}
_Tt_db_results dbStatus = file->getDBResults();
status = _tt_get_api_error( dbStatus, _TT_API_FILE );
if (status == TT_OK) {
_file_cache->insert( file );
} else if (status == TT_ERR_INTERNAL) {
_tt_syslog( 0, LOG_ERR,
"_Tt_db_file::_Tt_db_file(): %d", dbStatus);
}
}
return status;
}
void _Tt_mp::remove_file(_Tt_string path)
{
_Tt_string network_path = _Tt_db_file::getNetworkPath(path);
_file_cache->remove(network_path);
}
void _Tt_mp::
remove_session(_Tt_string id)
{
_session_cache->remove(id);
}
//
// Attempts to find the _Tt_session object associated with the given
// session id. If not found and create_ifnot is 1 then a new session is
// created and initialized. When it is initialized, the auto_start
// parameter is examined. If it is 1 then the new session will be
// initialized with the c_init method that will do an auto-start of the
// session if it isn't running. Otherwise, the "client_session_init"
// method is used which just tries to connect to a running session.
//
// Note that the server does use _Tt_c_session since servers can
// act as clients for one another when passing file scoped messages.
//
Tt_status _Tt_mp::
find_session(_Tt_string id, _Tt_session_ptr &sp,
int create_ifnot, int auto_start)
{
Tt_status result = TT_OK;
_Tt_session_ptr s;
if (_session_cache->lookup(id,s)) {
sp = s;
result = TT_OK;
} else {
// If this is a session address, try the X session ID
// XXX - this is a kludge to deal with X session
// IDs now that we use addres_strings as the lookup
// key. This should be removed if/when we expunge
// our internal use of X session IDs.
_Tt_session_table_cursor sc(_session_cache);
while (sc.next()) {
if (sc->has_id(id)) {
sp = *sc;
// Note: we return right here!
return TT_OK;
}
}
}
if (! create_ifnot || id.len() <= 0) {
result = TT_ERR_SESSION;
} else {
_Tt_c_session_ptr s = new _Tt_c_session();
result = s->set_id(id);
if (result != TT_OK) return result;
if (auto_start) result = s->c_init();
if (result != TT_OK) return result;
if (result == TT_OK) result = s->client_session_init();
if (result != TT_OK) return result;
_session_cache->insert(s);
sp = s;
result = TT_OK;
}
return result;
}
void _Tt_mp::
save_session_fd(int fd)
{
FD_SET(fd, &_session_fds);
}
int _Tt_mp::
find_session_by_fd(int fd, _Tt_session_ptr &sp)
{
_Tt_rpc_client_ptr rpc_client;
_Tt_session_table_cursor sc(_session_cache);
while (sc.next()) {
rpc_client = sc->_rpc_client;
if (rpc_client->socket() == fd) {
sp = *sc;
return(1);
}
}
return(0);
}
void _Tt_mp::
check_if_sessions_alive()
{
fd_set s_fds;
int fd, maxfds, n;
timeval tmout;
_Tt_session_ptr s;
_Tt_string id;
tmout.tv_sec = 0;
tmout.tv_usec = 0;
s_fds = _session_fds;
maxfds = _tt_getdtablesize();
n = select(maxfds, (fd_set *) 0, &s_fds, (fd_set *) 0, &tmout);
if (n < 0) {
return;
}
fd = 0;
while (n > 0) {
if (FD_ISSET(fd, &s_fds)) {
if (! find_session_by_fd(fd, s)) {
FD_CLR(fd, &_session_fds);
} else if (s->ping() != TT_OK) {
id = s->process_tree_id();
_tt_mp->remove_session(id);
FD_CLR(fd, &_session_fds);
}
n--;
}
fd++;
}
}

65
cde/lib/tt/lib/mp/mp_mp.h Normal file
View File

@@ -0,0 +1,65 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_mp.h /main/4 1999/09/17 18:29:12 mgreess $ */
/*
* mp_mp.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file implements the _Tt_mp object which represents the global
* information for the MP component. There should only be one instance of
* a _Tt_mp object in either server or client mode.
*/
#ifndef _MP_MP_H
#define _MP_MP_H
#include "tt_options.h"
#include "mp/mp_global.h"
#include "util/tt_table.h"
#include "mp/mp_file_utils.h"
#include "mp/mp_procid_utils.h"
#include "mp/mp_session_utils.h"
enum _Tt_mp_flags {
_TT_MP_IN_SERVER,
_TT_MP_INIT_DONE
};
class _Tt_mp : public _Tt_object {
public:
_Tt_mp();
virtual ~_Tt_mp();
int in_server() {
return(_flags&(1<<_TT_MP_IN_SERVER));
};
Tt_status find_file(_Tt_string path,
_Tt_file_ptr &f,
int create_ifnot);
void remove_file(_Tt_string path);
void remove_session(_Tt_string id);
void save_session_fd(int fd);
int find_session_by_fd(int fd, _Tt_session_ptr &sp);
void check_if_sessions_alive();
int generate_pattern_id(); int generate_message_id();
_Tt_session_ptr initial_session;
int active_messages;
Tt_status find_session(_Tt_string id,
_Tt_session_ptr &sp,
int create_ifnot,
int auto_start = 0);
_Tt_procid_table_ptr active_procs;
protected:
int _current_message_id;
int _current_pattern_id;
_Tt_file_table_ptr _file_cache;
_Tt_session_table_ptr _session_cache;
int _flags;
fd_set _session_fds;
};
#endif /* _MP_MP_H */

View File

@@ -0,0 +1,17 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_mp_utils.C /main/3 1995/10/23 10:25:08 rswiston $
/*
*
* mp_mp_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
/*
* #include <mp/mp.h>
*
* implement_ptr_to(_Tt_mp);
*
*/

View File

@@ -0,0 +1,114 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_msg_context.C /main/3 1995/10/23 10:25:15 rswiston $
/*
* @(#)mp_msg_context.C 1.14 94/11/17
*
* @(#)mp_msg_context.C 1.9 93/09/07
*
* Implementation of the _Tt_msg_context: a context slot in a message.
*/
#include "mp/mp_arg.h"
#include "mp/mp_msg_context.h"
#include "util/tt_iostream.h"
_Tt_msg_context::_Tt_msg_context()
{
_value = new _Tt_arg;
}
_Tt_msg_context::~_Tt_msg_context()
{
}
Tt_status
_Tt_msg_context::setValue(
const _Tt_string &value
)
{
_value->set_mode( TT_INOUT );
_value->set_type( "string" );
return _value->set_data_string( value );
}
Tt_status
_Tt_msg_context::setValue(
int value
)
{
_value->set_mode( TT_INOUT );
_value->set_type( "integer" );
return _value->set_data_int( value );
}
int
_Tt_msg_context::isEnvEntry() const
{
if (_slotName.len() == 0) {
return 0;
}
return _slotName[0] == '$';
}
_Tt_string
_Tt_msg_context::enVarName() const
{
_Tt_string name( ((char *)_slotName)+1 );
return name;
}
_Tt_string
_Tt_msg_context::stringRep() const
{
_Tt_string rep;
char temp[ 20 ];
switch (_value->data_type()) {
case _Tt_arg::UNSET:
break;
case _Tt_arg::STRING:
rep = _value->data_string();
break;
case _Tt_arg::INT:
sprintf( temp, "%d", _value->data_int());
rep = temp;
break;
}
return rep;
}
void
_Tt_msg_context::print(
const _Tt_ostream &os
) const
{
_Tt_context::print( os );
os << ": ";
if (!_value.is_null()) {
_value->print( os );
} else {
os << "\n";
}
}
void
_Tt_msg_context::print_(
const _Tt_ostream &os,
const _Tt_object *obj
)
{
((_Tt_msg_context *)obj)->print( os );
}
bool_t
_Tt_msg_context::xdr(
XDR *xdrs
)
{
if (! _Tt_context::xdr( xdrs )) {
return 0;
}
return _value.xdr( xdrs );
}

View File

@@ -0,0 +1,57 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_msg_context.h /main/3 1995/10/23 10:25:23 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_msg_context.h 1.6 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_msg_context.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* _Tt_msg_context is a context slot in a message.
*/
#ifndef _MP_MSG_CONTEXT_H
#define _MP_MSG_CONTEXT_H
#include <mp/mp_context.h>
#include <mp/mp_msg_context_utils.h>
#include <mp/mp_arg_utils.h>
#include <rpc/rpc.h>
class _Tt_msg_context : public _Tt_context {
public:
_Tt_msg_context();
virtual ~_Tt_msg_context();
Tt_status setValue(
const _Tt_string &value
);
Tt_status setValue(
int value
);
int isEnvEntry() const;
_Tt_string enVarName() const;
_Tt_string stringRep() const;
void print(
const _Tt_ostream &os
) const;
static void print_(
const _Tt_ostream &os,
const _Tt_object *obj
);
bool_t xdr(
XDR *xdrs
);
const _Tt_arg &value() const {return *_value;}
private:
_Tt_arg_ptr _value;
};
#endif /* _MP_MSG_CONTEXT_H */

View File

@@ -0,0 +1,26 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_msg_context_utils.C /main/3 1995/10/23 10:25:31 rswiston $
/* -*-C++-*-
*
* @(#)mp_msg_context_utils.C 1.5 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_msg_context_utils.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include <mp/mp_msg_context.h>
#include <mp/mp_context_utils.h>
#include <mp/mp_msg_context_utils.h>
implement_list_of(_Tt_msg_context)
_Tt_msg_context_list & _Tt_msg_context_list::
append_ordered(const _Tt_msg_context_ptr &e)
{
return (_Tt_msg_context_list &)this->_Tt_context_list::append_ordered(e);
}

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_msg_context_utils.h /main/3 1995/10/23 10:25:39 rswiston $ */
/*
*
* mp_msg_context_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_MSG_CONTEXT_UTILS_H
#define MP_MSG_CONTEXT_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
#include <mp/mp_context_utils.h>
class _Tt_msg_context;
declare_derived_list_of(_Tt_msg_context,_Tt_context)
#endif /* MP_MSG_CONTEXT_UTILS_H */

View File

@@ -0,0 +1,6 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_node.C /main/3 1995/10/23 10:25:47 rswiston $
/* This file is obsolete and should be removed when convenient */

View File

@@ -0,0 +1,6 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_node.h /main/3 1995/10/23 10:25:55 rswiston $ */
/* This file is obsolete and should be removed when convenient */

View File

@@ -0,0 +1,6 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_node_utils.C /main/3 1995/10/23 10:26:02 rswiston $
/* this file is obsolete and should be removed when convenient */

View File

@@ -0,0 +1,6 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_node_utils.h /main/3 1995/10/23 10:26:10 rswiston $ */
/* this file is obsolete and should be removed when convenient */

View File

@@ -0,0 +1,137 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_pat_context.C /main/3 1995/10/23 10:26:16 rswiston $
/*
*
* @(#)mp_pat_context.C 1.9 93/09/07
*
* Tool Talk Pattern Passer (MP) - mp_pat_context.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_pat_context: a context slot in a pattern.
*/
#include "mp/mp_arg.h"
#include "mp/mp_msg_context.h"
#include "mp/mp_pat_context.h"
#include "util/tt_iostream.h"
_Tt_pat_context::
_Tt_pat_context()
{
_values = new _Tt_arg_list;
}
_Tt_pat_context::
_Tt_pat_context(const _Tt_context &c) : _Tt_context(c)
{
_values = new _Tt_arg_list;
}
_Tt_pat_context::
~_Tt_pat_context()
{
}
Tt_status _Tt_pat_context::
addValue(
const _Tt_string &value
)
{
_Tt_arg_ptr newVal = new _Tt_arg( TT_INOUT, "string" );
if (newVal.is_null()) {
return TT_ERR_NOMEM;
}
Tt_status status = newVal->set_data_string( value );
if (status != TT_OK) {
return status;
}
_values->append( newVal );
return TT_OK;
}
Tt_status _Tt_pat_context::
addValue(
int value
)
{
_Tt_arg_ptr newVal = new _Tt_arg( TT_INOUT, "integer" );
if (newVal.is_null()) {
return TT_ERR_NOMEM;
}
Tt_status status = newVal->set_data_int( value );
if (status != TT_OK) {
return status;
}
_values->append( newVal );
return TT_OK;
}
Tt_status _Tt_pat_context::
addValue(
const _Tt_msg_context &msgCntxt
)
{
_Tt_arg_ptr newVal = new _Tt_arg( msgCntxt.value() );
if (newVal.is_null()) {
return TT_ERR_NOMEM;
}
_values->append( newVal );
return TT_OK;
}
Tt_status _Tt_pat_context::
deleteValue(
const _Tt_msg_context &msgCntxt
)
{
_Tt_arg_list_cursor argC( _values );
while (argC.next()) {
if (msgCntxt.value() == **argC) {
argC.remove();
return TT_OK;
}
}
return TT_WRN_NOTFOUND;
}
void _Tt_pat_context::
print(
const _Tt_ostream &os
) const
{
_Tt_context::print( os );
os << ":\n";
if (! _values.is_null()) {
_Tt_string indent = os.indent();
os.set_indent( indent.cat( "\t" ));
_Tt_arg_list_cursor argC( _values );
while (argC.next()) {
argC->print( os );
}
os.set_indent( indent );
}
}
void _Tt_pat_context::
print_(
const _Tt_ostream &os,
const _Tt_object *obj
)
{
((_Tt_pat_context *)obj)->print( os );
}
bool_t _Tt_pat_context::
xdr(
XDR *xdrs
)
{
if (! _Tt_context::xdr( xdrs )) {
return 0;
}
return _values.xdr( xdrs );
}

View File

@@ -0,0 +1,60 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_pat_context.h /main/3 1995/10/23 10:26:23 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_pat_context.h 1.4 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_pat_context.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* _Tt_pat_context is a context slot in a pattern.
*/
#ifndef _MP_PAT_CONTEXT_H
#define _MP_PAT_CONTEXT_H
#include <mp/mp_context.h>
#include <mp/mp_pat_context_utils.h>
#include <mp/mp_msg_context.h>
#include <mp/mp_arg_utils.h>
#include <rpc/rpc.h>
class _Tt_pat_context : public _Tt_context {
public:
_Tt_pat_context();
_Tt_pat_context(const _Tt_context &);
virtual ~_Tt_pat_context();
Tt_status addValue(
const _Tt_string &value
);
Tt_status addValue(
int value
);
Tt_status addValue(
const _Tt_msg_context &msgCntxt
);
Tt_status deleteValue(
const _Tt_msg_context &msgCntxt
);
void print(
const _Tt_ostream &os
) const;
static void print_(
const _Tt_ostream &os,
const _Tt_object *obj
);
bool_t xdr(
XDR *xdrs
);
protected:
_Tt_arg_list_ptr _values;
};
#endif /* _MP_PAT_CONTEXT_H */

View File

@@ -0,0 +1,26 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_pat_context_utils.C /main/3 1995/10/23 10:26:29 rswiston $
/* -*-C++-*-
*
* @(#)mp_pat_context_utils.C 1.4 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_pat_context_utils.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include <mp/mp_pat_context.h>
#include <mp/mp_context_utils.h>
#include <mp/mp_pat_context_utils.h>
implement_list_of(_Tt_pat_context)
_Tt_pat_context_list & _Tt_pat_context_list::
append_ordered(const _Tt_pat_context_ptr &e)
{
return (_Tt_pat_context_list &)this->_Tt_context_list::append_ordered(e);
}

View File

@@ -0,0 +1,27 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_pat_context_utils.h /main/3 1995/10/23 10:26:36 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_pat_context_utils.h 1.4 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_pat_context_utils.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*
* _Tt_pat_context is a context slot in a pattern.
*/
#ifndef MP_PAT_CONTEXT_UTILS_H
#define MP_PAT_CONTEXT_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
#include <mp/mp_context_utils.h>
class _Tt_pat_context;
declare_derived_list_of(_Tt_pat_context,_Tt_context)
#endif /* MP_PAT_CONTEXT_UTILS_H */

View File

@@ -0,0 +1,459 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_pattern.C /main/5 1999/10/14 18:48:24 mgreess $
/*
*
* @(#)mp_pattern.C 1.28 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_pattern.cc
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
#include "api/c/api_spec_map_ref.h"
#include "mp/mp_global.h"
#include "mp/mp_arg.h"
#include "mp/mp_pat_context.h"
#include "mp/mp_mp.h"
#include "mp/mp_pattern.h"
#include "mp/mp_message.h"
#include "mp/mp_session.h"
#include "mp/mp_xdr_functions.h"
#include "util/tt_enumname.h"
#include "util/tt_global_env.h"
#include "util/tt_port.h"
//
// Base constructor for _Tt_pattern objects. Should be called by all
// other _Tt_pattern constructors.
//
void _Tt_pattern::
base_constructor()
{
server_callback = 0;
_category = TT_CATEGORY_LAST;
_classes = 0;
_paradigms = 0;
_reliabilities = 0;
_scopes = 0;
_states = 0;
_files = new _Tt_string_list();
_handler_ptypes = new _Tt_string_list();
_handlers = new _Tt_string_list();
_objects = new _Tt_string_list();
_observer_ptypes = new _Tt_string_list();
_opnums = new _Tt_int_rec_list();
_ops = new _Tt_string_list();
_args = new _Tt_arg_list();
_contexts = new _Tt_pat_context_list;
_otypes = new _Tt_string_list();
_sender_ptypes = new _Tt_string_list();
_senders = new _Tt_string_list();
_sessions = new _Tt_string_list();
_flags = 0;
}
_Tt_pattern::
~_Tt_pattern()
{
}
//
// Deletes the given argument from the _files field of this object.
//
Tt_status _Tt_pattern::
del_file(const _Tt_string &f)
{
_Tt_string_list_cursor fcursor(_files);
while (fcursor.next()) {
if (*fcursor == f) {
fcursor.remove();
}
}
return(TT_OK);
}
//
// Deletes the given argument from the _sessions field of this object.
//
Tt_status _Tt_pattern::
del_session(const _Tt_string &s)
{
_Tt_string_list_cursor scursor(_sessions);
while (scursor.next()) {
if (*scursor == s) {
scursor.remove();
}
}
return(TT_OK);
}
//
// Adds the given object id to the _objects field. Will return
// TT_WRN_STALE_OBJID if the oid is a stale object id.
//
Tt_status _Tt_pattern::
add_object(const _Tt_string &oid)
{
_Tt_api_spec_map_ref spec_map;
_Tt_objid_spec_ptr spec = spec_map.getSpec(oid);
Tt_status status;
if (spec.is_null()) {
return(TT_ERR_OBJID);
}
switch (spec->getDBResults()) {
case TT_DB_OK:
status = TT_OK;
break;
case TT_DB_WRN_FORWARD_POINTER:
status = TT_WRN_STALE_OBJID;
break;
default:
return(TT_ERR_OBJID);
}
add_field(oid, _objects);
return(status);
}
//
// Generic function for adding an integer to a _Tt_int_rec_list if it
// isn't already there.
//
void _Tt_pattern::
add_field(int v, _Tt_int_rec_list_ptr &vlist)
{
_Tt_int_rec_list_cursor c(vlist);
while (c.next()) {
if (c->val == v) {
return;
}
}
vlist->push(new _Tt_int_rec((int)v));
}
//
// Generic function for adding a string to a _Tt_string_list if it
// isn't already there.
//
void _Tt_pattern::
add_field(const _Tt_string &v, _Tt_string_list_ptr &vlist)
{
_Tt_string_list_cursor c(vlist);
while (c.next()) {
if (*c == v) {
return;
}
}
vlist->push(v);
}
_Tt_pat_context_ptr _Tt_pattern::
context(const char *slotname) const
{
_Tt_pat_context_list_cursor contextC( _contexts );
while (contextC.next()) {
if (contextC->slotName() == slotname) {
return *contextC;
}
}
return 0;
}
_Tt_pat_context_ptr _Tt_pattern::
context(int i) const
{
if ((i >= 0) && (i < _contexts->count())) {
return (*_contexts)[ i ];
}
return 0;
}
int _Tt_pattern::
contextsCount() const
{
if (_contexts.is_null()) {
return 0;
}
return _contexts->count();
}
Tt_status
_Tt_pattern::add_netfile(
const _Tt_string &filepath,
int fallback_2_local_netfile
)
{
_Tt_string abspath;
Tt_status status = TT_OK;
int __scopes = scopes();
if ((__scopes&(1<<TT_FILE)) || (__scopes&(1<<TT_BOTH))) {
abspath = _Tt_db_file::getNetworkPath(filepath);
if ((abspath.len() == 0) && (! fallback_2_local_netfile)) {
return TT_ERR_FILE;
}
}
if (abspath.len() == 0) {
abspath = _tt_local_network_path(filepath);
if (abspath.len() == 0) {
return TT_ERR_FILE;
}
}
return(add_file(abspath));
}
//
// XDR encodes/decodes a pattern.
//
bool_t _Tt_pattern::
xdr(XDR *xdrs)
{
if (! tt_xdr_string(xdrs, &_pattern_id)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_category)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_classes)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_states)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_paradigms)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_scopes)) {
return(0);
}
if (! xdr_int(xdrs, (int *)&_reliabilities)) {
return(0);
}
if (! _files.xdr(xdrs)) {
return(0);
}
if (! _sessions.xdr(xdrs)) {
return(0);
}
if (! _ops.xdr(xdrs)) {
return(0);
}
if (! _opnums.xdr(xdrs)) {
return(0);
}
if (! _objects.xdr(xdrs)) {
return(0);
}
if (! _otypes.xdr(xdrs)) {
return(0);
}
if (! _senders.xdr(xdrs)) {
return(0);
}
if (! _handlers.xdr(xdrs)) {
return(0);
}
if (! _sender_ptypes.xdr(xdrs)) {
return(0);
}
if (! _handler_ptypes.xdr(xdrs)) {
return(0);
}
if (! _args.xdr(xdrs)) {
return(0);
}
if (_tt_global->xdr_version() >= TT_CONTEXTS_XDR_VERSION) {
if (! _contexts.xdr(xdrs)) {
return(0);
}
}
return(1);
}
//
// Function wrapper so that the xdr method for a pattern can be invoked
// from the C RPC interface.
//
bool_t tt_xdr_pattern(XDR *xdrs, _Tt_pattern_ptr *pat)
{
return((*pat)->xdr(xdrs));
}
//
// methods and functions associated with printing patterns
//
static const char *
int_to_class(int r)
{
return(_tt_enumname((Tt_class)r));
}
static const char *
int_to_paradigm(int r)
{
return(_tt_enumname((Tt_address) r));
}
static const char *
int_to_state(int r)
{
return(_tt_enumname((Tt_state) r));
}
static const char *
int_to_scope(int r)
{
return(_tt_enumname((Tt_scope) r));
}
//
// Used to print out a generic list of integers. The given conversion
// function ppfn returns an appropiate string to print for each integer.
// See all the int_to_* functions above.
//
static void
print_enum_mask(const _Tt_ostream &os, int start, int end, int mask,
const char *(*ppfn)(int a))
{
int i;
for (i=start;i <= end;i++) {
if (mask&(1<<i)) {
os << (*ppfn)(i) << " ";
}
}
}
//
// Used by the generic list and table packages to print out elements.
// Should not be used otherwise.
//
void
_tt_int_rec_print(const _Tt_ostream &os, const _Tt_object *obj)
{
((_Tt_int_rec *)obj)->print(os);
}
//
// Prints out a pattern object. Used for debugging and for printing out
// patterns being considered when tracing is turned on.
//
void _Tt_pattern::
print(const _Tt_ostream &os) const
{
os << "id:\t\t";
os << _pattern_id << "\n";
os << "category:\t" << _tt_enumname(_category) << "\n";
if (_classes != 0) {
os << "classes:\t";
print_enum_mask(os,(int)TT_CLASS_UNDEFINED,(int)TT_CLASS_LAST,
_classes, int_to_class);
os << "\n";
}
if (_states != 0) {
os << "states:\t\t";
print_enum_mask(os,(int)TT_CREATED, (int)TT_STATE_LAST,
_states, int_to_state);
os << "\n";
}
if (_paradigms != 0) {
os << "addresses:\t";
print_enum_mask(os,(int)TT_PROCEDURE,(int)TT_HANDLER,
_paradigms, int_to_paradigm);
os << "\n";
}
if (_scopes != 0) {
os << "scopes:\t\t";
print_enum_mask(os,(int)TT_SCOPE_NONE,(int)TT_FILE_IN_SESSION,
_scopes, int_to_scope);
os << "\n";
}
if (_files->count()) {
os << "files:\t\t";
_files->print(_tt_string_print, os);
os << "\n";
}
if (_sessions->count()) {
os << "sessions:\t";
_sessions->print(_tt_string_print, os);
os << "\n";
}
if (_ops->count()) {
os << "ops:\t\t";
_ops->print(_tt_string_print, os);
os << "\n";
}
if (_args->count()) {
os << "args:\n";
_Tt_string indent = os.indent();
os.set_indent( indent.cat( "\t" ));
_Tt_arg_list_cursor argC( _args );
while (argC.next()) {
argC->print( os );
}
os.set_indent( indent );
}
if (_contexts->count()) {
os << "contexts:\n";
_Tt_string indent = os.indent();
os.set_indent( indent.cat( "\t" ));
_Tt_pat_context_list_cursor contextC( _contexts );
while (contextC.next()) {
contextC->print( os );
}
os.set_indent( indent );
}
if (_opnums->count()) {
os << "opnums:\t";
_opnums->print(_tt_int_rec_print, os);
os << "\n";
}
if (_otypes->count()) {
os << "otypes:\t";
_otypes->print(_tt_string_print, os);
os << "\n";
}
if (_senders->count()) {
os << "senders:\t";
_senders->print(_tt_string_print, os);
os << "\n";
}
if (_handlers->count()) {
os << "handlers:\t";
_handlers->print(_tt_string_print, os);
os << "\n";
}
if (_sender_ptypes->count()) {
os << "sender_ptypes:\t";
_sender_ptypes->print(_tt_string_print, os);
os << "\n";
}
if (_handler_ptypes->count()) {
os << "handler_ptypes:\t";
_handler_ptypes->print(_tt_string_print, os);
os << "\n";
}
}

View File

@@ -0,0 +1,175 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_pattern.h /main/3 1995/10/23 10:26:51 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_pattern.h 1.15 30 Jul 1993
*
* Tool Talk Message Passer (MP) - mp_pattern.h
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* This file implements the _Tt_pattern object which represents the
* pattern that a process can register in order to receive messages. The
* fundamental method on a _Tt_pattern object add and return pattern
* fields and match a pattern to a message.
*/
#ifndef _MP_PATTERN_H
#define _MP_PATTERN_H
#include <mp/mp_global.h>
#include <mp/mp_message.h>
#include <mp/mp_pat_context_utils.h>
#include <mp/mp_pattern_utils.h>
#include <mp/mp_mp.h>
#include <mp/mp_xdr_functions.h>
#include <mp/mp_procid.h>
#include <util/tt_int_rec.h>
typedef Tt_callback_action (*_Tt_server_callback)(
const _Tt_message_ptr &msg,
void *server_data
);
enum _Tt_pattern_flags {
_TT_PATTERN_IS_REGISTERED,
_TT_PATTERN_IN_SESSION
};
class _Tt_pattern : public _Tt_object {
public:
void base_constructor();
_Tt_pattern();
virtual ~_Tt_pattern();
Tt_category category() const;
Tt_status set_category(Tt_category c);
void set_procid(const _Tt_procid_ptr &pid);
int classes() const;
int states() const;
int paradigms() const;
int scopes() const;
int reliabilities() const;
const _Tt_string_list_ptr &files() const;
const _Tt_string_list_ptr &sessions() const;
const _Tt_string_list_ptr &ops() const;
const _Tt_int_rec_list_ptr &opnums() const;
const _Tt_string_list_ptr &objects() const;
const _Tt_string_list_ptr &otypes() const;
const _Tt_string_list_ptr &senders() const;
const _Tt_string_list_ptr &handlers() const;
const _Tt_string_list_ptr &sender_ptypes() const;
const _Tt_string_list_ptr &handler_ptypes() const;
const _Tt_arg_list_ptr &args() const;
_Tt_pat_context_ptr context(const char *slotname) const;
_Tt_pat_context_ptr context(int i) const;
int contextsCount() const;
Tt_status add_message_class(Tt_class mclass);
Tt_status add_paradigm(Tt_address p);
Tt_status add_scope(Tt_scope s);
Tt_status add_file(const _Tt_string &file);
Tt_status add_netfile(
const _Tt_string &file,
int fallback_2_local_netfile = 0
);
Tt_status del_file(const _Tt_string &file);
Tt_status add_session(const _Tt_string &s);
Tt_status del_session(const _Tt_string &s);
Tt_status add_op(const _Tt_string &op);
Tt_status add_opnum(int o);
Tt_status add_object(const _Tt_string &oid);
Tt_status add_otype(const _Tt_string &ot);
Tt_status add_sender(const _Tt_string &s);
Tt_status add_handler(const _Tt_string &h);
Tt_status add_sender_ptype(const _Tt_string &s);
Tt_status add_state(Tt_state s);
Tt_status add_handler_ptype(const _Tt_string &h);
Tt_status add_observer_ptype(const _Tt_string &o);
Tt_status add_reliability(Tt_disposition r);
Tt_status add_arg(const _Tt_arg_ptr &arg);
Tt_status add_context(
const _Tt_pat_context_ptr &context);
bool_t xdr(XDR *xdrs);
void set_id(const _Tt_string &sender);
_Tt_string id() const;
const _Tt_procid_ptr &procid() const;
_Tt_string &sender();
int is_registered() const;
void set_registered();
void clr_registered();
void set_in_session();
void clr_in_session();
int in_session() const;
Tt_status join_files(const _Tt_string &sessID) const;
void print(const _Tt_ostream &os) const;
_Tt_server_callback server_callback;
protected:
// convenience methods to add values to integer list and
// string list fields. (see comment below for a description of
// the different types of pattern fields.
void add_field(int val,
_Tt_int_rec_list_ptr &vlist);
void add_field(const _Tt_string &val,
_Tt_string_list_ptr &vlist);
// procid that registered this pattern
_Tt_procid_ptr _procid;
// id of this pattern. For dynamic patterns, ids are relative
// to the procid that registered the pattern. For patterns
// generated from signatures, patterns are relative to the
// current session. In either case, pattern ids are unique
// among all patterns in a session (and BAD things happen if this
// isn't the case.)
_Tt_string _pattern_id;
// bit vector of _Tt_pattern_flags that are on or off for this
// object.
int _flags;
// pattern fields. There are three kinds of fields in a
// pattern. The simplest of these are string fields which are
// just lists of strings. Then there are integer lists (only
// opums). Finally, there are fields which represent
// collections of enum values. For example _classes is
// conceptually a list of Tt_class enums. For these fields we
// optimize storage as well as matching by representing them
// as integers such that if enum value x is in the list then
// <pfield>&(1<<x) is true where pfield is the given pattern
// field. This means matching on these fields is fast and they
// take up less space (much less than a real list of integers).
//
// The drawback is that enums with more than 32 members or
// enums where each member is assigned a number > 32 aren't
// supported.
Tt_category _category;
int _classes;
int _paradigms;
int _reliabilities;
int _scopes;
int _states;
_Tt_int_rec_list_ptr _opnums;
_Tt_arg_list_ptr _args;
_Tt_pat_context_list_ptr _contexts;
_Tt_string_list_ptr _files;
_Tt_string_list_ptr _handler_ptypes;
_Tt_string_list_ptr _handlers;
_Tt_string_list_ptr _objects;
_Tt_string_list_ptr _observer_ptypes;
_Tt_string_list_ptr _ops;
_Tt_string_list_ptr _otypes;
_Tt_string_list_ptr _sender_ptypes;
_Tt_string_list_ptr _senders;
_Tt_string_list_ptr _sessions;
friend class _Tt_mp;
friend class _Tt_message;
};
#include <mp/mp_pattern_inlines.h>
bool_t tt_xdr_pattern(XDR *xdrs, _Tt_pattern_ptr *pat);
#endif /* _MP_PATTERN_H */

View File

@@ -0,0 +1,292 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_pattern_inlines.h /main/3 1995/10/23 10:26:59 rswiston $ */
/* -*-C++-*-
*
* @(#)mp_pattern_inlines.h 1.6 30 Jul 1993
*
* mp_pattern_inlines.h
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*/
// inline functions definitions for selected _Tt_pattern methods.
inline Tt_category _Tt_pattern::
category() const
{
return _category;
}
inline Tt_status _Tt_pattern::
set_category(Tt_category c)
{
_category = c;
return(TT_OK);
}
inline void _Tt_pattern::
set_procid(const _Tt_procid_ptr &pid)
{
_procid = pid;
}
inline int _Tt_pattern::
classes() const
{
return _classes;
}
inline int _Tt_pattern::
states() const
{
return _states;
}
inline int _Tt_pattern::
paradigms() const
{
return _paradigms;
}
inline int _Tt_pattern::
scopes() const
{
return _scopes;
}
inline int _Tt_pattern::
reliabilities() const
{
return _reliabilities;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
files() const
{
return _files;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
sessions() const
{
return _sessions;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
ops() const
{
return _ops;
}
inline const _Tt_int_rec_list_ptr & _Tt_pattern::
opnums() const
{
return _opnums;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
objects() const
{
return _objects;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
otypes() const
{
return _otypes;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
senders() const
{
return _senders;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
handlers() const
{
return _handlers;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
sender_ptypes() const
{
return _sender_ptypes;
}
inline const _Tt_string_list_ptr & _Tt_pattern::
handler_ptypes() const
{
return _handler_ptypes;
}
inline const _Tt_arg_list_ptr & _Tt_pattern::
args() const
{
return _args;
}
inline Tt_status _Tt_pattern::
add_message_class(Tt_class mclass)
{
_classes |= (1<<mclass);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_paradigm(Tt_address p)
{
_paradigms |= (1<<p);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_scope(Tt_scope s)
{
_scopes |= (1<<s);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_file(const _Tt_string &file)
{
add_field(file, _files);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_session(const _Tt_string &s)
{
add_field(s, _sessions);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_op(const _Tt_string &op)
{
add_field(op, _ops);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_opnum(int o)
{
add_field(o, _opnums);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_otype(const _Tt_string &ot)
{
add_field(ot, _otypes);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_sender(const _Tt_string &s)
{
add_field(s, _senders);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_handler(const _Tt_string &h)
{
add_field(h, _handlers);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_sender_ptype(const _Tt_string &s)
{
add_field(s, _sender_ptypes);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_state(Tt_state s)
{
_states |= (1<<s);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_handler_ptype(const _Tt_string &h)
{
add_field(h, _handler_ptypes);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_reliability(Tt_disposition r)
{
_reliabilities |= (1<<r);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_arg(const _Tt_arg_ptr &arg)
{
_args->append(arg);
return(TT_OK);
}
inline Tt_status _Tt_pattern::
add_context(const _Tt_pat_context_ptr &context)
{
_contexts->append_ordered(context);
return(TT_OK);
}
inline _Tt_string _Tt_pattern::
id() const
{
return _pattern_id;
}
inline const _Tt_procid_ptr & _Tt_pattern::
procid() const
{
return _procid;
}
inline int _Tt_pattern::
is_registered() const
{
return _flags&(1<<_TT_PATTERN_IS_REGISTERED);
}
inline void _Tt_pattern::
set_registered()
{
_flags |= (1<<_TT_PATTERN_IS_REGISTERED);
}
inline void _Tt_pattern::
clr_registered()
{
_flags &= ~(1<<_TT_PATTERN_IS_REGISTERED);
}
inline void _Tt_pattern::
set_in_session()
{
_flags |= (1<<_TT_PATTERN_IN_SESSION);
}
inline void _Tt_pattern::
clr_in_session()
{
_flags &= ~(1<<_TT_PATTERN_IN_SESSION);
}
inline int _Tt_pattern::
in_session() const
{
return(_flags&(1<<_TT_PATTERN_IN_SESSION));
}

View File

@@ -0,0 +1,38 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_pattern_utils.C /main/3 1995/10/23 10:27:06 rswiston $
/*
*
* mp_pattern_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_pattern.h>
_Tt_patlist::
_Tt_patlist()
{
}
_Tt_patlist::
~_Tt_patlist()
{
}
_Tt_patlist::
_Tt_patlist(_Tt_string o)
{
_op = o;
}
_Tt_string
_tt_patlist_op(_Tt_object_ptr &o)
{
return(((_Tt_patlist *)o.c_pointer())->op());
}
implement_list_of(_Tt_pattern)
implement_list_of(_Tt_patlist)
implement_table_of(_Tt_patlist)

View File

@@ -0,0 +1,38 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_pattern_utils.h /main/3 1995/10/23 10:27:13 rswiston $ */
/*
*
* mp_pattern_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_pattern
*/
#ifndef MP_PATTERN_UTILS_H
#define MP_PATTERN_UTILS_H
#include <util/tt_object.h>
#include <util/tt_list.h>
#include <util/tt_string.h>
#include <util/tt_table.h>
class _Tt_pattern;
declare_list_of(_Tt_pattern)
class _Tt_patlist : public _Tt_object {
public:
_Tt_patlist();
~_Tt_patlist();
_Tt_patlist(_Tt_string o);
void set_op(_Tt_string o){ _op = o; };
_Tt_string op(){ return _op; };
_Tt_pattern_list_ptr patterns;
private:
_Tt_string _op;
};
_Tt_string _tt_patlist_op(_Tt_object_ptr &o);
declare_list_of(_Tt_patlist)
declare_table_of(_Tt_patlist)
#endif /* MP_PATTERN_UTILS_H */

View File

@@ -0,0 +1,315 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_procid.C /main/4 1997/07/30 15:43:53 samborn $
/*
*
* mp_procid.cc -- methods for communicating with active processes
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <errno.h>
#include <fcntl.h>
#include "util/tt_host.h"
#include "mp/mp_file.h"
#include "mp/mp_message.h"
#include "mp/mp_mp.h"
#include "mp/mp_pattern.h"
#include "mp/mp_procid.h"
#include "mp/mp_session.h"
#include "mp/mp_stream_socket.h"
#include "util/tt_int_rec.h"
#include "util/tt_global_env.h"
#include <arpa/inet.h>
#if defined(sgi)
#include <CC/libc.h>
#endif
_Tt_procid::
_Tt_procid()
{
_fd = -1;
_pid = 0;
_version = 0;
_flags = 0;
_mxdr_stream = (XDR *)0;
}
_Tt_procid::
~_Tt_procid()
{
}
//
// Returns the fd which will be used to signal this procid if there are
// new messages for it. -1 means error. This method is only used in
// client mode. This method caches the fd returned from the
// _Tt_stream_socket::fd method. This method has the side-effect that it
// will accept the connection on the socket if not already done. See the
// comments in _Tt_c_procid::set_fd_channel for more details.
//
int _Tt_procid::
fd()
{
if (_socket.is_null()) {
return(-1);
} else if (_fd == -1) {
_fd = _socket->fd();
}
return(_fd);
}
//
// Returns the string version of the id for this procid. See
// _Tt_c_procid::init() for a description of the format for this id.
//
// XXX: Warning! Do not inline the following. Causes weirdness with
// the table package.
//
const _Tt_string & _Tt_procid::
id() const
{
// return string representation
return(_id);
}
//
// Returns 1 if this procid's id is the same as the one given.
//
int _Tt_procid::
is_equal(_Tt_string &i)
{
if (_id.len()) {
return(_id == i);
} else {
return(0);
}
}
//
// Returns the TCP port to connect to to signal a procid for a new
// message. This method is only used in server mode.
//
int _Tt_procid::
port() const
{
if (_socket.is_null()) {
return(-1);
} else {
return(_socket->port());
}
}
//
// XDR encodes/decodes a procid.
//
bool_t _Tt_procid::
xdr(XDR *xdrs)
{
long localpid;
if (! _id.xdr(xdrs)) {
return 0;
}
if (xdrs->x_op == XDR_ENCODE) {
localpid = _pid;
}
if (! xdr_long(xdrs, &localpid)) {
return 0;
}
if (xdrs->x_op == XDR_DECODE) {
_pid = (pid_t)localpid;
}
return(_proc_host_ipaddr.xdr(xdrs));
}
void _Tt_procid::
print(const _Tt_ostream &os) const
{
os << _id << " [" << _pid;
if (! _proc_host.is_null()) {
os << "@" << _proc_host->name();
}
os << "]\n";
}
//
// Returns 1 if this procid is handling m or is voting on it.
//
int _Tt_procid::
processing(const _Tt_message &m)
{
switch (m.state()) {
case TT_FAILED:
case TT_HANDLED:
case TT_RETURNED:
// if message state is already final then it can't be
// handled by anyone.
return 0;
default:
break;
}
if (!m.handler().is_null()) {
return m.handler()->is_equal( this );
} else if (m.message_class() == TT_OFFER) {
return 1;
} else {
return 0;
}
}
//
// Wrapper to invoke the _Tt_procid_ptr::xdr method.
//
bool_t
tt_xdr_procid(XDR *xdrs, _Tt_procid_ptr *patp)
{
return((*patp).xdr(xdrs));
}
//
// Wrapper to invoke the _Tt_message_list_ptr::xdr method.
//
bool_t
tt_xdr_message_list(XDR *xdrs, _Tt_message_list_ptr *mptr)
{
return((*mptr).xdr(xdrs));
}
//
// Add the given path to the list of files this procid object has
// joined.
//
void _Tt_procid::
add_joined_file(_Tt_string fpath)
{
if (joined_to_file(fpath)) {
return;
}
if (_joined_files.is_null()) {
_joined_files = new _Tt_string_list();
}
_joined_files->push(fpath);
}
//
// Delete the given path from the list of files this procid object has
// joined.
//
void _Tt_procid::
del_joined_file(_Tt_string fpath)
{
if (_joined_files.is_null()) {
return;
}
_Tt_string_list_cursor jc(_joined_files);
while (jc.next()) {
if (*jc == fpath) {
jc.remove();
}
}
}
//
// Return 1 if the given path represents a file this procid object has
// joined.
//
int _Tt_procid::
joined_to_file(_Tt_string fpath)
{
if (_joined_files.is_null()) {
return(0);
}
_Tt_string_list_cursor jc(_joined_files);
while (jc.next()) {
if (*jc == fpath) {
return(1);
}
}
return(0);
}
//
// Invokes _Tt_procid::id method on o which is assumed to point to a
// _Tt_procid. Used by the table package to generate keys.
//
_Tt_string
_tt_procid_id(_Tt_object_ptr &o)
{
return(((_Tt_procid *)o.c_pointer())->id());
}
#ifdef OPT_ADDMSG_DIRECT
//
// If this option is turned on, these functions are used to read/write
// a given counted buffer to the given _Tt_stream_socket object.
// "iohandle" is really a pointer to this _Tt_stream_socket object (it
// is given to xdrrec_create, and then XDR will give it to these
// functions to do the read/writes to an xdr stream. See
// _Tt_s_procid::signal_new_message(_Tt_message_ptr &m), and
// _Tt_c_procid::next_message.)
//
int
_tt_xdr_readit(char *iohandle, char *buf, int nbytes)
{
int rval;
fd_set readfds;
timeval tmout;
int fd;
_Tt_stream_socket *sptr = (_Tt_stream_socket *)iohandle;
fd = sptr->fd();
FD_ZERO(&readfds);
FD_SET(fd,&readfds);
tmout.tv_sec = 0;
tmout.tv_usec = 0;
if (select(FD_SETSIZE, &readfds, 0, 0, &tmout) <= 0) {
if (errno == EBADF) {
_tt_syslog( 0, LOG_ERR, "_tt_xdr_readit(): %m" );
return(-1);
}
}
if (!FD_ISSET(fd, &readfds)) {
_tt_syslog( 0, LOG_ERR, "_tt_xdr_readit(): !FD_ISSET()" );
return(0);
}
rval = sptr->recv(buf, nbytes);
return((rval) ? rval : -1);
}
int
_tt_xdr_writeit(char *iohandle, char *buf, int nbytes)
{
return(((_Tt_stream_socket *)iohandle)->send(buf,nbytes));
}
#endif // OPT_ADDMSG_DIRECT

View File

@@ -0,0 +1,136 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_procid.h /main/3 1995/10/23 10:27:28 rswiston $ */
/*
* mp_procid.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file contains the implementation of _Tt_procid which is an object
* that represents an active process communicating with a message server.
* There are two instances of this object depending on whether the object
* is in client or server mode. The client instance is basically just a
* handle on it's id. The server instance maintains information such as
* what patterns are registered for a process, what signalling channel is
* used, and also what messages are waiting to be delivered to the client
* instance of the procid.
*/
#ifndef MP_PROCID_H
#define MP_PROCID_H
#include "util/tt_table.h"
#include "util/tt_host_utils.h"
#include "mp/mp_global.h"
#include "mp/mp_stream_socket_utils.h"
#include "mp/mp_session_utils.h"
#include "mp/mp_message_utils.h"
#include "mp/mp_pattern_utils.h"
#include "mp/mp_procid_utils.h"
#include "mp_xdr_functions.h"
#define _TT_MESSAGE_TIMEOUT 300 /* default message timeout in seconds */
#ifdef OPT_ADDMSG_DIRECT
/*
* if this option is turned on then TT_ADDMSG_VERS should be set to
* the version number at which addmsg_direct is used. The code assumes
* that all versions later than this version also support this
* optimization.
*
* XXX: This should probably be changed to a mechanism that allows
* clients to tell their session that they would like this optimization
* to be used. The session can then deny their request meaning it doesn't
* support the optimization.
*/
# define TT_ADDMSG_VERS 3
#else
/*
* defining this as -1 assures that no code will make use of it
*/
# define TT_ADDMSG_VERS -1
#endif
enum _Tt_procid_flagbits {
_TT_PROC_ACTIVE, /* is an active proc */
_TT_PROC_FD_CHANNEL_ON, /* fd channel is valid */
_TT_PROC_COMMITTED, /* committed to default session */
_TT_PROC_IS_LOCAL, /* is local to server's machine */
_TT_PROC_SIGNALLED, /* has been signalled about new msgs */
_TT_PROC_MSGSENT /* msg sent directly to proc */
};
class _Tt_procid : public _Tt_object {
public:
_Tt_procid();
virtual ~_Tt_procid();
void add_joined_file(_Tt_string fpath);
void del_joined_file(_Tt_string fpath);
int fd();
const _Tt_string &id() const;
int is_equal(const _Tt_procid_ptr &p) {
return(_id == p->_id);
}
int is_equal(_Tt_string &id);
int joined_to_file(_Tt_string fpath);
int processing(const _Tt_message &m);
_Tt_pattern_list_ptr &patterns() {
return _patterns;
}
pid_t pid() const {
return _pid;
}
int port() const;
void print(const _Tt_ostream &os) const;
_Tt_host_ptr &proc_host() {
return _proc_host;
}
int program() const {
return _program;
}
void set_start_token(const _Tt_string &token) {
_start_token = token;
}
_Tt_string &start_token() {
return _start_token;
}
int version() const {
return _version;
}
_Tt_string &proc_host_ipaddr() {
return _proc_host_ipaddr;
}
_Tt_string_list_ptr &ptypes() {
return _declared_ptypes;
}
bool_t xdr(XDR *xdrs);
protected:
int _fd;
int _flags;
int _program;
int _version;
pid_t _pid;
_Tt_string _id;
_Tt_string _start_token;
_Tt_string _proc_host_ipaddr;
_Tt_string_list_ptr _joined_files;
_Tt_string_list_ptr _declared_ptypes;
_Tt_pattern_list_ptr _patterns;
_Tt_host_ptr _proc_host;
_Tt_stream_socket_ptr _socket;
XDR *_mxdr_stream;
};
_Tt_string _tt_procid_id(_Tt_object_ptr &o);
bool_t tt_xdr_procid(XDR *xdrs, _Tt_procid_ptr *patp);
bool_t tt_xdr_message_list(XDR *xdrs, _Tt_message_list_ptr *mptr);
#ifdef OPT_ADDMSG_DIRECT
int _tt_xdr_readit(char *iohandle, char *buf, int nbytes);
int _tt_xdr_writeit(char *iohandle, char *buf, int nbytes);
#endif /* OPT_ADDMSG_DIRECT */
#endif /* MP_PROCID_H */

View File

@@ -0,0 +1,15 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_procid_utils.C /main/3 1995/10/23 10:27:36 rswiston $
/*
*
* mp_procid_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_procid.h>
implement_list_of(_Tt_procid)
implement_table_of(_Tt_procid)

View File

@@ -0,0 +1,24 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_procid_utils.h /main/3 1995/10/23 10:27:43 rswiston $ */
/*
*
* mp_procid_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Utilities declarations for _Tt_procid
*/
#ifndef MP_PROCID_UTILS_H
#define MP_PROCID_UTILS_H
#include <util/tt_object.h>
#include <util/tt_string.h>
#include <util/tt_table.h>
class _Tt_procid;
declare_list_of(_Tt_procid)
declare_table_of(_Tt_procid)
#endif /* MP_PROCID_UTILS_H */

View File

@@ -0,0 +1,56 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_rpc.h /main/5 1999/08/30 10:55:41 mgreess $ */
/*
*
* @(#)mp_rpc.h 1.15 93/09/07
*
* Copyright (c) 1990,1993 by Sun Microsystems, Inc.
*
* Common declarations for RPC implementation classes.
*/
#ifndef _TT_MP_RPC
#define _TT_MP_RPC
#include "tt_options.h"
#if defined(linux)
# define __SVR4_I386_ABI_L1__
#endif
#include <rpc/rpc.h>
#if defined(linux)
# undef __SVR4_I386_ABI_L1__
#endif
#if defined(ultrix) || defined(_AIX)
extern "C" {
void svcerr_auth (SVCXPRT *, enum auth_stat);
SVCXPRT *svcfd_create(int,int,int);
void svc_getreqset(fd_set *);
};
#endif
#if defined(OPT_TLI)
# include <netconfig.h>
# include <tiuser.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
#endif /* OPT_TLI */
#include <sys/types.h>
#include "util/tt_object.h"
#include "util/tt_ptr.h"
#include "util/tt_int_rec.h"
#include "mp/mp_rpc_fns.h"
#include "util/tt_host_utils.h"
enum _Tt_rpcsrv_err {
_TT_RPCSRV_OK,
_TT_RPCSRV_ERR,
_TT_RPCSRV_TMOUT,
_TT_RPCSRV_FDERR
};
#endif /* _TT_MP_RPC */

View File

@@ -0,0 +1,335 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_rpc_client.C /main/9 1999/09/08 18:21:02 mgreess $
/*
*
* mp_rpc_client.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <sys/time.h> // ultrix
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include "tt_options.h"
#include "mp/mp_auth.h"
#include "mp/mp_rpc_client.h"
#include "mp/mp_xdr_functions.h"
#include "util/tt_host.h"
#include "util/tt_port.h"
#if defined(ultrix)
extern "C"
{ extern struct XSizeHints;
extern struct XStandardColormap;
extern struct XTextProperty;
extern struct XWMHints;
extern struct XClassHint;
};
#endif
#if defined(_AIX)
/* AIX's FD_ZERO macro uses bzero() without declaring it. */
#include <strings.h>
/* And arpa/inet.h has a buggy declaration of inet_addr */
extern "C" in_addr_t inet_addr(const char *);
#endif
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <memory.h>
#if defined(sgi)
/* SGI's FD_ZERO macro uses bzero() without declaring it. */
#include <CC/libc.h>
#endif
#include <sys/resource.h>
#include <util/tt_global_env.h>
#include <mp/mp_rpc_fns.h>
/*
* Constructs an rpc client.
*/
_Tt_rpc_client::
_Tt_rpc_client(int conn_socket)
{
_socket = conn_socket;
_client = (CLIENT *)0;
}
/*
* Destroys an rpc client (breaks off connections)
*/
_Tt_rpc_client::
~_Tt_rpc_client()
{
if (_client != (CLIENT *)0) {
clnt_destroy(_client);
}
_host = (_Tt_host *)0;
}
/*
* Returns the socket associated with an rpc client. --> it would be
* nice to use this socket rather than open up a new one when signalling
* procids.
*/
int _Tt_rpc_client::
socket()
{
return(_socket);
}
/*
* create client connection to host,program,version
*/
int _Tt_rpc_client::
init(_Tt_host_ptr &host, int program, int version,
uid_t servuid, _Tt_auth &auth)
{
int optval;
static caddr_t saved_opaque = 0;
static int saved_len = 0;
optval = (_socket == RPC_ANYSOCK);
_auth = auth;
_host = host;
_program = program;
_version = version;
_server_uid = servuid;
if (_client != (CLIENT *)0) {
if (_auth.auth_level() == _TT_AUTH_UNIX) {
auth_destroy(_client->cl_auth);
}
clnt_destroy(_client);
}
#if defined(OPT_SECURE_RPC)
if (_auth.auth_level() == _TT_AUTH_DES) {
if (_server_uid == 0) {
host2netname(_servername, (char *)_host->name(), 0);
} else {
user2netname(_servername, _server_uid, 0);
}
}
#endif /* OPT_SECURE_RPC */
#ifndef OPT_TLI
memset(&_server_addr, 0, sizeof(_server_addr));
_server_addr.sin_family = AF_INET;
_server_addr.sin_port = htons((optval) ? 0 : 4000);
_server_addr.sin_addr.s_addr = inet_addr((char *)(_host->stringaddr()));
_client = clnttcp_create(&_server_addr, _program,
_version, &_socket, 4000, 4000);
if (_client == 0) {
// XXX only when in some kind of debug mode
//clnt_pcreateerror("_Tt_rpc_client::init(): clnttcp_create()");
return 0;
}
if (_auth.auth_level() == _TT_AUTH_UNIX) {
_client->cl_auth = authunix_create_default();
}
if (optval) {
#ifndef linux
if (setsockopt(_socket, SOL_SOCKET, SO_USELOOPBACK,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_rpc_client::init(): "
"setsockopt(SO_USELOOPBACK): %m");
}
#endif
if (setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_rpc_client::init(): "
"setsockopt(TCP_NODELAY): %m");
}
}
#else
_client = clnt_create((char *)_host->name(),
_program, _version, "circuit_v");
if (_client == 0) {
// XXX only when in some kind of debug mode
//clnt_pcreateerror( "_Tt_rpc_client::init(): clnt_create()" );
return 0;
}
if (!clnt_control(_client, CLGET_FD, (char *)&_socket)) {
// I cannot imagine how this could ever fail at this point.
return 0;
}
// We used to call _tt_tli_set_nodelay here on the RPC connection.
// This stopped working mysteriously, suddenly the endpoint started
// coming back in state T_DATAXFER instead of T_IDLE from clnt_create.
// Fortunately, in the meantime the TIRPC library has started
// setting NODELAY on RPC/TCP connections, so we don't need to
// do it here anymore anyway.
if (_auth.auth_level() == _TT_AUTH_UNIX) {
_client->cl_auth = authunix_create_default();
}
#endif // !OPT_TLI
// Set close-on-exec bit so a libtt client which forks and execs won't
// be short some fd's in the child.
if (-1==fcntl(_socket, F_SETFD, 1)) {
_tt_syslog( 0, LOG_ERR, "_Tt_rpc_client::init(): "
"fcntl(F_SETFD): %m");
}
return(1);
}
/*
* invoke rpc procedure
*/
clnt_stat _Tt_rpc_client::
call(int procnum, xdrproc_t inproc, char *in,
xdrproc_t outproc, char *out, int timeout)
{
fd_set bogus;
timeval tmout;
timeval total_timeout;
struct sigaction curr_action;
int need2reset_sigpipe = 0;
_Tt_auth_iceauth_args args;
if (_client == (CLIENT *)0) {
return(RPC_CANTSEND);
}
total_timeout.tv_sec = ((timeout < 0) ? 0 : timeout);
total_timeout.tv_usec = 0;
clnt_control(_client, CLSET_TIMEOUT, (char *) &total_timeout);
switch (_auth.auth_level()) {
case _TT_AUTH_UNIX:
break;
case _TT_AUTH_ICEAUTH:
break;
#if defined(OPT_SECURE_RPC)
case _TT_AUTH_DES:
#ifdef OPT_TLI
_client->cl_auth =
authdes_seccreate(_servername, 60, (char *)_host->name(),
(des_block *)0);
if (_client->cl_auth == 0) {
_tt_syslog( 0, LOG_WARNING, "authdes_seccreate(): 0" );
// XXX what todo when authdes_seccreate() fails?
return RPC_AUTHERROR;
}
#else
_client->cl_auth =
authdes_create(_servername, 60, &_server_addr,
(des_block *)0);
if (_client->cl_auth == 0) {
_tt_syslog( 0, LOG_WARNING, "authdes_seccreate(): 0" );
// XXX what todo when authdes_seccreate() fails?
return RPC_AUTHERROR;
}
#endif /* OPT_TLI */
break;
#endif /* OPT_SECURE_RPC */
case _TT_AUTH_NONE:
break;
default:
return(RPC_AUTHERROR);
}
if (timeout == 0) {
FD_ZERO(&bogus);
FD_SET(_socket, &bogus);
tmout.tv_sec = 0;
tmout.tv_usec = 0;
select(FD_SETSIZE, &bogus, 0, 0, &tmout);
if (FD_ISSET(_socket, &bogus)) {
return(RPC_CANTSEND);
}
}
#if defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
if (timeout <= 0)
{
outproc = (xdrproc_t) NULL;
}
#endif
//
// tcp write errors (when the rpc_server on the other end dies)
// cause a SIGPIPE. We need to make sure the SIGPIPE is caught,
// or the process dies.
//
if (sigaction(SIGPIPE, 0, &curr_action) != 0) {
_tt_syslog( 0, LOG_ERR, "sigaction(): %m" );
}
#if defined(OPT_BUG_SUNOS_5) || defined(OPT_BUG_UW_1)
if ((SIG_TYP)curr_action.sa_handler == SIG_DFL)
#else
#if defined(OPT_BUG_UW_2) || defined(OPT_BUG_UXP)
if ((void(*)(int))curr_action.sa_handler == SIG_DFL)
#else
if (curr_action.sa_handler == SIG_DFL)
#endif
#endif
{
need2reset_sigpipe = 1;
signal(SIGPIPE, SIG_IGN);
}
if (_TT_AUTH_ICEAUTH == _auth.auth_level()) {
args.auth_level = _auth.auth_level();
args.auth_cookie = _auth.auth_cookie();
args.inproc = (xdr_auth_proc_t) inproc;
args.inargs = (caddr_t) in;
_clnt_stat = clnt_call(_client, procnum,
(xdrproc_t) tt_xdr_auth_iceauth_args,
(char*) &args,
outproc, out,
total_timeout);
}
else {
_clnt_stat = clnt_call(_client, procnum,
inproc, in,
outproc, out,
total_timeout);
}
#if defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
if (timeout <= 0)
{
total_timeout.tv_sec = 10;
total_timeout.tv_usec = 0;
clnt_control(_client, CLSET_TIMEOUT, (char *) &total_timeout);
clnt_call(_client, NULLPROC, (xdrproc_t) xdr_void, (char *)NULL,
(xdrproc_t) xdr_void, (char *) NULL, total_timeout);
}
#endif
if (need2reset_sigpipe) {
signal(SIGPIPE, SIG_DFL);
}
#if !defined(OPT_BUG_RPCINTR)
if (_clnt_stat == RPC_INTR) {
return(RPC_CANTSEND);
}
#endif
if (_auth.auth_level() == _TT_AUTH_DES) {
auth_destroy(_client->cl_auth);
}
return(_clnt_stat);
}

View File

@@ -0,0 +1,56 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_rpc_client.h /main/4 1999/08/30 10:57:12 mgreess $ */
/*
*
* mp_rpc_server.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of
* _Tt_rpc_client which represents the ttsession
* RPC client.
*/
#ifndef _TT_MP_RPC_CLIENT
#define _TT_MP_RPC_CLIENT
#include "mp/mp_auth.h"
#include "mp/mp_rpc.h"
class _Tt_rpc_client : public _Tt_object {
public:
_Tt_rpc_client(int conn_socket = RPC_ANYSOCK);
virtual ~_Tt_rpc_client();
// create client connection to host,program,version
int init(_Tt_host_ptr &host,
int program, int version,
uid_t servuid,
_Tt_auth &auth);
int socket();
// invoke rpc procedure
clnt_stat call(int procnum,
xdrproc_t inproc,
char *in,
xdrproc_t outproc,
char *out,
int timeout);
CLIENT *rpc_handle() { return _client; };
private:
_Tt_host_ptr _host;
int _program;
int _version;
int _socket;
uid_t _server_uid;
_Tt_auth _auth;
char _servername[MAXNETNAMELEN];
CLIENT *_client;
clnt_stat _clnt_stat;
#if defined(OPT_TLI)
int _server_addr;
#else
sockaddr_in _server_addr;
#endif /* OPT_TLI */
};
#endif /* _TT_MP_RPC_CLIENT */

View File

@@ -0,0 +1,15 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_rpc_client_utils.C /main/3 1995/10/23 10:28:13 rswiston $
/*
*
* mp_rpc_client_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_rpc_client_utils.h>
#include <mp/mp_rpc_client.h>
implement_ptr_to(_Tt_rpc_client)

View File

@@ -0,0 +1,19 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_rpc_client_utils.h /main/3 1995/10/23 10:28:19 rswiston $ */
/*
*
* mp_rpc_client_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_RPC_CLIENT_UTILS_H
#define MP_RPC_CLIENT_UTILS_H
#include <util/tt_object.h>
class _Tt_rpc_client;
declare_ptr_to(_Tt_rpc_client)
#endif /* MP_RPC_CLIENT_UTILS_H */

View File

@@ -0,0 +1,95 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_rpc_fns.C /main/4 1996/04/21 19:12:28 drk $ */
/*
* mp_rpc_fns.C
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <tt_options.h>
#include <rpc/rpc.h>
#if defined(OPT_TLI)
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <tiuser.h>
#include <sys/socket.h>
/*
* Sets the TCP_NODELAY option for a tli stream bound using tcp. This
* option is crucial to good message performance since otherwise there is
* a 200 ms delay between messages. This code is based on the source code
* for tli rpc (since documentation was sorely lacking).
*/
extern "C"
int
_tt_tli_set_nodelay(int fd)
{
struct t_optmgmt *options;
struct sochdr {
struct opthdr opthdr;
long value;
} sochdr;
options = (struct t_optmgmt *)t_alloc(fd, T_OPTMGMT, 0);
if (options == (struct t_optmgmt *)0) {
return (0);
}
sochdr.opthdr.level = IPPROTO_TCP;
sochdr.opthdr.name = TCP_NODELAY;
sochdr.opthdr.len = 4;
sochdr.value = 1;
options->opt.maxlen = sizeof(sochdr);
options->opt.len = sizeof(sochdr);
options->opt.buf = (char *) &sochdr;
options->flags = T_NEGOTIATE;
if (t_optmgmt(fd, options, options) == -1) {
t_error("t_optmgmt");
return(0);
}
options->opt.buf = 0;
(void) t_free((char *)options, T_OPTMGMT);
return(1);
}
extern "C"
int
_tt_bind_endpoint(int fd,
char *s,
char *r)
{
return(t_bind(fd, (struct t_bind *)s, (struct t_bind *)r));
}
#endif /* OPT_TLI */
/*
* XXX: the following are needed because of bugs in the C++ header files
* for these functions. Should use the native definitions when the header
* files are fixed.
*/
extern "C"
void
_tt_svc_freeargs(SVCXPRT *transp,
xdrproc_t inproc,
char *in)
{
svc_freeargs(transp, inproc, in);
}
extern "C"
int
_tt_svc_getargs(SVCXPRT *transp,
xdrproc_t inproc,
char *in)
{
return(svc_getargs(transp, inproc, in));
}

View File

@@ -0,0 +1,29 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_rpc_fns.h /main/3 1995/10/23 10:28:33 rswiston $ */
/*
*
* mp_rpc_fns.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file just implements two function wrappers around two RPC
* functions in order to workaround a problem with the C++ header files
* (bug has already been submitted).
*/
#ifndef _TT_MP_RPC_FNS_H
#define _TT_MP_RPC_FNS_H
#include <stdlib.h>
#include <tt_options.h>
extern "C" { void _tt_svc_freeargs(SVCXPRT *, xdrproc_t, char *); }
extern "C" { int _tt_svc_getargs(SVCXPRT *, xdrproc_t, char *); }
#ifdef OPT_TLI
extern "C" { int _tt_bind_endpoint(int, char *, char *); }
extern "C" { int _tt_tli_set_nodelay(int fd); }
#endif /* OPT_TLI */
#endif /* _TT_MP_RPC_FNS_H */

View File

@@ -0,0 +1,146 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_rpc_interface.h /main/4 1999/08/30 10:57:58 mgreess $ */
/* -*-C++-*-
*
* @(#)mp_rpc_interface.h 1.9 93/07/30
*
* mp_rpc_interface.h
*
* Constants that must be known by both client and server in the
* ttsession RPC interface.
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#if !defined(_MP_RPC_INTERFACE_H)
#define _MP_RPC_INTERFACE_H
/*
* Current ToolTalk RPC protocol version
*
* 1 1.0 Classic
* 2 1.0.1 Asynchronous (i.e. faster) RPCs
* 3 1.2 TT_OFFER, TT_HANDLE_PUSH, TT_HANDLE_ROTATE, affecting
* any RPC that can send ttsession a new message or pattern:
* TT_RPC_DISPATCH
* TT_RPC_DISPATCH_2
* TT_RPC_DISPATCH_WITH_CONTEXT
* TT_RPC_DISPATCH_2_WITH_CONTEXT
* TT_RPC_ADD_PATTERN
* TT_RPC_ADD_PATTERN_WITH_CONTEXT
*/
const int TT_RPC_VERSION = 4;
const int TT_OFFER_RPC_VERSION = 4;
/*
* Current ToolTalk XDR protocol version. See tt_xdr_version.h
*
* 1 1.0 Classic; used by default for all on-disk data structures
* 2 1.0.1 new _Tt_string::xdr(); more efficient _Tt_message::xdr(); etc?
* 3 1.1 contexts in _Tt_pattern::xdr(), _Tt_signature::xdr();
* used in any types database with contextful signatures.
* 4 1.2 PUSH, ROTATE in _Tt_pattern::xdr(), _Tt_signature::xdr();
* _Tt_arg::_matched_type in _Tt_arg::xdr();
* used in any types database with push/rotate signatures.
* However, we still use version 3 for the wire, because
* PUSH/ROTATE only make a difference in the types database.
*/
const int TT_XDR_VERSION = 3;
const int TT_TYPESDB_DEFAULT_XDR_VERSION = 1;
const int TT_CONTEXTS_XDR_VERSION = 3;
const int TT_PUSH_ROTATE_XDR_VERSION = 4;
/*
* Default timeout for RPC requests (in seconds).
* Use a very large value to indicate almost infinity.
* In addition to accommodating a loaded ttsession, it will also
* facilitate debugging.
* ONE HUNDRED MILLION IS THE MAXIMUM PERMITTED VALUE
* ON SunOS 4.1. Use ONE MILLION to leave room for possible weird system
* dependencies. That will still allow the sender to wait a patient 11.6 days.
*/
#define TT_RPC_TMOUT 1000000
/*
* RPC procedure numbers
*/
/*
* Note that each rpc procedure number cannot be re-used. Adding a new
* rpc procedure thus means allocating a new number below (and then
* bumping up TT_RPC_LAST) and adding the dispatch function to the
* _tt_rpc_dispatch_table in mp_rpc_implement.cc. The only exception
* to this is TT_RPC_VRFY_SESSION which has an out-of-sequence rpc
* number (it is chosen to minimize the likelyhood of being implemented
* by another program since the purpose of it is to identify a tooltalk
* session.)
*/
typedef enum {
TT_RPC_NULLPROC = 0,
TT_RPC_DISPATCH = 1,
TT_RPC_UPDATE_MSG = 2,
TT_RPC_JOIN_FILE = 3,
TT_RPC_QUIT_FILE = 4,
TT_RPC_JOIN_SESSION = 5,
TT_RPC_QUIT_SESSION = 6,
TT_RPC_NEXT_MESSAGE = 7,
TT_RPC_ADD_PATTERN = 8,
TT_RPC_DEL_PATTERN = 9,
TT_RPC_DECLARE_PTYPE = 10,
TT_RPC_SET_FD_CHANNEL = 11,
TT_RPC_SET_PROP = 12,
TT_RPC_ADD_PROP = 13,
TT_RPC_GET_PROP = 14,
TT_RPC_PROP_COUNT = 15,
TT_RPC_PROP_NAME = 16,
TT_RPC_PROP_NAMES_COUNT = 17,
TT_RPC_ALLOC_PROCID_KEY = 18,
TT_RPC_CLOSE_PROCID = 19,
TT_RPC_OTYPE_DERIVEDS_COUNT = 20,
TT_RPC_OTYPE_DERIVED = 21,
TT_RPC_OTYPE_BASE = 22,
TT_RPC_OTYPE_IS_DERIVED = 23,
TT_RPC_OTYPE_OSIG_COUNT = 24,
TT_RPC_OTYPE_HSIG_COUNT = 25,
TT_RPC_OTYPE_OSIG_OP = 26,
TT_RPC_OTYPE_HSIG_OP = 27,
TT_RPC_OTYPE_OSIG_ARGS_COUNT = 28,
TT_RPC_OTYPE_HSIG_ARGS_COUNT = 29,
TT_RPC_OTYPE_OSIG_ARG_MODE = 30,
TT_RPC_OTYPE_HSIG_ARG_MODE = 31,
TT_RPC_OTYPE_OSIG_ARG_TYPE = 32,
TT_RPC_OTYPE_HSIG_ARG_TYPE = 33,
TT_RPC_HDISPATCH = 34,
TT_RPC_HUPDATE_MSG = 35,
/* version 2 numbers */
TT_RPC_DISPATCH_2 = 36,
TT_RPC_UPDATE_MSG_2 = 37,
TT_RPC_MSGREAD_2 = 38,
/* S493 numbers */
TT_RPC_DISPATCH_ON_EXIT = 39,
TT_RPC_UNDECLARE_PTYPE = 40,
TT_RPC_EXISTS_PTYPE = 41,
TT_RPC_UNBLOCK_PTYPE = 42,
TT_RPC_JOIN_CONTEXT = 43,
TT_RPC_QUIT_CONTEXT = 44,
TT_RPC_DISPATCH_WITH_CONTEXT = 45,
TT_RPC_DISPATCH_2_WITH_CONTEXT = 46,
TT_RPC_ADD_PATTERN_WITH_CONTEXT = 47,
/* S1093 numbers */
TT_RPC_LOAD_TYPES = 48,
/* Add new RPC numbers before here and bump TT_RPC_LAST */
TT_RPC_LAST = 49,
/* This high number is treated specially */
TT_RPC_VRFY_SESSION = 400
} _Tt_rpc_procedure_number;
#endif /* _MP_RPC_INTERFACE_H */

View File

@@ -0,0 +1,917 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_session.C /main/13 1999/09/16 13:46:46 mgreess $
/*
* @(#)mp_session.C 1.84 96/01/10
*
* Tool Talk Message Passer (MP) - mp_session.cc
*
* Copyright (c) 1990,1992 by Sun Microsystems, Inc.
*
* Implementation of the _Tt_session class.
*/
#include "util/tt_global_env.h"
#include "util/tt_xdr_version.h"
#include "util/tt_host.h"
#include "util/tt_port.h"
#include "util/tt_gettext.h"
#include "mp/mp_global.h"
#include "mp/mp_message.h"
#include "mp/mp_mp.h"
#include "mp/mp_c_global.h"
#include "mp/mp_c_session.h"
#include "mp/mp_c_mp.h"
#include "mp/mp_pattern.h"
#include "mp/mp_rpc_client.h"
#include "mp/mp_rpc_interface.h"
#include "mp/mp_session.h"
#include "mp/mp_desktop.h"
#include "mp/mp_xdr_functions.h"
#include <unistd.h>
#ifdef OPT_UNIX_SOCKET_RPC
# include <sys/socket.h>
# include <sys/un.h>
#endif // OPT_UNIX_SOCKET_RPC
_Tt_session::
_Tt_session()
{
_env = _TT_ENV_LAST;
_is_server = 0; // default server mode
_is_dead = 0;
_rpc_version = 0;
}
_Tt_session::
~_Tt_session()
{
if (! _desktop.is_null()) {
if (_is_server && _env == _TT_ENV_X11 && (_id.len() > 0)) {
if ( (! _desktop->del_prop(TT_XATOM_NAME))
|| (! _desktop->del_prop(TT_CDE_XATOM_NAME)))
{
_tt_syslog( 0, LOG_WARNING,
catgets( _ttcatd, 1, 14,
"could not delete the X "
"root window property %s "
"advertising this "
"session" ),
TT_XATOM_NAME );
}
}
}
#ifdef OPT_UNIX_SOCKET_RPC
if (_is_server && _socket_name.len()) {
(void)unlink((char *)_socket_name);
}
#endif
}
#ifdef OPT_UNIX_SOCKET_RPC
//
// Returns the name of the socket file if the unix socket rpc option is
// enabled. Note that the name should be unique for all sessions running
// on the same machine so it has to be derived from the session id
// (which has the required uniqueness properties).
//
char * _Tt_session::
local_socket_name()
{
#define SPRFX "/tmp/.TT"
if (_socket_name.len() == 0) {
char *sname = (char *)malloc(_id.len() + strlen(SPRFX) + 1);
char *sc;
sprintf(sname,"%s%s", SPRFX, (char *)_id);
sc = sname;
while (*sc) {
if (*sc == ' ') {
*sc = '_';
}
sc++;
}
_socket_name = sname;
free((MALLOCTYPE *)sname);
}
return((char *)_socket_name);
}
//
// Opens a connection to the unix socket bound to the given socket name.
// If successful returns the fd for the connection. Otherwise, returns
// -1.
//
int
c_open_unix_socket(char *socket_name)
{
int sock;
struct sockaddr_un server_addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
_tt_syslog( 0, LOG_ERR, "c_open_unix_socket(): socket(): %m" );
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strcpy(server_addr.sun_path, socket_name);
#if defined(ultrix) || defined(_AIX) || defined(hpux) || defined(__osf__)
int servlen = strlen(server_addr.sun_path) + sizeof(server_addr.sun_fam\
ily);
if (connect(sock, (sockaddr *)&server_addr, servlen) < 0) {
#else
if (connect(sock, (sockaddr *)&server_addr, sizeof(sockaddr_un)) < 0) {
#endif
return(-1);
}
return(sock);
}
#endif // OPT_UNIX_SOCKET_RPC
//
// Called if an event comes in from our desktop connection.
//
int _Tt_session::
desktop_event_callback()
{
if (! _desktop->process_event()) {
return (-1);
}
else
return 0;
}
//
// Initializes a session with the assumption that the server session is
// already running. If the server session isn't running then this method
// will return an error as opposed to attempting to autostart a new
// session (see _Tt_session::c_init). This is intended as a lower-level
// init function used by c_init or whenever autostarting is not required.
//
// Returns:
// TT_OK
// TT_ERR_ACCESS Could not init desktop (diagnostic emitted)
// TT_WRN_NOTFOUND No advertised address
// TT_ERR_INVALID Could not parse advertised address
// TT_ERR_NO_MATCH Advertised address's version is too new
// (diagnostic emitted)
// TT_ERR_ADDRESS Could not find advertised host
// TT_ERR_NOMP Could not init as rpc client
//
Tt_status _Tt_session::
client_session_init()
{
// this is a client of this session. Note that since this
// function may be called in the server, we can't use
// _tt_mp->in_server().
//
Tt_status err;
int rpc_init_done = 0;
_Tt_host_ptr lh;
_is_server = 0;
if (env() == _TT_ENV_X11 && _desktop.is_null()) {
_desktop = new _Tt_desktop();
if (! _desktop->init(_displayname, _TT_DESKTOP_X11)) {
return(TT_ERR_ACCESS);
}
}
if (_address_string.len() == 0) {
if (find_advertised_address(_address_string) != TT_OK) {
return(TT_WRN_NOTFOUND);
}
}
if (_address_string.len() == 0) {
// Don't call parsed_address() with an empty string,
// or it will think we're trying to create an address
// string instead of parse it. parsed_address()
// shouldn't be this cute. XXX
return TT_ERR_INVALID;
}
if ((err = parsed_address(_address_string)) != TT_OK) {
_address_string = (char *)0;
return(err);
}
if (_TT_AUTH_ICEAUTH == _auth.auth_level() &&
(err = _auth.retrieve_auth_cookie()) != TT_OK) {
return err;
}
if (! _tt_global->find_host(_hostaddr, _host, 1)) {
return(TT_ERR_ADDRESS);
}
if (_id.len() == 0) {
(void)set_id();
}
#ifdef OPT_UNIX_SOCKET_RPC
if (_tt_global->get_local_host(lh)) {
// if we are in the same host as the server session
// then we attempt to connect to its advertised unix
// socket to set up an rpc connection. If we succeed
// then we set rpc_init_done to 1 to prevent a normal
// tcp rpc connection from being made.
if (lh->stringaddr() == _host->stringaddr()) {
_u_sock = c_open_unix_socket(local_socket_name());
if (_u_sock != -1) {
_rpc_client = new _Tt_rpc_client(_u_sock);
if (_rpc_client->init(lh, _rpc_program,
_rpc_version,
_server_uid,
&_auth)) {
rpc_init_done = 1;
// Since we opened the fd ourselves,
// clnt_destroy won\'t close it
// unless we tell it it\'s OK.
clnt_control(_rpc_client->rpc_handle(),
CLSET_FD_CLOSE,
(char *) NULL);
}
}
}
}
#endif // OPT_UNIX_SOCKET_RPC
if (! rpc_init_done) {
_rpc_client = new _Tt_rpc_client();
if (! _rpc_client->init(_host, _rpc_program, _rpc_version,
_server_uid, _auth)) {
return(TT_ERR_NOMP);
}
}
// Get and save the file descriptor for this session.
_tt_mp->save_session_fd(_rpc_client->socket());
return(TT_OK);
}
//
// Verifies that the server side of the session is alive and is a
// ToolTalk session. Currently this is done by first invoking rpc
// procedure 0 to see if the session is responding to rpc requests. If
// that succeeds then we invoke rpc procedure TT_RPC_VRFY_SESSION which
// is a reasonably large number. The reply to this procedure should be
// the session id of the session we're talking to. This is a fairly good
// (but not foolproof!) method of verifying that this is a ToolTalk
// session.
//
// In fact it seems to be too picky, if the session id we have is
// different only in the IP address, it may just be an alternate
// IP address for the very same session.
//
// Returns:
// TT_OK
// TT_ERR_NOMP Session unreachable or a hoaxer
// TT_ERR_NO_MATCH Session has wrong version
// TT_ERR_INVALID Could not parse advertised address
// TT_ERR_AUTHORIZATION RPC authorization error
//
Tt_status _Tt_session::
ping()
{
Tt_status is_live;
_Tt_string sid;
// We used to call the NULLPROC here first, but that seems
// to be a waste of a round-trip since it doesn't tell
// us anything that the TT_RPC_VRFY_SESSION call doesn't.
is_live = call((int)TT_RPC_VRFY_SESSION,
(xdrproc_t)xdr_void, 0,
(xdrproc_t)tt_xdr_string,
(char *)&sid);
// We used to string-compare the returned session id with the one we
// have, but that was too picky since the IP address can usefully be
// different. Skip the check for now, perhaps we should check at
// least some of the components (UNIX pid?) We already know the
// transient RPC number is good, and most everything else is
// constant. We do make a minimal check that the id string is non
// null, this might catch the (unlikely) case where the program at
// the other end isn't a ttsession but does happen to have a
// procedure with a number the same as TT_RPC_VRFY_SESSION,
// although in that case I'd expect the RPC to fail in the
// XDR routines.
if (is_live == TT_OK && 0 == sid.len()) {
is_live = TT_ERR_NOMP;
}
if (is_live == TT_ERR_UNIMP) {
is_live = TT_ERR_INTERNAL;
}
// And finally, for reasons I haven't quite figured out,
// if the session id we have *isn't* equal to the one returned
// by ttsession, file scoped messages fail. I suspect
// pattern matching somewhere compares the ids.
// So, if the ttsession thinks its name is different, replace
// our idea of the name with its idea of its name.
if (is_live == TT_OK) {
set_id(sid);
}
return(is_live);
}
//
// Invokes an rpc call named by the rpc_proc parameter on the server
// session and returns any results. If timeout is anything other than -1
// then it will be used as the timeout value. Otherwise a suitable
// timeout value is chosen. If rebind is 1 then a new rpc connection will
// be attempted if this rpc fails.
//
// Returns:
// TT_OK
// TT_ERR_NOMP Could not talk to session
// TT_ERR_VERSION_MISMATCH RPC VERSMISMATCH
// TT_ERR_UNIMP rpc_proc not implemented by session
// TT_ERR_INVALID Could not parse address
// TT_ERR_AUTHORIZATION RPC authorization error
//
Tt_status _Tt_session::
call(int rpc_proc,
xdrproc_t xdr_arg_fn, char *arg,
xdrproc_t xdr_res_fn, char *res,
int timeout, int rebind)
{
//
// Ensure global xdr version is set to proper value for this session.
//
int xdr_version_2_use = _rpc_version;
//
// Some rpc calls use an xdr version number that is greater
// than the version number of the rpc protocol they exist in.
// See e.g. _tt_rpc_add_pattern_with_context().
//
switch (rpc_proc) {
case TT_RPC_ADD_PATTERN_WITH_CONTEXT:
if (xdr_version_2_use < TT_CONTEXTS_XDR_VERSION) {
xdr_version_2_use = TT_CONTEXTS_XDR_VERSION;
}
break;
}
_Tt_xdr_version ver(xdr_version_2_use);
Tt_status status;
clnt_stat rpc_status;
int processing;
int retry;
int tmout;
if (_rpc_client.is_null()) {
return(TT_ERR_INTERNAL);
}
if (timeout == -1) {
switch (rpc_proc) {
case TT_RPC_HDISPATCH:
case TT_RPC_HUPDATE_MSG:
rebind = 1;
/* fall through */
case TT_RPC_DISPATCH_2:
case TT_RPC_DISPATCH_2_WITH_CONTEXT:
case TT_RPC_UPDATE_MSG_2:
case TT_RPC_MSGREAD_2:
tmout = -1;
break;
default:
tmout = TT_RPC_TMOUT;
break;
}
} else {
tmout = timeout;
}
retry = 5;
processing = 1;
status = TT_ERR_NOMP;
while (processing && retry >= 0) {
if (_is_dead) {
// We sometimes hang if we call a dead session
rpc_status = RPC_CANTRECV;
if (! _rpc_client->init(_host, _rpc_program,
_rpc_version,
_server_uid,
_auth)) {
status = TT_ERR_NOMP;
processing = 0;
break;
}
} else {
rpc_status = _rpc_client->call(rpc_proc, xdr_arg_fn,
arg, xdr_res_fn, res,
tmout);
}
switch (rpc_status) {
case RPC_SUCCESS:
status = TT_OK;
processing = 0;
break;
case RPC_CANTRECV:
_is_dead = 1;
status = TT_ERR_NOMP;
retry--;
break;
case RPC_VERSMISMATCH:
case RPC_PROGVERSMISMATCH:
status = TT_ERR_VERSION_MISMATCH;
processing = 0;
break;
case RPC_TIMEDOUT:
if (tmout == 0 || tmout == -1) {
// rpc always returns a timeout error if we're
// in message-passing mode
status = TT_OK;
} else {
// network errors
status = TT_ERR_NOMP;
}
processing = 0;
break;
case RPC_CANTSEND:
if (!rebind) {
status = TT_ERR_NOMP;
retry--;
break;
}
// try to rebind _rpc_client and try again
if (! _rpc_client->init(_host, _rpc_program,
_rpc_version,
_server_uid,
_auth)) {
status = TT_ERR_NOMP;
processing = 0;
break;
}
continue;
case RPC_PROCUNAVAIL:
// We get this if there is a mild version
// mismatch, e.g. a 1.1 library talking to
// a 1.0.x server, and one of the new
// API calls is used. This is relatively
// benign, just let the user know that
// his call is unimplemented in this system
status = TT_ERR_UNIMP;
processing = 0;
break;
case RPC_AUTHERROR:
status = TT_ERR_AUTHORIZATION;
processing = 0;
break;
default:
status = TT_ERR_INTERNAL;
processing = 0;
break;
}
}
if (status == TT_ERR_NOMP &&
!_tt_mp->in_server() &&
!_tt_c_mp->default_c_session.is_null() &&
has_id(_tt_c_mp->default_c_session->address_string())) {
_tt_c_mp->default_c_session = NULL;
}
return(status);
}
//
// Attempts to find the address of the server session. This is done
// according to what kind of environment or session type we're in.
//
Tt_status _Tt_session::
find_advertised_address(_Tt_string &session_addr)
{
switch (env()) {
case _TT_ENV_X11:
if ((! _desktop->get_prop(TT_CDE_XATOM_NAME, session_addr)) &&
(! _desktop->get_prop(TT_XATOM_NAME, session_addr))) {
return(TT_ERR_NOMP);
}
return(TT_OK);
case _TT_ENV_PROCESS_TREE:
if (_address_string.len() == 0) {
session_addr = _tt_get_first_set_env_var(2, TT_CDE_XATOM_NAME, TT_XATOM_NAME);
} else {
session_addr = _address_string;
}
return(TT_OK);
case _TT_ENV_LAST:
default:
return(TT_ERR_NOMP);
}
}
//
// Returns a number indicating what type of session we're in.
//
_Tt_env _Tt_session::
env()
{
if (_tt_mp->in_server()) {
if (_env == _TT_ENV_LAST && getenv("DISPLAY")) {
_env = _TT_ENV_X11;
}
return(_env);
} else if (_env != _TT_ENV_LAST) {
return(_env);
} else {
if (_tt_get_first_set_env_var(2, TT_CDE_XATOM_NAME, TT_XATOM_NAME)) {
return(_env = _TT_ENV_PROCESS_TREE);
} else if (getenv("DISPLAY")) {
return(_env = _TT_ENV_X11);
} else {
return(_TT_ENV_LAST);
}
}
}
//
// Sets the session-type for the session. This affects how the session id
// is advertised to potential clients.
//
void _Tt_session::
set_env(_Tt_env session_env, _Tt_string arg)
{
_env = session_env;
switch (_env) {
case _TT_ENV_X11:
_displayname = arg;
break;
default:
break;
}
}
//
// Returns the ToolTalk session id for the X session named by xdisp. Note
// that no actual contact is attempted.
//
_Tt_string _Tt_session::
Xid(_Tt_string xdisp)
{
return _desktop->session_name(xdisp);
}
/*
void _Tt_session::
print(FILE *fs) const
{
fprintf(fs,"_Tt_session::\n");
}
*/
//
// Used to set or get the address string of a session as well as set
// appropiately the _rpc_version field of the session. If addr_string is
// null, then parsed_address will set the address string of the session.
// In this case, it sets _rpc_version to the default TT_RPC_VERSION. If
// addr_string is not null then parsed_address will attempt to parse the
// string and extract the information in it. In this case, if the
// addr_string happens to be an fcs1 version of session addresses then
// _rpc_version is set to 1, otherwise it is set to TT_RPC_VERSION.
//
// Note that the intended convention for address strings is that only the
// information that is known to this method will be parsed out of them.
// If there is any information beyond that then it is left uninterpreted.
// This means that future ToolTalk versions are free to append
// information to the end of an address string (as is already done
// below) without compromising compatibility with older clients.
//
// Returns:
// TT_OK
// TT_ERR_INVALID Could not parse address
// TT_ERR_NO_MATCH Address version is too new (diagnostic emitted)
//
Tt_status _Tt_session::
parsed_address(_Tt_string &addr_string)
{
#define IPVADDRLEN 16
char session_host[IPVADDRLEN];
char strid[BUFSIZ];
int junk_version = 1;
Tt_status status;
const char *addr_format_fmt = "%%ld %%d %%d %%d %%lu %%%ds %%d";
char addr_format[32];
const char *fcs1_addr_format_fmt = "%%ld %%d %%d %%d %%lu %%%ds";
char fcs1_addr_format[32];
//
// Note: the fcs 1.0 version of tooltalk uses the first 6
// fields in addr_format. Changing these first 6 fields
// compromises binary compatibility with the 1.0 version.
// Additional fields can be added at the end of addr_format as
// long as if the parsing fails then the old format
// (fcs1_addr_format) is tried.
//
_rpc_version = TT_RPC_VERSION;
if (addr_string.len() == 0) {
int ipaddr_len;
// set address string
if (_host.is_null()) {
return(TT_ERR_INTERNAL);
}
if (_host->stringaddr().len() == 0) {
return(TT_ERR_INTERNAL);
}
ipaddr_len = _host->stringaddr().len();
if (ipaddr_len > IPVADDRLEN) ipaddr_len = IPVADDRLEN;
sprintf(fcs1_addr_format, fcs1_addr_format_fmt, ipaddr_len);
sprintf(addr_format, addr_format_fmt, ipaddr_len);
// put version number for format first (this is so we
// can change the format later)
sprintf(strid, "%02d ", _TT_XATOM_VERSION);
sprintf(strid+3, addr_format,
(long)_pid,
_rpc_program,
junk_version,
(int)_auth.auth_level(),
(long)_server_uid,
(char *)_host->stringaddr(),
_rpc_version);
addr_string = strid;
if ((status = _auth.set_sessionid(
_rpc_program,
_auth.auth_level(),
_host->stringaddr(),
_rpc_version)) != TT_OK) {
_tt_syslog(0, LOG_ERR,"_auth.set_sessionid() != TT_OK");
return(status);
}
} else {
// get (parse) address string
char *str = (char *)addr_string;
sprintf(fcs1_addr_format, fcs1_addr_format_fmt, IPVADDRLEN);
sprintf(addr_format, addr_format_fmt, IPVADDRLEN);
// check version number of format first
// XXX: note that if _TT_XATOM_VERSION is ever changed
// then backward compatibility is seriously
// compromised.
if (atoi(str) != _TT_XATOM_VERSION) {
_tt_syslog( 0, LOG_ERR,
catgets( _ttcatd, 1, 15,
"address version is %d, but "
"I only understand %d! (address: "
"<%s>)" ),
atoi(str), _TT_XATOM_VERSION,
addr_string.operator const char *() );
return TT_ERR_NO_MATCH;
}
// XXX: Originally, the fcs1_addr_format put in a
// field describing the rpc version of the server.
// However, the fcs1 version of client_session_init
// erroneously initialized the rpc connection with the
// *server* rpc version rather than its own. Thus we
// can't use the rpc version field in fcs1_addr_format
// because then old fcs1.0 clients would mistakenly
// initialize themselves as version 1+ clients. Thus
// (sigh) we have to add a field at the end of
// fcs1_addr_format that is the real rpc version of
// the server. This is the reason that the first rpc
// version parsed from addr_format is thrown away.
long long_pid;
long long_server_uid;
_Tt_auth_level auth_level;
if (7 != sscanf(str+3, addr_format,
&long_pid,
&_rpc_program,
&junk_version, /* always 1 ... */
&auth_level,
&long_server_uid,
session_host,
&_rpc_version)) {
// new format scan failed. Try to parse the
// string for the old format
if (6 != sscanf(str+3, fcs1_addr_format,
&long_pid,
&_rpc_program,
&_rpc_version,
&auth_level,
&long_server_uid,
session_host)) {
_pid = (pid_t) long_pid;
_server_uid = (uid_t) long_server_uid;
return(TT_ERR_INVALID);
} else {
_rpc_version = 1;
}
}
_pid = (pid_t) long_pid;
_server_uid = (uid_t) long_server_uid;
_hostaddr = session_host;
_auth.set_auth_level(auth_level);
if ((status = _auth.set_sessionid(
_rpc_program,
auth_level,
_hostaddr,
_rpc_version)) != TT_OK) {
_tt_syslog(0, LOG_ERR,"_auth.set_sessionid() != TT_OK");
return(status);
}
}
return(TT_OK);
}
//
// Sets the id of a session. Note that addressing information (the rpc
// number and version) are not part of the id. This makes it possible in
// the future to provide server address rebinding.
//
Tt_status _Tt_session::
set_id(char *id)
{
char host[64];
char dpname[125];
int svnum;
char *ssid;
if (id != (char *)0) {
_id = id;
switch (_id[0]) {
case 'X':
// construct a suitable DISPLAY name from the id
// which should have the format "X <host> <server_num>"
if (sscanf((char *)id, "X %s %d", host, &svnum) != 2) {
return(TT_ERR_SESSION);
}
sprintf(dpname, "%s:%d", host, svnum);
_displayname = dpname;
_server_num = svnum;
_env = _TT_ENV_X11;
break;
case 'P':
// A process-tree session id is just an address string
// preceded by "P ".
_address_string = _id.mid(2, _id.len());
_env = _TT_ENV_PROCESS_TREE;
break;
default:
return(TT_ERR_SESSION);
}
} else {
// set the "id" which is the publicly visible *logical*
// address of this session.
ssid = _tt_get_first_set_env_var(2, TT_CDE_START_SID, TT_START_SID);
if (ssid != (char *)0) {
_id = ssid;
} else {
switch (env()) {
case _TT_ENV_X11:
_type = "X";
if (! _displayname.len()) {
_displayname = _tt_global->xdisplayname;
}
_id = Xid(_displayname);
break;
case _TT_ENV_PROCESS_TREE:
_type = "P";
_server_num = _pid;
// sami said originally:
// we need to include the address string in
// the id of a process-tree session because
// there is no alternate means of finding
// the address (ie. for X11 the id could be
// rid of address info because the X server
// served as the alternate way of finding
// the address).
// rfm sez, 16 June 94:
// Of course that alternate way was a bad
// idea since it means other users can't
// send messages using the session because
// they can't contact the X server.
_id = process_tree_id();
break;
case _TT_ENV_LAST:
default:
return(TT_ERR_INTERNAL);
}
}
}
return(TT_OK);
}
//
// Returns a process-tree id for this session. This is essentially just
// the address of the session preceded by a "P". The purpose of this is
// that whenever this exact session needs to be advertised to a
// persistent medium (as is done with file-scope messages) this version
// of the session id is used so that if the session goes down and comes
// up again, the session id stored on disk will become stale.
//
_Tt_string _Tt_session::
process_tree_id()
{
_Tt_string result = "P ";
return(result.cat(_address_string));
}
bool_t _Tt_session::
xdr(XDR *xdrs)
{
return(_id.xdr(xdrs) && _address_string.xdr(xdrs));
}
_Tt_string _Tt_session::
address_string()
{
return(_address_string);
}
_Tt_string _Tt_session::
displayname()
{
return(_displayname);
}
_Tt_string
_tt_session_address(_Tt_object_ptr &o)
{
return ((_Tt_session *)o.c_pointer())->address_string();
}
//
// Returns 1 if the given id is the same as the id of this session or if
// it is a process-tree id then it has the same address as this session.
//
int _Tt_session::
has_id(const _Tt_string &id)
{
if (id == _id) {
return(1);
}
if (id.len() == 0) {
return(0);
}
if (id == _address_string) {
return(1);
}
if (id[0] == 'P') {
_Tt_string addr = id.mid(2,id.len());
return(addr == _address_string);
}
return(0);
}
// ...for strings list
int _Tt_session::
has_id(const _Tt_string_list_ptr slist_p)
{
_Tt_string_list_cursor c(slist_p);
while (c.next()) {
if (has_id(*c)) {
return(1);
}
}
return(0);
}

View File

@@ -0,0 +1,153 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $TOG: mp_session.h /main/4 1999/08/30 10:59:15 mgreess $ */
/*
* @(#)mp_session.h 1.36 95/01/25
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file contains the implementation of the _Tt_session object which
* represents the minimal message-passing domain. The primary
* responsibility of the _Tt_session is to advertise its presence in
* whatever form is appropriate (ie. as an X atom for X11, in the root
* directory of an NSE environment, etc.). When the _Tt_session object is
* created as part of a client application it represents mostly a
* connection to a _Tt_session object that is part of the message server.
* This server instance is responsible for storing session-queued
* messages, handling RPC requests to the server, and storing client
* properties. When clients will be able to join multiple sessions the
* server instance of _Tt_session will also be responsible for
* forwarding messages to other sessions (ie. the clients still pass
* messages through the same default session (to insure the proper
* flowcontrol) but those messages are passed on to their respective
* sessions.
*/
#ifndef MP_SESSION_H
#define MP_SESSION_H
#include "tt_options.h"
#include "util/tt_host_utils.h"
#include "mp/mp_auth.h"
#include "mp/mp_global.h"
#include "mp/mp_mp.h"
#include "mp/mp_rpc.h"
#include "mp/mp_desktop_utils.h"
#include "mp/mp_rpc_client_utils.h"
#include "mp/mp_session_utils.h"
#include "mp/mp_session_prop_utils.h"
#include "mp/mp_message_utils.h"
#include "mp/mp_pattern_utils.h"
#include "mp/mp_procid_utils.h"
/*
* string used to advertise a tt session in both the X and
* process-tree sessions. Note that in X ICCCM compliance
* dictates that the atom name be prefixed by the vendor
* string. Since there's no good reason for them to be different,
* the same name is used for process-tree sessions.
*/
#define TT_XATOM_NAME "_SUN_TT_SESSION"
#define TT_CDE_XATOM_NAME "TT_SESSION"
#define TT_START_TOKEN "_SUN_TT_TOKEN"
#define TT_CDE_START_TOKEN "TT_TOKEN"
#define TT_FILE_HINT "_SUN_TT_FILE"
#define TT_CDE_FILE_HINT "TT_FILE"
#define TT_START_SID "_SUN_TT_SID"
#define TT_CDE_START_SID "_TT_SID"
enum _Tt_env {
_TT_ENV_X11,
_TT_ENV_PROCESS_TREE,
_TT_ENV_LAST
};
class _Tt_session : public _Tt_object {
public:
_Tt_session();
virtual ~_Tt_session();
_Tt_string address_string();
_Tt_string auth_cookie() {
return _auth.auth_cookie();
}
_Tt_auth_level auth_level() {
return _auth.auth_level();
}
Tt_status call(int rpc_proc,
xdrproc_t xdr_arg_fn, char *arg,
xdrproc_t xdr_res_fn, char *res,
int timeout = -1, int rebind = 0);
_Tt_env env();
const _Tt_host_ptr &host() {
return _host;
}
const _Tt_string &id() const {
return _id;
}
Tt_status ping();
//void print(FILE *fs = stdout) const;
int rpc_program() {
return _rpc_program;
}
int rpc_version() {
return _rpc_version;
}
Tt_status set_auth_level(_Tt_auth_level auth_level) {
return _auth.set_auth_level(auth_level);
}
void set_env(_Tt_env env, _Tt_string arg);
_Tt_string Xid(_Tt_string xdisp);
bool_t xdr(XDR *xdrs);
int desktop_event_callback();
_Tt_string displayname();
Tt_status set_id(char *sid = (char *)0);
Tt_status client_session_init();
_Tt_string process_tree_id();
// Determine if this session is in a list of sessions.
int has_id(const _Tt_string &id);
int has_id(const _Tt_string_list_ptr slist_p);
protected:
Tt_status auto_start_init();
Tt_status client_session_init_byid(_Tt_string sid);
Tt_status find_advertised_address(_Tt_string &addr);
Tt_status parsed_address(_Tt_string &session_addr);
//
// state variables
//
_Tt_string _address_string;
_Tt_auth _auth;
_Tt_string _displayname;
_Tt_env _env;
_Tt_host_ptr _host;
_Tt_string _hostaddr;
_Tt_string _id;
int _is_server;
int _is_dead;
pid_t _pid;
_Tt_session_prop_list_ptr _properties;
_Tt_message_list_ptr _queued_messages;
_Tt_rpc_client_ptr _rpc_client;
int _rpc_program;
int _rpc_version;
pid_t _server_num;
uid_t _server_uid;
_Tt_string _type;
_Tt_desktop_ptr _desktop;
#ifdef OPT_UNIX_SOCKET_RPC
int _u_sock;
char *local_socket_name();
_Tt_string _socket_name;
#endif /* OPT_UNIX_SOCKET_RPC */
friend class _Tt_s_mp;
friend class _Tt_s_session;
friend _Tt_mp::find_session_by_fd(int, _Tt_session_ptr &);
};
_Tt_string _tt_session_address(_Tt_object_ptr &o);
#endif /* MP_SESSION_H */

View File

@@ -0,0 +1,39 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_session_prop.C /main/3 1995/10/23 10:29:02 rswiston $
/*
*
* mp_session_prop.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include "mp/mp_session_prop.h"
#include "util/tt_string.h"
_Tt_session_prop::
_Tt_session_prop()
{
}
_Tt_session_prop::
_Tt_session_prop(_Tt_string name, _Tt_string_list_ptr values)
{
_name = name;
_values = values;
}
_Tt_session_prop::
_Tt_session_prop(_Tt_string name, _Tt_string value)
{
_name = name;
_values = new _Tt_string_list();
_values->append(value);
}
_Tt_session_prop::
~_Tt_session_prop()
{
}

View File

@@ -0,0 +1,28 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_session_prop.h /main/3 1995/10/23 10:29:09 rswiston $ */
/*
*
* mp_session_prop.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#if !defined(_MP_SESSION_PROP_H)
#define _MP_SESSION_PROP_H
#include "util/tt_string.h"
class _Tt_session_prop : public _Tt_object {
public:
_Tt_session_prop();
_Tt_session_prop(_Tt_string name, _Tt_string_list_ptr values);
_Tt_session_prop(_Tt_string name, _Tt_string value);
virtual ~_Tt_session_prop();
_Tt_string _name;
_Tt_string_list_ptr _values;
};
#endif

View File

@@ -0,0 +1,16 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_session_prop_utils.C /main/3 1995/10/23 10:29:16 rswiston $
/*
*
* mp_session_prop_utils.cc
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#include "mp/mp_session_prop.h"
#include "mp/mp_session_prop_utils.h"
implement_list_of(_Tt_session_prop)

View File

@@ -0,0 +1,21 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_session_prop_utils.h /main/3 1995/10/23 10:29:23 rswiston $ */
/*
*
* mp_session_prop_utils.h
*
* Copyright (c) 1992 by Sun Microsystems, Inc.
*/
#if !defined(_MP_SESSION_PROP_UTILS_H)
#define _MP_SESSION_PROP_UTILS_H
#include "util/tt_list.h"
class _Tt_session_prop;
declare_list_of(_Tt_session_prop)
#endif

View File

@@ -0,0 +1,17 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_session_utils.C /main/3 1995/10/23 10:29:30 rswiston $
/*
*
* mp_session_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of auxilliary data structures for the _Tt_session class
*/
#include <mp/mp_session.h>
implement_list_of(_Tt_session)
implement_table_of(_Tt_session)

View File

@@ -0,0 +1,24 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_session_utils.h /main/3 1995/10/23 10:29:36 rswiston $ */
/*
*
* mp_session_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* Declaration of auxilliary data structures for the _Tt_session class
*/
#ifndef MP_SESSION_UTILS_H
#define MP_SESSION_UTILS_H
#include <util/tt_object.h>
#include <util/tt_string.h>
#include <util/tt_table.h>
class _Tt_session;
declare_list_of(_Tt_session)
declare_table_of(_Tt_session)
#endif /* MP_SESSION_UTILS_H */

View File

@@ -0,0 +1,590 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $TOG: mp_stream_socket.C /main/10 1998/03/19 18:58:53 mgreess $
/*
*
* mp_socket.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include "tt_options.h"
#include <stdio.h>
#include "mp/mp_stream_socket.h"
#if defined(linux)
#include <sys/poll.h>
#else
#include <poll.h>
#endif
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#include <errno.h>
#include "util/tt_global_env.h"
#include "util/tt_host.h"
#include "util/tt_port.h"
#if defined(OPT_TLI)
# include <mp/mp_rpc_fns.h>
# include <tiuser.h>
# if defined(OPT_BUG_USL)
extern int t_errno;
# endif
#else
# include <netinet/tcp.h>
#endif
#include <sys/time.h>
#if defined(ultrix)
extern "C" unsigned long inet_addr(char *);
#endif
#include <arpa/inet.h>
#if defined(OPT_BUG_USL)
extern char *t_errlist[];
char *t_strerror(int t_errno)
{
return(t_errlist[t_errno]);
}
#endif
/*
* Constructs a socket object. Using (char *)0 for host means use the
* current host. Specifying a portnum of 0 indicates that the first
* available port number should be chosen.
*/
_Tt_stream_socket::
_Tt_stream_socket()
{
}
_Tt_stream_socket::
_Tt_stream_socket(_Tt_host_ptr &host, int portnum)
{
_msgsock = -1;
_host = host;
memset(&_hostaddr, 0, sizeof(_hostaddr));
_hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);
_hostaddr.sin_port = htons(portnum);
_hostaddr.sin_family = AF_INET;
}
/*
* Closes the connection on the socket.
*/
_Tt_stream_socket::
~_Tt_stream_socket()
{
#ifndef OPT_TLI
close(_sock);
close(_msgsock);
#else
t_close(_sock);
if (_msgsock != _sock) {
t_close(_msgsock);
}
#endif
}
int _Tt_stream_socket::
sock()
{
return(_sock);
}
/*
* Returns the file descriptor associated with a socket.
*/
int _Tt_stream_socket::
fd()
{
if (_is_source) {
if ((_msgsock != -1) || (accept() != -1)) {
return(_msgsock);
} else {
return(-1);
}
} else {
return(_sock);
}
}
/*
* Returns the external port number attached to a socket.
*/
int _Tt_stream_socket::
port()
{
#if defined(OPT_TLI)
return(_port);
#else
return((int)ntohs(_hostaddr.sin_port));
#endif
}
/*
* Initializes a stream socket. This method must be called before using a
* socket to receive messages. The method assumes that if hostname is
* (char *)0 then this is the "from" end of a socket. Otherwise, it is
* assumed that this is an object which connects to a socket (presumed
* already open) on the host named in _host.
*/
int _Tt_stream_socket::
init(int init_as_source)
{
_Tt_host host;
#if defined(OPT_TLI)
_sock = t_open("/dev/tcp", O_RDWR, 0);
if (_sock < 0) {
_tt_syslog( 0, LOG_ERR,
"_Tt_stream_socket::init(): t_open(): %s",
t_strerror( t_errno ) );
return 0;
}
#else
int len;
int optval;
_sock = socket(AF_INET, SOCK_STREAM, 0);
if (_sock < 0) {
_tt_syslog( 0, LOG_ERR,
"_Tt_stream_socket::init(): socket(): %m" );
return 0;
}
#endif
if (-1==fcntl(_sock, F_SETFD, 1)) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"fcntl(F_SETFD): %m");
}
_is_source = init_as_source;
if (init_as_source) { /* 'from' end of socket */
#if !defined(OPT_TLI)
optval = 1;
#ifndef linux
if (setsockopt(_sock, SOL_SOCKET, SO_USELOOPBACK,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"setsockopt(SO_USELOOPBACK): %m" );
close(_sock);
return(0);
}
#endif
if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"setsockopt(TCP_NODELAY): %m" );
}
if (bind(_sock, (struct sockaddr *)&_hostaddr,
sizeof(_hostaddr)) < 0) {
close(_sock);
return(0);
}
len = sizeof(sockaddr_in);
#if defined(_AIX) && (OSMAJORVERSION==4) && (OSMINORVERSION==2)
if (getsockname(_sock, (sockaddr *)&_hostaddr, (size_t *)&len)
< 0) {
#else
if (getsockname(_sock, (sockaddr *)&_hostaddr, &len) < 0) {
#endif
return(0);
}
return(listen(_sock,5) == 0);
#else
struct t_bind *bind;
if ((bind = (struct t_bind *)t_alloc(_sock, T_BIND, T_ADDR)) ==
(struct t_bind *)0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_alloc(T_BIND): %s",
t_strerror( t_errno ) );
return(0);
}
// We use random port selection.
// This means that we always let t_bind choose a
// suitable port number for us and we ignore the
// portnum argument given in the constructor for this
// class. If we were ever to claim _Tt_stream_socket
// as a general C++ wrapper class for socket/TLI, this
// would have to change.
bind->addr.len = 0;
bind->qlen = 8;
if (t_bind(_sock, bind, bind) < 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_bind(): %s", t_strerror( t_errno ) );
t_free((char *)bind, T_BIND);
return(0);
}
_port = ntohs(((sockaddr_in *)(bind->addr.buf))->sin_port);
t_free((char *)bind, T_BIND);
_srequest = (struct t_call *)t_alloc(_sock, T_CALL, T_ADDR);
if (_srequest == (t_call *)0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_alloc(T_CALL): %s",
t_strerror( t_errno ) );
return(0);
}
#endif // !OPT_TLI
} else { // 'to' end of socket
//
// If both Client and Server or (To and From) sockets are
// on the same host, it is better to use the localhost ip
// address. This removes ToolTalks dependency on the state
// of the network and permits standalone operation.
//
// In this instance 'local_host' is the host where ttsession
// is running. '_host' is the host where the 'procid'
// proccess is running. If both are on the same host, copy
// in the the localhost ip address rather than the actual
// "configured" ip address.
//
_Tt_host_ptr local_host;
if ( (_tt_global->get_local_host(local_host) ) &&
( _host->stringaddr() == local_host->stringaddr() ) ) {
//
// _host_ == local_host => (both on same host)
//
_hostaddr.sin_addr.s_addr = inet_addr((char *)"127.0.0.1");
} else {
//
// _host_ != local_host => (on different hosts)
//
memcpy((char *)&_hostaddr.sin_addr,
(char *)_host->addr(),
_host->addr_length());
}
#if !defined(OPT_TLI)
// set up socket options to insure that a close will
// immediately send the message to a socket. This is
// essential for the use of sockets as signalling
// mechanisms.
if (setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"setsockopt(TCP_NODELAY): %m" );
}
#ifndef linux
if (setsockopt(_sock, SOL_SOCKET, SO_USELOOPBACK,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"setsockopt(SO_USELOOPBACK): %m" );
close(_sock);
return(0);
}
#endif
if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"setsockopt(SO_REUSEADDR): %m" );
close(_sock);
return(0);
}
#if defined(sun)
// XXX: It's not at all clear that we need to do this
// anywhere.. default seems to be don't linger anyway.
if (setsockopt(_sock, SOL_SOCKET, ~SO_LINGER,
(char *)&optval, sizeof(int)) == -1) {
_tt_syslog( 0, LOG_WARNING, "_Tt_stream_socket::init(): "
"setsockopt(~SO_LINGER): %m" );
}
#endif // sun
if (connect(_sock,
(struct sockaddr *)&_hostaddr,
sizeof(_hostaddr)) < 0) {
close(_sock);
return(0);
}
#else
t_call *sndcall, *rcvcall;
if (t_bind(_sock, 0, 0) < 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_bind(,0,0): %s", t_strerror( t_errno ) );
return(0);
}
(void)_tt_tli_set_nodelay(_sock);
sndcall = (t_call *)t_alloc(_sock, T_CALL, 0);
if (sndcall == 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_alloc(T_CALL,0): %s",
t_strerror( t_errno ) );
return(0);
}
sndcall->addr.maxlen = sizeof(_hostaddr);
sndcall->addr.len = sizeof(_hostaddr);
sndcall->addr.buf = (char *)&_hostaddr;
sndcall->opt.len = 0;
sndcall->udata.len = 0;
rcvcall = (t_call *)t_alloc(_sock, T_CALL, T_OPT|T_ADDR);
if (rcvcall == 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::init(): "
"t_alloc(T_CALL, T_OPT|T_ADDR): %s",
t_strerror( t_errno ) );
if (t_free((char *)sndcall, T_CALL) < 0) {
_tt_syslog( 0, LOG_ERR, "t_free(): %s",
t_strerror( t_errno ) );
}
return(0);
}
rcvcall->udata.maxlen = 0;
if (t_connect(_sock, sndcall, rcvcall) < 0) {
_tt_syslog( 0, LOG_ERR, "t_connect(): %s",
t_strerror( t_errno ) );
sndcall->addr.buf = 0;
if (t_free((char *)sndcall, T_CALL) < 0) {
_tt_syslog( 0, LOG_ERR, "t_free(sndcall): %s",
t_strerror( t_errno ) );
}
if (t_free((char *)rcvcall, T_CALL) < 0) {
_tt_syslog( 0, LOG_ERR, "t_free(rcvcall): %s",
t_strerror( t_errno ) );
}
t_close(_sock);
return(0);
}
sndcall->addr.buf = 0;
if (t_free((char *)sndcall, T_CALL) < 0) {
_tt_syslog( 0, LOG_ERR, "t_free(sndcall): %s",
t_strerror( t_errno ) );
}
if (t_free((char *)rcvcall, T_CALL) < 0) {
_tt_syslog( 0, LOG_ERR, "t_free(rcvcall): %s",
t_strerror( t_errno ) );
}
#endif // !OPT_TLI
}
return(1);
}
/*
* Sends a message to a socket. Since the socket object is used by the mp
* primarily to signal clients, a close is done after the write to insure
* the message gets flushed out to the receiving socket.
*
* --> It would be extremely helpful if all the really "fatal" cases of
* failing to write to a socket can be identified since this information
* could be fed back to the mp server to determine when a process has
* died or is no longer listening on a socket.
*/
int _Tt_stream_socket::
send(char *msg, int len)
{
int rval;
#ifndef OPT_TLI
if ((rval = ::send(_sock, msg, len, 0)) == len) {
return(rval);
} else {
close(_sock);
return(0);
}
#else
#if defined(OPT_BUG_USL)
t_sync(_sock);
#endif
if ((rval = t_snd(_sock, msg, len, 0)) == len) {
return(rval);
} else {
_tt_syslog(0, LOG_ERR,
"==> ERROR FROM SEND: len = %d, rval = %d, err = %d\n",
len, rval, t_errno);
t_close(_sock);
return(0);
}
#endif // !OPT_TLI
}
int _Tt_stream_socket::
accept()
{
if (_msgsock == -1) {
#ifndef OPT_TLI
int addrlen = sizeof(sockaddr_in);
sockaddr_in saddr;
#if defined(_AIX) && (OSMAJORVERSION==4) && (OSMINORVERSION==2)
_msgsock = ::accept(_sock, (struct sockaddr *)&saddr,
(size_t *)&addrlen);
#else
_msgsock = ::accept(_sock, (struct sockaddr *)&saddr,
&addrlen);
#endif
if (_msgsock < 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::accept(): "
"accept(): %m" );
return -1;
}
if (-1==fcntl(_msgsock, F_SETFD, 1)) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::accept(): "
"fcntl(F_SETFD): %m");
}
#else
int rval;
struct t_call *call_data;
struct t_bind *bind_data;
call_data = (struct t_call *)t_alloc(_sock, T_CALL, T_ALL);
if (t_listen(_sock, call_data) < 0) {
_Tt_string errstr(t_strerror(t_errno));
if (t_errno == TSYSERR) {
// Add in errno info
errstr = errstr.cat(": ").cat(strerror(errno));
}
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::accept(): "
"t_listen(): %s", (char *) errstr );
return(-1);
}
// Since we expect no further connections on this
// endpoint, it would theoretically be possible
// to use the same fd in arg 1 and arg 2 of t_accept.
// This appears to be an actual advantage of TLI over
// sockets -- I don't think you can do this with
// sockets. However, I can't get it to work!
// So what I do is open a new endpoint, accept to
// that, and then close the original fd since we
// don't need it any more.
_msgsock = t_open("/dev/tcp", O_RDWR, 0);
if (_msgsock < 0) {
_tt_syslog( 0, LOG_ERR,
"_Tt_stream_socket::accept(): "
"t_open(): %s",
t_strerror( t_errno ) );
t_free((char *)call_data, T_CALL);
return -1;
}
bind_data = (struct t_bind *)t_alloc(_msgsock, T_BIND, T_ALL);
if (t_bind(_msgsock, bind_data, bind_data) < 0) {
_tt_syslog( 0, LOG_ERR, "_Tt_stream_socket::accept(): "
"t_bind(): %s", t_strerror( t_errno ) );
if (bind_data) t_free((char *)bind_data, T_BIND);
if (call_data) t_free((char *)call_data, T_CALL);
return -1;
}
rval = t_accept(_sock, _msgsock, call_data);
if (rval == -1) {
_tt_syslog( 0, LOG_ERR, "t_accept(): %s",
t_strerror( t_errno ) );
t_free((char *)bind_data, T_BIND);
t_free((char *)call_data, T_CALL);
return(-1);
} else {
(void)_tt_tli_set_nodelay(_msgsock);
if (-1==fcntl(_msgsock, F_SETFD, 1)) {
_tt_syslog( 0, LOG_ERR,
"_Tt_stream_socket::accept(): "
"fcntl(F_SETFD): %m");
}
}
t_free((char *)bind_data, T_BIND);
t_free((char *)call_data, T_CALL);
t_close(_sock);
_sock = _msgsock;
#endif // !OPT_TLI
}
return(_msgsock);
}
/*
* Receives a message from a socket. This method will block if there is
* no input so if nonblocking is required it should be called only after
* the socket fd has been checked for activity.
*
* --> sockets can be set to be nonblocking. Should this be the default
* for the sockets the mp opens?
*/
int _Tt_stream_socket::
recv(char *msg, int msglen)
{
int rval;
if (_msgsock == -1 && accept() == -1) {
return(-1);
}
#ifndef OPT_TLI
if ((rval = ::recv(_msgsock, msg, msglen, 0)) < 0) {
close(_msgsock);
return(-1);
}
#else
int flags;
rval = t_rcv(_msgsock, msg, msglen, &flags);
if (rval == -1) {
if (t_errno == TLOOK) {
if (t_look(_msgsock) == T_DISCONNECT &&
t_rcvdis(_msgsock,(struct t_discon *)0) < 0) {
_tt_syslog( 0, LOG_ERR, "t_rcvdis(): %s",
t_strerror( t_errno ) );
return(-1);
} else {
return(0);
}
} else {
_tt_syslog( 0, LOG_ERR, "t_rcv(): %s",
t_strerror( t_errno ) );
return(-1);
}
}
#endif // !OPT_TLI
msg[rval] = 0;
return(rval);
}
// read_would_block is not a predicate. It returns 1 if a read
// is safe (would not block. It returns 0 if a read would block,
// and -1 if there is some error condition.
int _Tt_stream_socket::
read_would_block()
{
struct pollfd fds[1];
fds[0].fd = _msgsock;
fds[0].events = POLLIN;
fds[0].revents = 0;
while(-1 == poll(fds, (sizeof fds)/(sizeof (struct pollfd)), 0)) {
if (errno==EAGAIN || errno==EINTR) {
// interrupted, try again.
} else {
// something is wrong
return -1;
}
}
if (0 != (fds[0].revents & (POLLHUP|POLLNVAL|POLLERR)) ) {
return -1;
} else if (0 != (fds[0].revents & POLLIN) ) {
return 1;
} else {
return 0;
}
}

View File

@@ -0,0 +1,57 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_stream_socket.h /main/3 1995/10/23 10:29:57 rswiston $ */
/*
* mp_stream_socket.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*
* This file implements the _Tt_stream_socket which is an object used to
* deal with TCP sockets. The methods for this object handle creation,
* destruction and communicating over TCP sockets. Note that the
* implementation of stream sockets is tailored specifically to the use
* of sockets by the MP as a signalling mechanism. The methods here are
* not intended to be a general C++ wrapper for sockets.
*/
#ifndef MP_STREAM_SOCKET_H
#define MP_STREAM_SOCKET_H
#include <sys/types.h>
#include <tt_options.h>
#ifdef OPT_TLI
# include <tiuser.h>
#endif
#include <netinet/in.h>
#include <util/tt_object.h>
#include <util/tt_ptr.h>
#include <util/tt_host_utils.h>
class _Tt_stream_socket : public _Tt_object {
public:
_Tt_stream_socket();
_Tt_stream_socket(_Tt_host_ptr &host, int port);
virtual ~_Tt_stream_socket();
int init(int init_as_source);
int send(char *msg, int len);
int recv(char *msg, int len);
int port();
int fd();
int sock();
int read_would_block();
private:
int accept();
int _is_source;
int _msgsock;
int _sock;
_Tt_host_ptr _host;
sockaddr_in _hostaddr;
#ifdef OPT_TLI
int _port;
t_call *_srequest;
#endif /* OPT_TLI */
};
#endif /* MP_STREAM_SOCKET_H */

View File

@@ -0,0 +1,15 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_stream_socket_utils.C /main/3 1995/10/23 10:30:06 rswiston $
/*
*
* mp_stream_socket_utils.cc
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#include <mp/mp_stream_socket_utils.h>
#include <mp/mp_stream_socket.h>
implement_ptr_to(_Tt_stream_socket)

View File

@@ -0,0 +1,19 @@
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: mp_stream_socket_utils.h /main/3 1995/10/23 10:30:16 rswiston $ */
/*
*
* mp_stream_socket_utils.h
*
* Copyright (c) 1990 by Sun Microsystems, Inc.
*/
#ifndef MP_STREAM_SOCKET_UTILS_H
#define MP_STREAM_SOCKET_UTILS_H
#include <util/tt_object.h>
class _Tt_stream_socket;
declare_ptr_to(_Tt_stream_socket)
#endif /* MP_STREAM_SOCKET_UTILS_H */

View File

@@ -0,0 +1,40 @@
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
//%% (c) Copyright 1993, 1994 Novell, Inc.
//%% $XConsortium: mp_trace.C /main/4 1995/11/21 19:25:54 cde-sun $
/*
* @(#)mp_trace.cc 1.2 93/08/15
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*/
#include "mp/mp_trace.h"
_Tt_msg_trace::_Tt_msg_trace(
_Tt_message &msg,
_Tt_dispatch_reason reason
)
{
entry( msg, reason );
}
_Tt_msg_trace::_Tt_msg_trace(
_Tt_message &msg,
const _Tt_procid &recipient
)
{
entry( msg, recipient );
}
_Tt_msg_trace::_Tt_msg_trace(
_Tt_message &msg,
Tt_state old_state
)
{
entry( msg, old_state );
}
_Tt_msg_trace::~_Tt_msg_trace()
{
exitq();
}

Some files were not shown because too many files have changed in this diff Show More