Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
57
cde/lib/DtSvc/DtEncap/Imakefile
Normal file
57
cde/lib/DtSvc/DtEncap/Imakefile
Normal file
@@ -0,0 +1,57 @@
|
||||
XCOMM $XConsortium: Imakefile /main/7 1996/08/22 09:10:00 rswiston $
|
||||
XCOMM (c) Copyright 1996 Digital Equipment Corporation.
|
||||
XCOMM (c) Copyright 1993-1994,1996 Hewlett-Packard Company.
|
||||
XCOMM (c) Copyright 1993-1994,1996 International Business Machines Corp.
|
||||
XCOMM (c) Copyright 1993-1994,1996 Sun Microsystems, Inc.
|
||||
XCOMM (c) Copyright 1993-1994,1996 Novell, Inc.
|
||||
XCOMM (c) Copyright 1996 FUJITSU LIMITED.
|
||||
XCOMM (c) Copyright 1996 Hitachi.
|
||||
|
||||
#define DoNormalLib NormalLibDtSvc
|
||||
#define DoSharedLib SharedLibDtSvc
|
||||
#define DoDebugLib DebugLibDtSvc
|
||||
#define DoProfileLib ProfileLibDtSvc
|
||||
#define LibName DtSvc
|
||||
#define SoRev SODTSVCREV
|
||||
#define LibHeaders NO
|
||||
#define LibCreate NO
|
||||
|
||||
#include <Threads.tmpl>
|
||||
|
||||
#ifndef DtSvcDefines
|
||||
# define DtSvcDefines -DXK_MISCELLANY -DMULTIBYTE
|
||||
#endif
|
||||
DEFINES = DtSvcDefines \
|
||||
-DCDE_CONFIGURATION_TOP=\"$(CDE_CONFIGURATION_TOP)\" \
|
||||
-DCDE_INSTALLATION_TOP=\"$(CDE_INSTALLATION_TOP)\" \
|
||||
-DCDE_LOGFILES_TOP=\"$(CDE_LOGFILES_TOP)/tmp\"
|
||||
|
||||
INCLUDES = -I. -I../include -I../DtUtil2
|
||||
|
||||
|
||||
SRCS = MemoryMgr.c SbEvent.c Symbolic.c bmsglob.c \
|
||||
connect.c local.c nls.c noio.c \
|
||||
pathwexp.c pipe.c pty.c remote.c \
|
||||
sbstdinc.c scoop.c spc-env.c spc-error.c \
|
||||
spc-exec.c spc-net.c spc-obj.c spc-proto.c \
|
||||
spc-sm.c spc-termio.c spc-util.c spc-xt.c \
|
||||
spc.c stringbuf.c usersig.c
|
||||
|
||||
/* WARNING!!!!
|
||||
* Any .o's added to this list need to be added to DTENCAP_OBJS4
|
||||
* and SHARED_DTENCAP_OBJS4 in the DtSvc Imakefile.
|
||||
*/
|
||||
OBJS = MemoryMgr.o SbEvent.o Symbolic.o bmsglob.o \
|
||||
connect.o local.o nls.o noio.o \
|
||||
pathwexp.o pipe.o pty.o remote.o \
|
||||
sbstdinc.o scoop.o spc-env.o spc-error.o \
|
||||
spc-exec.o spc-net.o spc-obj.o spc-proto.o \
|
||||
spc-sm.o spc-termio.o spc-util.o spc-xt.o \
|
||||
spc.o stringbuf.o usersig.o
|
||||
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
SubdirLibraryRule($(OBJS))
|
||||
|
||||
DependTarget()
|
||||
54
cde/lib/DtSvc/DtEncap/MemoryMgr.c
Normal file
54
cde/lib/DtSvc/DtEncap/MemoryMgr.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* File: MemoryMgr.c $XConsortium: MemoryMgr.c /main/3 1995/10/26 15:34:54 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#ifdef DOMAIN_ALLOW_MALLOC_OVERRIDE
|
||||
#include "/usr/include/apollo/shlib.h"
|
||||
#endif
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <bms/bms.h>
|
||||
#include <bms/XeUserMsg.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CPLUSPLUS_MALLOC_TYPE (malloc_t)
|
||||
#else
|
||||
#define CPLUSPLUS_MALLOC_TYPE
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
void * XeMalloc( size_t size )
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString ptr;
|
||||
|
||||
if (!size) return 0;
|
||||
if (ptr = malloc(size)) {
|
||||
*ptr = (XeChar)NULL; /* Force first byte to NULL for bozos who */
|
||||
/* think malloc zeros memory! */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
_DtSimpleError(XeProgName, XeError, XeString_NULL,
|
||||
"><DtEncap: cannot malloc memory");
|
||||
exit(1);
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
void XeFree( void * ptr )
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
if (ptr)
|
||||
free((char *)ptr);
|
||||
}
|
||||
63
cde/lib/DtSvc/DtEncap/SbEvent.c
Normal file
63
cde/lib/DtSvc/DtEncap/SbEvent.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* File: SbEvent.c $XConsortium: SbEvent.c /main/3 1995/10/26 15:35:08 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1990, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define __need_fd_set
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <errno.h>
|
||||
|
||||
typedef char Boolean;
|
||||
#include <bms/XeUserMsg.h>
|
||||
|
||||
#ifdef _AIX
|
||||
/*
|
||||
* The AIX compiler gives an internal error if it includes
|
||||
* <bms/SbEvent.h>. The required typedefs were removed from
|
||||
* this header and placed within this file.
|
||||
*/
|
||||
typedef void (*SbInputCallbackProc) ();
|
||||
typedef unsigned long SbInputId;
|
||||
#else
|
||||
#include <bms/SbEvent.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h> /* for fd_set, FD_SET macros, et. al. */
|
||||
|
||||
SbInputId (*SbAddInput_hookfn) (
|
||||
int fd,
|
||||
SbInputCallbackProc proc,
|
||||
void* data) = NULL;
|
||||
|
||||
SbInputId (*SbAddException_hookfn) (
|
||||
int fd,
|
||||
SbInputCallbackProc proc,
|
||||
void* data) = NULL;
|
||||
|
||||
void (*SbRemoveInput_hookfn) (
|
||||
SbInputId id) = NULL;
|
||||
|
||||
void (*SbRemoveException_hookfn) (
|
||||
SbInputId id) = NULL;
|
||||
|
||||
void (*SbMainLoopUntil_hookfn) (
|
||||
Boolean *flag) = NULL;
|
||||
|
||||
void (*SbBreakMainLoop_hookfn) (
|
||||
void) = NULL;
|
||||
|
||||
/* spcd calls this guy */
|
||||
|
||||
void XeCall_SbMainLoopUntil(Boolean *flag)
|
||||
{
|
||||
(*SbMainLoopUntil_hookfn)(flag);
|
||||
}
|
||||
|
||||
464
cde/lib/DtSvc/DtEncap/Symbolic.c
Normal file
464
cde/lib/DtSvc/DtEncap/Symbolic.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* File: Symbolic.c $XConsortium: Symbolic.c /main/5 1996/09/27 19:00:23 drk $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#ifdef __osf__
|
||||
#define SBSTDINC_H_NO_REDEFINE
|
||||
#endif
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <bms/bms.h>
|
||||
#include <bms/XeUserMsg.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
#include <bms/Symbolic.h>
|
||||
|
||||
#include <codelibs/stringx.h> /* strhash */
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* HASHING */
|
||||
|
||||
/* This is the default symbol table to use */
|
||||
/* --------------------------------------- */
|
||||
#define XE_END_OF_HASH_TABLE (XeSymtabList) -1
|
||||
|
||||
static XeSymTable D_sym_table = NULL;
|
||||
|
||||
typedef struct _unknown_entry_data {
|
||||
XeString name;
|
||||
} *unknown_entry_data;
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* Symbol (hash) Table */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static unsigned int
|
||||
keyhash(XeSymTable t, void *key)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
unsigned int hash;
|
||||
|
||||
if (t->hash_fn)
|
||||
{
|
||||
hash = t->hash_fn( key, t->hashsize );
|
||||
if (hash >= t->hashsize)
|
||||
_DtSimpleError(XeProgName, XeInternalError, NULL,
|
||||
(XeString) "Symbolic.c: Hash value from user hash function out of range",
|
||||
NULL);
|
||||
/* We don't come back from the error routine */
|
||||
}
|
||||
else
|
||||
{
|
||||
hash = strhash( (const char *) key );
|
||||
hash = hash & (t->hashsize - 1);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static unsigned int
|
||||
trap_bad_hash_fn(void * UNUSED_PARM(ptr), unsigned int UNUSED_PARM(size))
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
_DtSimpleError(XeProgName, XeInternalError, NULL,
|
||||
(XeString) "Symbolic.c: Hash table at must be power of 2",
|
||||
NULL);
|
||||
/* We don't come back from the error routine */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeSymTable
|
||||
Xe_new_symtab(unsigned int hashsize)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
|
||||
/* Note, hashsize must be power of 2 if using default hash function */
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
XeSymTable t = (XeSymTable) XeMalloc( sizeof (struct _XeSymTable) );
|
||||
t->hashsize = hashsize;
|
||||
|
||||
t->list = (XeSymtabList *)XeMalloc( sizeof( XeSymtabList ) * hashsize );
|
||||
|
||||
for (i = 0; i < hashsize; i++)
|
||||
t->list[i] = (XeSymtabList)NULL;
|
||||
|
||||
t->curr_list = XE_END_OF_HASH_TABLE;
|
||||
t->curr_hash = 0;
|
||||
|
||||
Xe_set_sym_fns(t,
|
||||
(XeSymFn_cmp)NULL,
|
||||
(XeSymFn_init)NULL,
|
||||
(XeSymFn_clean)NULL,
|
||||
(XeSymFn_hash)NULL);
|
||||
|
||||
/* If not a power of two, user better have a hash function */
|
||||
/* that handles that. Install hash function trap so that if */
|
||||
/* he does not install one, we catch it. */
|
||||
/* --------------------------------------------------------- */
|
||||
if (hashsize & (hashsize - 1))
|
||||
t->hash_fn = trap_bad_hash_fn;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeSymTable
|
||||
Xe_default_symtab(void)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
#define D_HASHSIZE 256
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (D_sym_table) {
|
||||
_DtSvcProcessUnlock();
|
||||
return D_sym_table;
|
||||
}
|
||||
|
||||
D_sym_table = Xe_new_symtab(D_HASHSIZE);
|
||||
_DtSvcProcessUnlock();
|
||||
return(D_sym_table);
|
||||
}
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static XeSymtabList
|
||||
NukeOneItem(XeSymTable t, XeSymtabList l)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeSymtabList next;
|
||||
|
||||
/* For standard XeSymbols: */
|
||||
/* 1) Free the name */
|
||||
/* 2) Call free function if configured */
|
||||
/* 3) Free the XeSymbol entry */
|
||||
/* ---------------------------------------- */
|
||||
if (l->data_is_XeSymbol)
|
||||
{
|
||||
XeFree( ((XeSymbol)l->data)->name );
|
||||
if (t->clean_fn)
|
||||
t->clean_fn( ((XeSymbol)l->data)->value );
|
||||
XeFree( l->data );
|
||||
}
|
||||
/* For "anysym" symbols: */
|
||||
/* 1) Call free function if configured */
|
||||
/* 2) If we malloced the data, free it */
|
||||
/* ---------------------------------------- */
|
||||
else
|
||||
{
|
||||
if (t->clean_fn)
|
||||
t->clean_fn( l->data );
|
||||
|
||||
if (l->data_is_malloc_mem)
|
||||
XeFree(l->data);
|
||||
}
|
||||
|
||||
next = l->rest;
|
||||
XeFree(l);
|
||||
return next;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeSymTable
|
||||
Xe_set_sym_fns(XeSymTable t,
|
||||
XeSymFn_cmp cmp_fn,
|
||||
XeSymFn_init init_fn,
|
||||
XeSymFn_clean clean_fn,
|
||||
XeSymFn_hash hash_fn)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
if (!t) t = Xe_default_symtab();
|
||||
|
||||
t->cmp_fn = cmp_fn;
|
||||
t->init_fn = init_fn;
|
||||
t->clean_fn = clean_fn;
|
||||
t->hash_fn = hash_fn;
|
||||
return(t);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static XeSymbol
|
||||
make_sym(XeString name)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeSymbol sym = Xe_make_struct(_XeSymbol);
|
||||
|
||||
sym->name = strdup( name );
|
||||
sym->value = (void*)NULL;
|
||||
return sym;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static void *
|
||||
intern_something(XeSymTable t,
|
||||
void * data,
|
||||
unsigned int size,
|
||||
Boolean is_XeSymbol,
|
||||
Boolean lookup_only,
|
||||
int *bucket)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
unsigned int hash;
|
||||
XeSymtabList l;
|
||||
XeSymtabList l0;
|
||||
Boolean match;
|
||||
void * hash_key;
|
||||
|
||||
/* If no cmp function assume first item of "data" is a string pointer */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (is_XeSymbol)
|
||||
hash_key = data;
|
||||
else
|
||||
hash_key = (t->hash_fn) ? data : ((unknown_entry_data) data)->name;
|
||||
|
||||
hash = keyhash( t, hash_key );
|
||||
l = t->list[hash];
|
||||
|
||||
if (bucket)
|
||||
*bucket = hash;
|
||||
|
||||
for (l0 = NULL; l; l0 = l, l = l->rest)
|
||||
{
|
||||
void * cmp_key;
|
||||
void * cmp_key2;
|
||||
|
||||
if (is_XeSymbol)
|
||||
cmp_key = data;
|
||||
else
|
||||
cmp_key = (t->cmp_fn) ? data : ((unknown_entry_data) data)->name;
|
||||
|
||||
if (l->data_is_XeSymbol)
|
||||
cmp_key2 = ((XeSymbol) l->data)->name;
|
||||
else
|
||||
cmp_key2 = (t->cmp_fn) ? l->data : ((unknown_entry_data) l->data)->name;
|
||||
|
||||
/* Use the "compare" function to see if we have a match on our key */
|
||||
/* --------------------------------------------------------------- */
|
||||
if (t->cmp_fn)
|
||||
match = (t->cmp_fn( cmp_key, cmp_key2 ) == 0);
|
||||
else
|
||||
match = (strcmp((const char *) cmp_key, (const char *)cmp_key2 ) == 0);
|
||||
|
||||
if (match)
|
||||
return l->data;
|
||||
}
|
||||
|
||||
/* If just doing a lookup, don't add a new symbol */
|
||||
/* ---------------------------------------------- */
|
||||
if (lookup_only) return (void *) NULL;
|
||||
|
||||
/* There was no match. We need to create an entry in the hash table. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
l = (XeSymtabList) XeMalloc( sizeof(struct _XeSymtabList) );
|
||||
l->rest = (XeSymtabList)NULL;
|
||||
l->data_is_XeSymbol = is_XeSymbol;
|
||||
l->data_is_malloc_mem = FALSE;
|
||||
|
||||
|
||||
if (l0)
|
||||
l0->rest = l;
|
||||
else
|
||||
t->list[hash] = l;
|
||||
|
||||
/* If we have a standard symbol, make the XeSymbol entry. */
|
||||
/* -------------------------------------------------------- */
|
||||
if (is_XeSymbol)
|
||||
{
|
||||
XeSymbol sym = make_sym((XeString)data);
|
||||
l->data = (void*) sym;
|
||||
if (t->init_fn)
|
||||
sym->value = t->init_fn( l->data, size /* will be 0 */ );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 1) If "size" != 0, */
|
||||
/* - malloc "size" bytes, */
|
||||
/* - copy "data" into malloced space, */
|
||||
/* - Save pointer to malloc space as user's data pointer */
|
||||
/* Else */
|
||||
/* - Save "data" as pointer to user's data */
|
||||
/* 2) If a "init_fn" is configured, */
|
||||
/* - call init_fn( user's data pointer, "size" ) */
|
||||
/* - set user's data pointer to return value of init_fn */
|
||||
/* ONLY if "size" was zero. */
|
||||
/* */
|
||||
/* If size is non zero AND there is a user's malloc function, */
|
||||
/* beware that the return value from the malloc function is not*/
|
||||
/* save anywhere by these routines. If size was zero, the */
|
||||
/* return value of the user's function is kept. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (size)
|
||||
{
|
||||
l->data = XeMalloc( size );
|
||||
memcpy(l->data, data, size);
|
||||
l->data_is_malloc_mem = TRUE;
|
||||
}
|
||||
else
|
||||
l->data = data;
|
||||
|
||||
if (t->init_fn)
|
||||
{
|
||||
void * new_data = t->init_fn( l->data, size );
|
||||
|
||||
if (!size)
|
||||
l->data = new_data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* appended to the end of the hash chain (if any). */
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
t->curr_list = l;
|
||||
t->curr_hash = hash;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Added data %p in list[%d] @ %p\n", l->data, hash, l);
|
||||
#endif
|
||||
|
||||
return l->data;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeSymbol
|
||||
Xe_intern(XeSymTable t, ConstXeString const name)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (!name) return (XeSymbol)NULL;
|
||||
|
||||
if (!t) t = Xe_default_symtab();
|
||||
|
||||
return (XeSymbol)intern_something(t, (void *)name, 0, TRUE, FALSE, (int*)NULL);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeSymbol
|
||||
Xe_lookup(XeSymTable t, ConstXeString const name)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (!name) return (XeSymbol)NULL;
|
||||
|
||||
if (!t) t = Xe_default_symtab();
|
||||
|
||||
return (XeSymbol)intern_something(t, (void *)name, 0, TRUE, TRUE, (int*)NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* LISTS */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeList
|
||||
Xe_make_list(void * data, XeList rest)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeList temp = Xe_make_struct(_XeList);
|
||||
|
||||
temp->data = data;
|
||||
temp->rest = rest;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* QUEUES */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeQueue
|
||||
Xe_init_queue(XeQueue q, void * nullval)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
q->head = 0;
|
||||
q->null = nullval;
|
||||
return q;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeQueue
|
||||
Xe_make_queue(void * nullval)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
return Xe_init_queue(Xe_make_struct(_XeQueue), nullval);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
void *
|
||||
Xe_pop_queue(XeQueue q)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeList head = q->head;
|
||||
|
||||
if (head) {
|
||||
void * val = head->data;
|
||||
|
||||
q->head = head->rest;
|
||||
XeFree(head);
|
||||
return val;
|
||||
} else
|
||||
return q->null;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
void *
|
||||
Xe_delete_queue_element(XeQueue q, void * val)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeList last = 0, head = q->head;
|
||||
|
||||
while (head)
|
||||
if (head->data == val) {
|
||||
if (last)
|
||||
last->rest = head->rest;
|
||||
else
|
||||
q->head = head->rest;
|
||||
if (q->tail == head)
|
||||
q->tail = last;
|
||||
XeFree(head);
|
||||
return val;
|
||||
} else
|
||||
last = head, head = head->rest;
|
||||
return q->null;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
void
|
||||
Xe_push_queue(XeQueue q, void * val)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeList new_ptr = Xe_make_list(val, 0);
|
||||
|
||||
if (q->head)
|
||||
q->tail->rest = new_ptr;
|
||||
else
|
||||
q->head = new_ptr;
|
||||
q->tail = new_ptr;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
void
|
||||
Xe_release_queue(XeQueue q)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (q) {
|
||||
while (q->head)
|
||||
Xe_pop_queue(q);
|
||||
XeFree(q);
|
||||
}
|
||||
}
|
||||
47
cde/lib/DtSvc/DtEncap/bmsglob.c
Normal file
47
cde/lib/DtSvc/DtEncap/bmsglob.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* File: bmsglob.c $XConsortium: bmsglob.c /main/4 1996/06/21 17:35:08 ageorge $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1990, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#ifdef __osf__
|
||||
/* #define SBSTDINC_H_NO_INCLUDE */
|
||||
#define SBSTDINC_H_NO_REDEFINE
|
||||
#endif
|
||||
|
||||
#include <bms/sbport.h>
|
||||
#include <bms/bms.h>
|
||||
|
||||
char *XeToolClass = NULL;
|
||||
|
||||
/* --------- */
|
||||
/* context.c */
|
||||
/* --------- */
|
||||
XeString XeProgName = (XeString) "<unknown program name>";
|
||||
|
||||
/*-------------- */
|
||||
/* SPC/spc-obj.c */
|
||||
/*-------------- */
|
||||
int SPC_Initialized=FALSE;
|
||||
|
||||
/*-------------- */
|
||||
/* SPC/spc-error.c */
|
||||
/*-------------- */
|
||||
int XeSPCErrorNumber = 0;
|
||||
FILE *spc_logF = (FILE*)NULL;
|
||||
|
||||
/*-------------- */
|
||||
/* SPC/spc-env.c */
|
||||
/*-------------- */
|
||||
XeString spc_user_environment_file=XeString_NULL;
|
||||
|
||||
/*-------------- */
|
||||
/* SPC/spc-proto.c */
|
||||
/*-------------- */
|
||||
FILE *SPC_Print_Protocol = (FILE*)NULL;
|
||||
429
cde/lib/DtSvc/DtEncap/connect.c
Normal file
429
cde/lib/DtSvc/DtEncap/connect.c
Normal file
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
* File: connect.c $TOG: connect.c /main/8 1998/04/09 17:44:33 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <sys/socket.h> /**** needed by gethostbyname et al *****/
|
||||
#define X_INCLUDE_NETDB_H
|
||||
#define XOS_USE_XT_LOCKING
|
||||
#include <X11/Xos_r.h>
|
||||
|
||||
#include <bms/bms.h>
|
||||
#include <bms/connect.h>
|
||||
#include <bms/MemoryMgr.h> /* Xe_make_struct, make_str ... */
|
||||
#include <bms/XeUserMsg.h>
|
||||
#include <bms/pathwexp.h> /* Xe_shellexp */
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
#include <codelibs/pathutils.h>
|
||||
|
||||
/*
|
||||
* local variables
|
||||
*/
|
||||
static XeString context_host = NULL;
|
||||
|
||||
static XeString FindDomainHost (XeString host_spec);
|
||||
static void UnParseFileString (XeString host, XeString path);
|
||||
static int GetDomainName (XeString buffer, unsigned int bufsize);
|
||||
|
||||
#define strequal(xxx_str1, xxx_str2) (!strcmp(xxx_str1, xxx_str2))
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeString
|
||||
XeCreateContextString(XeString host,
|
||||
XeString directory,
|
||||
XeString file)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString context_string;
|
||||
|
||||
host = XeFindShortHost(host);
|
||||
|
||||
if ((strequal(directory, (XeString)"")) || (directory == NULL)){
|
||||
if ((strequal(file, (XeString)"")) || (file == NULL)){
|
||||
return((XeString) NULL);
|
||||
} else {
|
||||
context_string = XeMalloc (strlen(host) + strlen(file) + 2);
|
||||
sprintf (context_string, "%s:%s", host, file);
|
||||
}
|
||||
} else {
|
||||
if ((strequal(file, (XeString)"")) || (file == NULL)){
|
||||
context_string = XeMalloc(strlen(host) + strlen(directory) + 2);
|
||||
sprintf (context_string, "%s:%s", host, directory);
|
||||
}
|
||||
else {
|
||||
context_string = XeMalloc(strlen(host) + strlen(directory) +
|
||||
strlen(file) + 3);
|
||||
sprintf (context_string, "%s:%s/%s", host, directory, file);
|
||||
}
|
||||
}
|
||||
Xe_release_str(host);
|
||||
return(context_string);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeString
|
||||
XeFindShortHost(XeString host_spec)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString host, ptr, ptr2;
|
||||
XeChar localhost[MAXHOSTNAMELEN];
|
||||
|
||||
if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
|
||||
_DtSvcProcessLock();
|
||||
if (!context_host){
|
||||
context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
|
||||
Xegetcwd(context_host, MAXHOSTNAMELEN);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
host_spec = context_host;
|
||||
}
|
||||
host_spec = Xe_shellexp(host_spec);
|
||||
ptr = strstr(host_spec, (XeString)".");
|
||||
if (!ptr) /* short name already */
|
||||
host = strdup(host_spec);
|
||||
else {
|
||||
GetDomainName(localhost, MAXHOSTNAMELEN);
|
||||
ptr2 = strstr(localhost, (XeString)".");
|
||||
if (ptr2 && strequal(ptr, ptr2)) { /* domains same, can eliminate */
|
||||
host = Xe_make_ntype(ptr-host_spec+1, XeChar);
|
||||
strncpy(host, host_spec, ptr-host_spec); /* copy only up to "." */
|
||||
host[ptr-host_spec] = NULL; /* NULL terminate copy */
|
||||
}
|
||||
else
|
||||
host = strdup(host_spec);
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
/* temporary without domain comparisons */
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeString
|
||||
XeFindHost(XeString host_spec)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
|
||||
_DtSvcProcessLock();
|
||||
if (!context_host){
|
||||
context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
|
||||
Xegetcwd(context_host, MAXHOSTNAMELEN);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
host_spec = context_host;
|
||||
}
|
||||
host_spec = Xe_shellexp(host_spec);
|
||||
return strdup(host_spec);
|
||||
}
|
||||
|
||||
|
||||
/* this should be XeFindHost but is called other name for 1.0 operation
|
||||
using only simple names if in short domain. See defect HZNlp05737 */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static XeString
|
||||
FindDomainHost(XeString host_spec)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString host;
|
||||
XeString ptr;
|
||||
XeChar localhost[MAXHOSTNAMELEN];
|
||||
|
||||
if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
|
||||
_DtSvcProcessLock();
|
||||
if (!context_host){
|
||||
context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
|
||||
Xegetcwd(context_host, MAXHOSTNAMELEN);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
host_spec = context_host;
|
||||
}
|
||||
else if (strequal(host_spec, (XeString)"*")) {
|
||||
host_spec = strdup((XeString)"*");
|
||||
return host_spec;
|
||||
}
|
||||
host_spec = Xe_shellexp(host_spec);
|
||||
ptr = strstr(host_spec, (XeString)".");
|
||||
if (ptr)
|
||||
host = strdup(host_spec);
|
||||
else {
|
||||
GetDomainName(localhost, MAXHOSTNAMELEN);
|
||||
ptr = strstr(localhost, (XeString)"."); /* points to domain name if one exists */
|
||||
if (ptr) {
|
||||
host = Xe_make_ntype(strlen(host_spec)+strlen(ptr)+1, XeChar);
|
||||
strcpy(host, host_spec);
|
||||
strcat(host, ptr);
|
||||
}
|
||||
else
|
||||
host = strdup(host_spec);
|
||||
}
|
||||
return(host);
|
||||
}
|
||||
|
||||
/****** XeParseFileString and UnParseFileString work together to munge and
|
||||
unmunge a path into a host path pair. UnParseFileString DOES NOT WORK
|
||||
FOR ARBITRARY STRINGS. It is not a general functions (it is a hack).
|
||||
Do not use It as a general function.
|
||||
******/
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static void
|
||||
UnParseFileString(XeString host, XeString path)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (host) { /* there was a host in the original string */
|
||||
*--path = (XeChar) ':';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeParseFileString(XeString line,
|
||||
XeString *host_addr,
|
||||
XeString *path_addr)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString current_position = line;
|
||||
|
||||
if ((XeChar)'/' == *line) {
|
||||
*host_addr = XeString_NULL;
|
||||
*path_addr = line;
|
||||
return(0);
|
||||
}
|
||||
|
||||
while (*current_position && ((XeChar) ':' != *current_position)) {
|
||||
int len;
|
||||
if ((len = mblen(current_position, MB_CUR_MAX)) > 1)
|
||||
current_position += len;
|
||||
else
|
||||
current_position++;
|
||||
}
|
||||
if (*current_position) { /* host was specified */
|
||||
*current_position++ = XeChar_NULL; /* ":" goes to NULL */
|
||||
*host_addr = line;
|
||||
*path_addr = current_position;
|
||||
} else {
|
||||
*host_addr = XeString_NULL;
|
||||
*path_addr = line;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/***** Xegethostname is a replacement for gethostname which always returns the
|
||||
canonical (domain) hostname
|
||||
******/
|
||||
|
||||
static XeString domainname = XeString_NULL;
|
||||
|
||||
/* this should be Xegethostname but is called other name for 1.0 operation
|
||||
using only simple names if in short domain. See defect HZNlp05737 */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static int
|
||||
GetDomainName(XeString buffer, unsigned int bufsize)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString tmpbuf = Xe_make_buffer(bufsize);
|
||||
XeString ptr;
|
||||
struct hostent *host_ret;
|
||||
_Xgethostbynameparams host_buf;
|
||||
static Boolean firstPass = TRUE;
|
||||
int status;
|
||||
|
||||
/* try to get domain name from hostname */
|
||||
if (status = gethostname(tmpbuf, bufsize)) {
|
||||
XeFree(tmpbuf);
|
||||
return status; /* failed gethostname */
|
||||
}
|
||||
ptr = strstr(tmpbuf, (XeString)".");
|
||||
_DtSvcProcessLock();
|
||||
if (domainname && ptr && strcmp(domainname, ptr)) /* domains are different */
|
||||
_DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><Domain configured in hostname and domain server are different: '%s', '%s'", domainname, ptr);
|
||||
if (!domainname && ptr)
|
||||
domainname = strdup(ptr);
|
||||
if (ptr) { /* "." in hostname */
|
||||
strncpy(buffer, tmpbuf, bufsize);
|
||||
XeFree(tmpbuf);
|
||||
_DtSvcProcessUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look up domain name in domain server */
|
||||
if (!domainname && (firstPass)) {
|
||||
firstPass = FALSE;
|
||||
host_ret = _XGethostbyname(tmpbuf, host_buf);
|
||||
if (host_ret == NULL) {
|
||||
_DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><%s not found in hosts database", tmpbuf);
|
||||
_DtSvcProcessUnlock();
|
||||
return -1;
|
||||
}
|
||||
if (ptr = strstr(host_ret->h_name, (XeString)".")) /* if dot in canonical name */
|
||||
domainname = strdup(ptr);
|
||||
}
|
||||
|
||||
/* construct full domain name for return */
|
||||
strncpy(buffer, tmpbuf, bufsize);
|
||||
if (domainname)
|
||||
strncat(buffer, domainname, bufsize - strlen(tmpbuf));
|
||||
XeFree(tmpbuf);
|
||||
_DtSvcProcessUnlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
int
|
||||
Xegetshorthostname(XeString buffer, unsigned int bufsize)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString ptr;
|
||||
int status;
|
||||
|
||||
if (status = gethostname(buffer, bufsize))
|
||||
return status; /* failed gethostname */
|
||||
if (ptr = strstr(buffer, (XeString)"."))
|
||||
*ptr = NULL; /* delete domain name if there is one */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
int
|
||||
Xegethostname(XeString buffer, unsigned int bufsize)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
return Xegetshorthostname(buffer, bufsize);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
Boolean
|
||||
XeIsLocalHostP(XeString hostname)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeChar localhost[MAXHOSTNAMELEN];
|
||||
XeString found_host = FindDomainHost(hostname);
|
||||
int status;
|
||||
|
||||
GetDomainName(localhost, MAXHOSTNAMELEN);
|
||||
status = strcmp(localhost, found_host)==0;
|
||||
XeFree(found_host);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
Boolean
|
||||
XeIsSameHostP(XeString host1, XeString host2)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString long_host1 = FindDomainHost(host1);
|
||||
XeString long_host2 = FindDomainHost(host2);
|
||||
int status = strcmp(long_host1, long_host2) == 0;
|
||||
if (!host1 || !host1[0] || !strcmp(host1,(XeString)"-")
|
||||
|| !host2 || !host2[0] || !strcmp(host2,(XeString)"-"))
|
||||
status = strcmp(host1, host2) == 0;
|
||||
|
||||
XeFree(long_host1);
|
||||
XeFree(long_host2);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* note the following functions use char not Xechar because they are
|
||||
plug replacements for the Unix functions */
|
||||
|
||||
static char *last_env_string = NULL; /* save env so it can be freed later */
|
||||
|
||||
/* Note: only use this function for $PWD as it assumes it can free the
|
||||
env variable when a new one is assigned -- this will only be true if
|
||||
the same variable is used for all calls to copying_putenv */
|
||||
static void
|
||||
copying_putenv(char *env)
|
||||
{
|
||||
char *env_copy = XeCopyStringM(env);
|
||||
putenv(env_copy);
|
||||
_DtSvcProcessLock();
|
||||
if (last_env_string)
|
||||
XeFree(last_env_string);
|
||||
last_env_string = env_copy;
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
char *
|
||||
Xegetcwd(char *buf, int size)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
Boolean pwd_ok = FALSE;
|
||||
char *env, *current_dir;
|
||||
|
||||
if (current_dir = getenv("PWD")) { /* use PWD instead of slow call */
|
||||
int s1, s2;
|
||||
struct stat sb1, sb2;
|
||||
|
||||
/* The code used to copy size-1 bytes. This is a waste most of */
|
||||
/* the time. All we need to copy is strlen($PWD) bytes unless */
|
||||
/* there are more bytes that fit into the array passed in. */
|
||||
|
||||
int len=strlen(current_dir);
|
||||
if (len > size-1)
|
||||
len = size-1;
|
||||
|
||||
strncpy(buf, current_dir, len);
|
||||
buf[len] = NULL;
|
||||
|
||||
/* Make sure $PWD is the same as "." before we trust it. */
|
||||
/* All this is still much faster the getcwd() esp. on UX discless. */
|
||||
s1 = stat(buf, &sb1);
|
||||
s2 = stat(".", &sb2);
|
||||
|
||||
/* If device and inode are the same, we have a match */
|
||||
pwd_ok = ((s1 == 0 && s2 == 0) &&
|
||||
(sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino) );
|
||||
}
|
||||
|
||||
if (!pwd_ok) {
|
||||
current_dir = getcwd(buf, size);
|
||||
env = XeMalloc(MAXPATHLEN+10);
|
||||
sprintf(env, "PWD=%s", buf);
|
||||
copying_putenv(env); /* set PWD if necessary for later cache use */
|
||||
if (env) XeFree(env);
|
||||
}
|
||||
return current_dir;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
int
|
||||
Xechdir (const char *path)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
int status;
|
||||
char *simple_path = NULL;
|
||||
char *env;
|
||||
char buf[MAXPATHLEN+10];
|
||||
if ((status = chdir(path))==0) {
|
||||
env = XeMalloc(MAXPATHLEN+10);
|
||||
|
||||
if (path[0] != '/') { /* relative path */
|
||||
path = getcwd(buf, sizeof buf);
|
||||
sprintf(env, "PWD=%s", path);
|
||||
}
|
||||
else {
|
||||
char *canon_path = pathcollapse(path, NULL, FALSE);
|
||||
/* absolute path */
|
||||
sprintf(env, "PWD=%s", canon_path);
|
||||
/* note XeFree() not appropriate if Xemalloc not used */
|
||||
free(canon_path);
|
||||
}
|
||||
|
||||
copying_putenv(env); /* update PWD if directory changed */
|
||||
if (env) XeFree(env);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
232
cde/lib/DtSvc/DtEncap/local.c
Normal file
232
cde/lib/DtSvc/DtEncap/local.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* File: local.c $TOG: local.c /main/5 1999/10/14 15:05:57 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define __need_timeval /* Needed for "struct timeval" from <time.h>. */
|
||||
#define __need_fd_set
|
||||
|
||||
#include <bms/sbport.h>
|
||||
#ifdef __osf__
|
||||
#include <sys/time.h> /* For declaration of select(). */
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <SPC/spc-proto.h>
|
||||
|
||||
/*
|
||||
**
|
||||
** Note that the close routines call the parent method AFTER the
|
||||
** work done for the child method. This is because the parent method
|
||||
** will do all the deallocation.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int close_local_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *wirelist;
|
||||
int result;
|
||||
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next){
|
||||
spc_close(wirelist->fd[READ_SIDE]);
|
||||
spc_close(wirelist->fd[WRITE_SIDE]);
|
||||
SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
|
||||
SPC_XtRemoveInput(&wirelist->except_toolkit_id, SPC_Exception);
|
||||
}
|
||||
|
||||
call_parent_method(channel, close, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int write_local_channel_object(SPC_Channel_Ptr channel,
|
||||
XeString buffer,
|
||||
int nbytes)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel,
|
||||
write,
|
||||
(channel, buffer, nbytes),
|
||||
result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
result = SPC_Write_Chars(channel->file_descs[STDIN], buffer, nbytes);
|
||||
if(result==ERROR) {
|
||||
SPC_Error(SPC_Writing);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/* the function exec_proc_local_channel_object is defined in spc-exec.c */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int signal_local_channel_object (SPC_Channel_Ptr channel,
|
||||
int sig)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, signal, (channel, sig), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if(sig == SIGKILL || IS_SPCIO_SIGNAL_PGRP(channel->IOMode))
|
||||
result=kill(-(channel->pid), sig);
|
||||
else
|
||||
result=kill(channel->pid, sig);
|
||||
|
||||
if(result==ERROR)
|
||||
return(errno!=ESRCH);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int local_channel_object_wait_for_termination(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, wait_for_termination, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* Do we need to check for remote channel input here? */
|
||||
|
||||
while(IS_ACTIVE(channel)) {
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
/* the SIGCLD signal handler will take care of us here */
|
||||
sigsuspend(&mask);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
remove_logfile_local_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, remove_logfile, (channel), result);
|
||||
|
||||
if(unlink(channel->logfile)==ERROR) {
|
||||
SPC_Error(SPC_Unlink_Logfile);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* This is malloc'ed memory from open_noio_channel_object() and tempnam() */
|
||||
XeFree(channel->logfile);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
extern SPC_Channel_Ptr spc_activation_list;
|
||||
|
||||
/* All this routine does is to look up the channel, and
|
||||
call the generic input handler routine */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void local_channel_object_input_handler(void * client_data,
|
||||
int *source,
|
||||
SPCInputId * UNUSED_PARM(id))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
/* WARNING!!! This routine is NOT XPG3 compliant. The timeval struct */
|
||||
/* is the problem here. */
|
||||
|
||||
SPC_Channel_Ptr channel=(SPC_Channel_Ptr) client_data;
|
||||
int fd=(*source);
|
||||
int connector;
|
||||
int len;
|
||||
fd_set read_fd_vect, except_fd_vect;
|
||||
SPC_Channel_Ptr tmp, this_ptr;
|
||||
struct timeval timeout; /* Not part of XPG3 !!! */
|
||||
|
||||
/* This ^&@$#% select is here to get around an X toolkit bug */
|
||||
|
||||
FD_ZERO(&read_fd_vect);
|
||||
FD_ZERO(&except_fd_vect);
|
||||
|
||||
FD_SET(fd, &read_fd_vect);
|
||||
FD_SET(fd, &except_fd_vect);
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
#if defined(SVR4) || defined(__osf__) || defined(__hpux)
|
||||
select(max_fds, (fd_set*)&read_fd_vect, NULL, (fd_set*)&except_fd_vect, &timeout);
|
||||
#else
|
||||
/* UX has select defined with int*, not fd_set* parms */
|
||||
select(max_fds, (int*)&read_fd_vect, NULL, (int*)&except_fd_vect, &timeout);
|
||||
#endif
|
||||
if(! (FD_ISSET(fd, &read_fd_vect) || FD_ISSET(fd, &except_fd_vect))) {
|
||||
return /* (FALSE) */;
|
||||
}
|
||||
|
||||
/* The following is to get around an apparent Xt bug where sometimes
|
||||
the client data pointer passed to me is not the one I was expecting.
|
||||
*/
|
||||
|
||||
tmp = spc_activation_list;
|
||||
this_ptr = NULL;
|
||||
while(tmp) {
|
||||
if((fd == Stdin(tmp)) || (fd == Stderr(tmp)))
|
||||
this_ptr = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if(this_ptr == NULL)
|
||||
this_ptr = channel;
|
||||
if(this_ptr != channel)
|
||||
channel = this_ptr;
|
||||
|
||||
if((connector=SPC_fd_to_connector(channel, fd)) == ERROR) {
|
||||
SPC_Error(SPC_Bad_Fd);
|
||||
return /* (SPC_ERROR) */;
|
||||
}
|
||||
len = SPC_Input_Handler(channel, connector);
|
||||
return /* (len) */;
|
||||
}
|
||||
|
||||
int local_channel_object_send_eof(SPC_Channel_Ptr channel)
|
||||
{
|
||||
Wire *wire = channel->wires[STDIN];
|
||||
|
||||
spc_close(wire->fd[READ_SIDE]);
|
||||
spc_close(wire->fd[WRITE_SIDE]);
|
||||
SPC_XtRemoveInput(&wire->read_toolkit_id, SPC_Input);
|
||||
SPC_XtRemoveInput(&wire->except_toolkit_id, SPC_Exception);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
39
cde/lib/DtSvc/DtEncap/nls.c
Normal file
39
cde/lib/DtSvc/DtEncap/nls.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* File: nls.c $XConsortium: nls.c /main/3 1995/10/26 15:36:38 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <bms/bms.h>
|
||||
|
||||
#ifndef CDE_LOGFILES_TOP
|
||||
#define CDE_LOGFILES_TOP "/var/dt/tmp"
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeString
|
||||
XeSBTempPath(XeString suffix)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString dir = (XeString) CDE_LOGFILES_TOP;
|
||||
XeString path;
|
||||
|
||||
if (!suffix || !*suffix)
|
||||
return strdup(dir);
|
||||
|
||||
path = (XeString)XeMalloc(strlen(dir) + strlen(suffix) + 2 );
|
||||
|
||||
strcpy(path, dir);
|
||||
strcat(path, "/");
|
||||
strcat(path, suffix);
|
||||
|
||||
return path;
|
||||
}
|
||||
382
cde/lib/DtSvc/DtEncap/noio.c
Normal file
382
cde/lib/DtSvc/DtEncap/noio.c
Normal file
@@ -0,0 +1,382 @@
|
||||
/* $XConsortium: noio.c /main/8 1996/11/21 19:53:13 drk $
|
||||
*
|
||||
* File: noio.c
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <bms/MemoryMgr.h>
|
||||
#define X_INCLUDE_PWD_H
|
||||
#define XOS_USE_XT_LOCKING
|
||||
#include <X11/Xos_r.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* Global variables */
|
||||
|
||||
/*
|
||||
* The name of the directory used for authentication and
|
||||
* for temporary logfiles.
|
||||
*/
|
||||
XeString SPCD_Authentication_Dir = NULL;
|
||||
|
||||
/*
|
||||
* This array contains the names of the logfiles the SPC daemon
|
||||
* creates. Before the daemon exits, if any logfiles exist, they
|
||||
* will be removed.
|
||||
*/
|
||||
char **SPC_logfile_list = NULL;
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void noio_channel_class_init(object_clasp t)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
noio_channel_clasp c =(noio_channel_clasp) t;
|
||||
|
||||
c->new_obj = alloc_channel_object;
|
||||
|
||||
c->open = open_noio_channel_object;
|
||||
c->close = close_local_channel_object;
|
||||
c->read = read_noio_channel_object;
|
||||
c->write = write_noio_channel_object;
|
||||
c->reset = reset_noio_channel_object;
|
||||
c->pre_fork = pre_fork_noio_channel_object;
|
||||
c->post_fork = post_fork_noio_channel_object;
|
||||
c->exec_proc = exec_proc_local_channel_object;
|
||||
c->signal = signal_local_channel_object;
|
||||
c->wait_for_termination = local_channel_object_wait_for_termination;
|
||||
c->attach = attach_noio_channel_object;
|
||||
c->input = noio_channel_object_input_handler;
|
||||
c->remove_logfile = remove_logfile_local_channel_object;
|
||||
|
||||
/* New B.00 methods */
|
||||
|
||||
c->send_eof = send_eof_noio_channel_object;
|
||||
c->set_termio = set_termio_noio_channel_object;
|
||||
}
|
||||
|
||||
static struct noio_channel_class noio_channel_class_struct = {
|
||||
(channel_clasp) &channel_class, /* base class pointer */
|
||||
"noio_channel", /* class name */
|
||||
noio_channel_class_init, /* class initialize function */
|
||||
sizeof(SPC_Channel), /* size */
|
||||
0
|
||||
};
|
||||
|
||||
noio_channel_clasp noio_channel_class = &noio_channel_class_struct;
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
static int is_dir_usable (
|
||||
char *dir);
|
||||
static char * get_tmp_dir (
|
||||
void);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* is_dir_usable - given a directory name, return 1 if:
|
||||
*
|
||||
* #1 the directory exists (determined by stat() succeeding)
|
||||
*
|
||||
* #2 the directory is readable
|
||||
*
|
||||
* #3 the directory is writeable
|
||||
*
|
||||
* otherwise, return 0.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* char *dir - the directory to check
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* 1 if 'dir' is usable and 0 if it is not
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int is_dir_usable (
|
||||
char *dir)
|
||||
{
|
||||
struct stat stat_buffer;
|
||||
|
||||
if ((stat (dir, &stat_buffer)) != 0)
|
||||
return (0);
|
||||
|
||||
if ((S_ISDIR(stat_buffer.st_mode)) && (access (dir, W_OK | R_OK) == 0))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* get_tmp_dir - determine the name of a directory to use
|
||||
* for temporary logfiles. The first dirctory in the
|
||||
* following list that passes the usability test in
|
||||
* 'is_dir_usable' will be returned:
|
||||
*
|
||||
* ~/.dt/tmp
|
||||
*
|
||||
* ~/.dt
|
||||
*
|
||||
* ~/
|
||||
*
|
||||
* Parameters: NONE
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* char * - the name of the temporary directory to use
|
||||
* or NULL if no usable directory is found.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* o The caller is responsible for free'ing the returned
|
||||
* string (if it is not NULL)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char * get_tmp_dir (
|
||||
void)
|
||||
{
|
||||
char *dir;
|
||||
_Xgetpwparams pwd_buf;
|
||||
struct passwd * pwd_ret;
|
||||
|
||||
if ((pwd_ret = _XGetpwuid(getuid(), pwd_buf)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
dir = malloc (strlen (pwd_ret->pw_dir) +
|
||||
strlen (SPCD_ENV_HOME_DIRECTORY) + 8);
|
||||
|
||||
if (!dir)
|
||||
return (NULL);
|
||||
|
||||
(void) sprintf (dir, "%s/%s/tmp", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
|
||||
if (is_dir_usable (dir))
|
||||
return (dir);
|
||||
|
||||
(void) sprintf (dir, "%s/%s", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
|
||||
if (is_dir_usable (dir))
|
||||
return (dir);
|
||||
|
||||
(void) sprintf (dir, "%s", pwd_ret->pw_dir);
|
||||
if (is_dir_usable (dir))
|
||||
return (dir);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Method definitions for noio channel objects
|
||||
***
|
||||
*/
|
||||
|
||||
/*
|
||||
* This routine handles initialization for noio channels
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr open_noio_channel_object(SPC_Channel_Ptr channel,
|
||||
int iomode,
|
||||
XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int i=0;
|
||||
SPC_Channel_Ptr result;
|
||||
XeString temp_dir_name = NULL;
|
||||
|
||||
call_parent_method(channel, open, (channel, iomode, hostname), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if(IS_SPCIO_USE_LOGFILE(iomode)) {
|
||||
|
||||
_DtSvcProcessLock();
|
||||
/* Storage from tempnam() freed in remove_logfile_local_channel_object */
|
||||
if (SPCD_Authentication_Dir != NULL)
|
||||
channel->logfile=tempnam(SPCD_Authentication_Dir,"SPC");
|
||||
else {
|
||||
temp_dir_name = get_tmp_dir ();
|
||||
channel->logfile=tempnam(temp_dir_name,"SPC");
|
||||
if (temp_dir_name != NULL)
|
||||
free(temp_dir_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the name of the logfile so it can removed by the
|
||||
* daemon before it exits.
|
||||
*/
|
||||
if (SPC_logfile_list == NULL)
|
||||
/*
|
||||
* Create the first block plus the NULL terminator.
|
||||
*/
|
||||
SPC_logfile_list = (char **) malloc (2 * sizeof (char *));
|
||||
else {
|
||||
/*
|
||||
* Need to add this file to the end of the list.
|
||||
*/
|
||||
for (i = 0; SPC_logfile_list[i] != NULL; i++);
|
||||
SPC_logfile_list = (char **) realloc (SPC_logfile_list,
|
||||
(i+2) * sizeof (char *));
|
||||
}
|
||||
if (channel->logfile != NULL)
|
||||
SPC_logfile_list[i] = strdup (channel->logfile);
|
||||
else
|
||||
SPC_logfile_list[i] = (char *) NULL;
|
||||
SPC_logfile_list[i+1] = (char *) NULL;
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
if(!channel->logfile) {
|
||||
SPC_Error(SPC_Out_Of_Memory);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return(channel);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int read_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(connector), /* STDOUT or STDERR */
|
||||
XeString UNUSED_PARM(buffer),
|
||||
int UNUSED_PARM(nbytes))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int write_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
XeString UNUSED_PARM(buffer),
|
||||
int UNUSED_PARM(nbytes))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int pre_fork_noio_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, pre_fork, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int post_fork_noio_channel_object(SPC_Channel_Ptr channel,
|
||||
int parentp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result, fd;
|
||||
|
||||
call_parent_method(channel, post_fork, (channel, parentp), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
|
||||
if (parentp) { /* Master process */
|
||||
}
|
||||
else { /* Slave process */
|
||||
|
||||
/* set up STDIN, STDOUT & STDERR to go to /dev/null,
|
||||
or to the appropriate logfile */
|
||||
|
||||
fd=(-1);
|
||||
|
||||
spc_dup2(fd, STDIN);
|
||||
|
||||
/* Open logfile if necessary */
|
||||
|
||||
if(IS_SPCIO_USE_LOGFILE(channel->IOMode))
|
||||
if((fd=open(channel->logfile, O_WRONLY | O_CREAT, 0666)) == ERROR) {
|
||||
SPC_Error(SPC_Cannot_Open_Log, channel->logfile);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
spc_dup2(fd, STDOUT);
|
||||
spc_dup2(fd, STDERR);
|
||||
|
||||
/* close all other file descriptors */
|
||||
|
||||
SPC_Close_Unused();
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int reset_noio_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int iomode=channel->IOMode;
|
||||
|
||||
call_parent_method(channel, reset, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int attach_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(foo))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* It is an error to try to attach to a noio channel... */
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void noio_channel_object_input_handler(void *UNUSED_PARM(client_data),
|
||||
int *UNUSED_PARM(source),
|
||||
SPCInputId *UNUSED_PARM(id))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return /* (SPC_ERROR) */;
|
||||
}
|
||||
|
||||
int send_eof_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel))
|
||||
{
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
int set_termio_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(connection),
|
||||
int UNUSED_PARM(side),
|
||||
struct termios * UNUSED_PARM(termio))
|
||||
{
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
31
cde/lib/DtSvc/DtEncap/pathwexp.c
Normal file
31
cde/lib/DtSvc/DtEncap/pathwexp.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* File: pathwexp.c $XConsortium: pathwexp.c /main/3 1995/10/26 15:37:07 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h>
|
||||
#include <bms/pathwexp.h>
|
||||
|
||||
#include <codelibs/shellutils.h>
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeString Xe_shellexp(XeString path)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
int num;
|
||||
XeString *res = (XeString *) shellscan(path, &num,
|
||||
SHX_NOGLOB | SHX_NOSPACE | SHX_NOMETA | SHX_NOGRAVE);
|
||||
|
||||
if (num == 0)
|
||||
return NULL;
|
||||
else
|
||||
return res[0];
|
||||
}
|
||||
|
||||
322
cde/lib/DtSvc/DtEncap/pipe.c
Normal file
322
cde/lib/DtSvc/DtEncap/pipe.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* File: pipe.c $XConsortium: pipe.c /main/4 1996/04/21 19:10:09 drk $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <errno.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void pipe_channel_class_init(object_clasp t)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
pipe_channel_clasp c = (pipe_channel_clasp) t;
|
||||
|
||||
c->new_obj = alloc_channel_object;
|
||||
|
||||
c->open = open_pipe_channel_object;
|
||||
c->close = close_local_channel_object;
|
||||
c->read = read_pipe_channel_object;
|
||||
c->write = write_local_channel_object;
|
||||
c->reset = reset_pipe_channel_object;
|
||||
c->pre_fork = pre_fork_pipe_channel_object;
|
||||
c->post_fork = post_fork_pipe_channel_object;
|
||||
c->exec_proc = exec_proc_local_channel_object;
|
||||
c->signal = signal_local_channel_object;
|
||||
c->wait_for_termination = local_channel_object_wait_for_termination;
|
||||
c->attach = attach_pipe_channel_object;
|
||||
c->add_input = add_input_pipe_channel_object;
|
||||
c->input = local_channel_object_input_handler;
|
||||
c->remove_logfile = remove_logfile_local_channel_object;
|
||||
|
||||
/* New B.00 methods */
|
||||
|
||||
c->send_eof = local_channel_object_send_eof;
|
||||
c->set_termio = set_termio_noio_channel_object;
|
||||
}
|
||||
|
||||
static struct pipe_channel_class pipe_channel_class_struct = {
|
||||
(channel_clasp) &channel_class, /* base class pointer */
|
||||
"pipe_channel", /* class name */
|
||||
pipe_channel_class_init, /* class initialize function */
|
||||
sizeof(SPC_Channel), /* size */
|
||||
0
|
||||
};
|
||||
|
||||
pipe_channel_clasp pipe_channel_class = &pipe_channel_class_struct;
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
Wire *getpipe(Wire *prevwire)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *wire_ptr=get_new_wire();
|
||||
|
||||
if(!wire_ptr)
|
||||
return(SPC_ERROR);
|
||||
|
||||
wire_ptr->next=prevwire;
|
||||
/* Get file descriptors for pipe */
|
||||
if (pipe(wire_ptr->fd) < OK) {
|
||||
SPC_Error(SPC_No_Pipe);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
return(wire_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Method definitions for pipe channel objects
|
||||
***
|
||||
*/
|
||||
|
||||
/*
|
||||
* This routine handles initialization for pipe channels
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr open_pipe_channel_object(SPC_Channel_Ptr channel,
|
||||
int iomode,
|
||||
XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
Wire *tmpwire=NULL;
|
||||
SPC_Channel_Ptr result;
|
||||
|
||||
call_parent_method(channel, open, (channel, iomode, hostname), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if (IS_SPCIO_STDIN(iomode)) {
|
||||
tmpwire=channel->wires[STDIN]=getpipe(NULL);
|
||||
if(!tmpwire)
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if (IS_SPCIO_STDOUT(iomode)) {
|
||||
tmpwire=channel->wires[STDOUT]=getpipe(tmpwire);
|
||||
if(!tmpwire)
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(IS_SPCIO_STDERR(iomode)) {
|
||||
if (!tmpwire ||
|
||||
IS_SPCIO_SEPARATE(iomode)) {
|
||||
tmpwire=channel->wires[STDERR]=getpipe(tmpwire);
|
||||
if(!tmpwire)
|
||||
return(SPC_ERROR);
|
||||
} else {
|
||||
channel->wires[STDERR]=channel->wires[STDOUT];
|
||||
}
|
||||
}
|
||||
|
||||
channel->file_descs[STDIN] =(channel->wires[STDIN]) ->fd[WRITE_SIDE];
|
||||
channel->file_descs[STDOUT]=(channel->wires[STDOUT])->fd[READ_SIDE];
|
||||
channel->file_descs[STDERR]=(channel->wires[STDERR])->fd[READ_SIDE];
|
||||
|
||||
channel->wire_list=tmpwire;
|
||||
|
||||
return(channel);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int read_pipe_channel_object(SPC_Channel_Ptr channel,
|
||||
int connector, /* STDOUT or STDERR */
|
||||
XeString buffer,
|
||||
int nbytes)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel,
|
||||
read,
|
||||
(channel, connector, buffer, nbytes),
|
||||
result);
|
||||
|
||||
if(result==Undefined)
|
||||
return(Undefined);
|
||||
|
||||
do {
|
||||
result = read(channel->file_descs[connector], buffer, nbytes);
|
||||
} while (result<0 && errno == EINTR);
|
||||
|
||||
if(result == 0) {
|
||||
|
||||
SPC_XtRemoveInput(&channel->wires[connector]->read_toolkit_id, SPC_Input);
|
||||
SPC_Change_State(channel, connector, 0, -1);
|
||||
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int pre_fork_pipe_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, pre_fork, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int post_fork_pipe_channel_object(SPC_Channel_Ptr channel,
|
||||
int parentp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, post_fork, (channel, parentp), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
|
||||
if (parentp) { /* Master process */
|
||||
|
||||
spc_close(channel->wires[STDIN]->fd[READ_SIDE]);
|
||||
spc_close(channel->wires[STDOUT]->fd[WRITE_SIDE]);
|
||||
spc_close(channel->wires[STDERR]->fd[WRITE_SIDE]);
|
||||
|
||||
channel->wires[STDIN]->fd[READ_SIDE] = (-1);
|
||||
channel->wires[STDOUT]->fd[WRITE_SIDE] = (-1);
|
||||
channel->wires[STDERR]->fd[WRITE_SIDE] = (-1);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
else { /* Slave process */
|
||||
|
||||
/* Close the "other" side of the pipes */
|
||||
|
||||
spc_close(channel->wires[STDIN]->fd[WRITE_SIDE]);
|
||||
spc_close(channel->wires[STDOUT]->fd[READ_SIDE]);
|
||||
spc_close(channel->wires[STDERR]->fd[READ_SIDE]);
|
||||
|
||||
/* Dup the file descriptors to fd's 3, 4, 5.
|
||||
spc_dup2 is used to make sure these guys are hooked to something
|
||||
(/dev/null if necessary). We do this step here just in case any
|
||||
of the source file descriptors are 0, 1, or 2. */
|
||||
|
||||
spc_dup2(channel->wires[STDIN]->fd[READ_SIDE], 3);
|
||||
spc_dup2(channel->wires[STDOUT]->fd[WRITE_SIDE], 4);
|
||||
spc_dup2(channel->wires[STDERR]->fd[WRITE_SIDE], 5);
|
||||
|
||||
/* Go to STDIN, STDOUT, STDERR */
|
||||
|
||||
spc_dup2(3, STDIN);
|
||||
spc_dup2(4, STDOUT);
|
||||
spc_dup2(5, STDERR);
|
||||
|
||||
/* Close any other open file descriptors in the child */
|
||||
SPC_Close_Unused();
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int reset_pipe_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int iomode=channel->IOMode;
|
||||
Wire *wirelist;
|
||||
|
||||
call_parent_method(channel, reset, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* Close the file descriptors */
|
||||
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
|
||||
SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
|
||||
close(wirelist->fd[READ_SIDE]);
|
||||
close(wirelist->fd[WRITE_SIDE]);
|
||||
wirelist->flags &= ~SPCIO_DATA;
|
||||
}
|
||||
|
||||
/* Allocate new file descriptors */
|
||||
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
|
||||
if(pipe(wirelist->fd) < 0) {
|
||||
SPC_Error(SPC_No_Pipe);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* set the file_descs array to the new file descriptors & set up
|
||||
the new read mask */
|
||||
|
||||
channel->file_descs[STDIN] = (channel->wires[STDIN])->fd[WRITE_SIDE];
|
||||
channel->file_descs[STDOUT] = (channel->wires[STDOUT])->fd[READ_SIDE];
|
||||
channel->file_descs[STDERR] = (channel->wires[STDERR])->fd[READ_SIDE];
|
||||
|
||||
XeSPCAddInput(channel, NULL, NULL);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int attach_pipe_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(foo))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* It is an error to try to attach to a pipe channel... */
|
||||
SPC_Error(SPC_Bad_Operation);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int add_input_pipe_channel_object(SPC_Channel_Ptr channel,
|
||||
SbInputHandlerProc handler,
|
||||
void *data)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result, fd;
|
||||
Wire *wirelist, *stdinwire;
|
||||
|
||||
call_parent_method(channel, add_input, (channel, handler, data), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
stdinwire=channel->wires[STDIN];
|
||||
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
|
||||
|
||||
if(wirelist == stdinwire)
|
||||
continue;
|
||||
|
||||
if(wirelist->read_toolkit_id != -1)
|
||||
continue;
|
||||
|
||||
fd=wirelist->fd[READ_SIDE];
|
||||
SPC_XtAddInput(channel,
|
||||
&wirelist->read_toolkit_id,
|
||||
fd,
|
||||
channel->class_ptr->input,
|
||||
SPC_Input);
|
||||
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
1107
cde/lib/DtSvc/DtEncap/pty.c
Normal file
1107
cde/lib/DtSvc/DtEncap/pty.c
Normal file
File diff suppressed because it is too large
Load Diff
488
cde/lib/DtSvc/DtEncap/remote.c
Normal file
488
cde/lib/DtSvc/DtEncap/remote.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* File: remote.c $XConsortium: remote.c /main/5 1996/06/21 17:34:53 ageorge $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h>
|
||||
#include <bms/usersig.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <SPC/spc-proto.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void remote_channel_class_init(object_clasp t)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
channel_clasp c=(channel_clasp) t;
|
||||
|
||||
c->new_obj = alloc_channel_object;
|
||||
|
||||
c->open = open_remote_channel_object;
|
||||
c->close = close_remote_channel_object;
|
||||
c->read = read_remote_channel_object;
|
||||
c->write = write_remote_channel_object;
|
||||
c->reset = reset_remote_channel_object;
|
||||
/* pre_fork & post_fork have no method */
|
||||
c->exec_proc = exec_proc_remote_channel_object;
|
||||
c->signal = signal_remote_channel_object;
|
||||
/* wait_for_termination has no method */
|
||||
c->attach = attach_remote_channel_object;
|
||||
c->add_input = add_input_remote_channel_object;
|
||||
c->input = SPC_Conditional_Packet_Handler;
|
||||
c->remove_logfile = remove_logfile_remote_channel_object;
|
||||
|
||||
/* New B.00 methods */
|
||||
|
||||
c->send_eof = send_eof_remote_channel_object;
|
||||
c->set_termio = set_termio_remote_channel_object;
|
||||
|
||||
}
|
||||
|
||||
static struct remote_channel_class remote_channel_class_struct = {
|
||||
(channel_clasp) &channel_class, /* base class pointer */
|
||||
"remote_channel", /* class name */
|
||||
remote_channel_class_init,/* class initialize function */
|
||||
sizeof(SPC_Channel), /* size */
|
||||
0
|
||||
};
|
||||
|
||||
remote_channel_clasp remote_channel_class = &remote_channel_class_struct;
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
Wire *get_new_remote_wire(Wire *prevwire)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *mywire=get_new_wire();
|
||||
|
||||
if(mywire==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
mywire->next=prevwire;
|
||||
return(mywire);
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Method definitions for remote channel objects
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr open_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
int iomode,
|
||||
XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Channel_Ptr result;
|
||||
int seqno, retval;
|
||||
Wire *tmpwire=NULL;
|
||||
int sid;
|
||||
|
||||
call_parent_method(channel, open, (channel, iomode, hostname), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
channel->cid=0;
|
||||
channel->queued_remote_data=Xe_make_queue(NULL);
|
||||
iomode=channel->IOMode;
|
||||
|
||||
if(IS_SPCIO_STDIN(iomode)) {
|
||||
tmpwire=get_new_remote_wire(tmpwire);
|
||||
channel->wires[STDIN]=tmpwire;
|
||||
}
|
||||
if(IS_SPCIO_STDOUT(iomode)) {
|
||||
tmpwire=get_new_remote_wire(tmpwire);
|
||||
channel->wires[STDOUT]=tmpwire;
|
||||
}
|
||||
if(IS_SPCIO_STDERR(iomode)) {
|
||||
if(!tmpwire || /* ERRORONLY */
|
||||
IS_SPCIO_SEPARATE(iomode))
|
||||
tmpwire=get_new_remote_wire(tmpwire);
|
||||
channel->wires[STDERR]=tmpwire;
|
||||
}
|
||||
|
||||
channel->wire_list=tmpwire;
|
||||
|
||||
if(!(channel->connection=SPC_Open_Connection(hostname)))
|
||||
return(SPC_ERROR);
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
CHANNEL_OPEN, iomode);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
channel->cid=retval;
|
||||
sid=channel->connection->sid;
|
||||
channel->file_descs[STDIN]=sid;
|
||||
channel->file_descs[STDOUT]=sid;
|
||||
channel->file_descs[STDERR]=sid;
|
||||
|
||||
if ((SPC_client_version_number >= SPC_PROTOCOL_VERSION_CDE_BASE) &&
|
||||
(SPC_who_am_i == SPC_I_AM_A_CLIENT)) {
|
||||
channel->wires[STDIN]->master_name = NULL;
|
||||
channel->wires[STDIN]->slave_name = NULL;
|
||||
channel->wires[STDOUT]->master_name = NULL;
|
||||
channel->wires[STDOUT]->slave_name = NULL;
|
||||
channel->wires[STDERR]->master_name = NULL;
|
||||
channel->wires[STDERR]->slave_name = NULL;
|
||||
}
|
||||
else
|
||||
SPC_Query_Devices(channel);
|
||||
|
||||
SPC_Query_Logfile(channel);
|
||||
|
||||
return(channel);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Note that the close routines call the parent method AFTER the
|
||||
** work done for the child method. This is because the parent method
|
||||
** will do all the deallocation.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int close_remote_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int result;
|
||||
int seqno, retval;
|
||||
|
||||
channel->IOMode |= SPCIO_DELAY_CLOSE;
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
CHANNEL_CLOSE);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
|
||||
call_parent_method(channel, close, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int reset_remote_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int result;
|
||||
int seqno, retval;
|
||||
XeQueue tmpqueue;
|
||||
protocol_request_ptr prot;
|
||||
|
||||
call_parent_method(channel, reset, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
CHANNEL_RESET);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* At this point, we know that the remote server has sent us all
|
||||
necessary data (since RESET expects a reply). So, we are safe to
|
||||
flush any queued data on this channel. */
|
||||
|
||||
{
|
||||
if (tmpqueue=channel->queued_remote_data)
|
||||
{
|
||||
Xe_for_queue(protocol_request_ptr, prot, tmpqueue) {
|
||||
Xe_delete_queue_element(channel->queued_remote_data, prot);
|
||||
SPC_Free_Protocol_Ptr(prot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int exec_proc_remote_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int retval, seqno;
|
||||
int tmp_errorno;
|
||||
|
||||
call_parent_method(channel, exec_proc, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
call_parent_method(channel, pre_fork, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if((channel->connection->protocol_version > 2) ||
|
||||
IS_SPCIO_FORCE_CONTEXT(channel->IOMode))
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
APP_B00_SPAWN,
|
||||
channel->path, channel->context_dir,
|
||||
channel->argv, channel->envp);
|
||||
else
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
APPLICATION_SPAWN,
|
||||
channel->path, channel->context_dir,
|
||||
channel->argv, channel->envp);
|
||||
|
||||
_DtSvcProcessLock();
|
||||
tmp_errorno = XeSPCErrorNumber;
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
if (tmp_errorno != 0)
|
||||
XeSPCErrorNumber = tmp_errorno;
|
||||
_DtSvcProcessUnlock();
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
channel->pid=retval;
|
||||
|
||||
call_parent_method(channel, post_fork, (channel, retval), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int write_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
XeString buffer,
|
||||
int len)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int seqno, retval;
|
||||
int lentogo=len, lentowrite;
|
||||
|
||||
call_parent_method(channel, write, (channel, buffer, len), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
do {
|
||||
|
||||
lentowrite=min(lentogo, SPC_BUFSIZ);
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
APPLICATION_DATA, buffer, lentowrite);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
lentogo -= lentowrite;
|
||||
buffer += lentowrite;
|
||||
|
||||
} while(lentogo>0);
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int read_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
int connection,
|
||||
XeString buffer,
|
||||
int len)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, read, (channel, connection, buffer, len), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if(!IS_SPCIO_DATA(channel->wires[connection]->flags))
|
||||
return(0);
|
||||
|
||||
result=SPC_Read_Remote_Data(channel, connection, buffer, len);
|
||||
if(result == 0)
|
||||
/* Got EOF. Yank the data line */
|
||||
SPC_Change_State(channel, connection, 0, -1);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int signal_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
int sig)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int seqno, retval;
|
||||
|
||||
call_parent_method(channel, signal, (channel, sig), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if (channel->connection->protocol_version >= 2) {
|
||||
XeString signame = XeSignalToName( sig );
|
||||
|
||||
if (!signame)
|
||||
{
|
||||
SPC_Error(SPC_Bad_Signal_Value, sig);
|
||||
return (SPC_ERROR);
|
||||
}
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
APPLICATION_SIGNAL, signame);
|
||||
}
|
||||
else
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
APPLICATION_SIGNAL, sig);
|
||||
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int attach_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
int pid)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int seqno, retval;
|
||||
|
||||
call_parent_method(channel, attach, (channel, pid), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
CHANNEL_ATTACH, pid);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
SPC_Flush_Queued_Data(channel);
|
||||
|
||||
if(!mempf0(channel, pre_fork))
|
||||
return(SPC_ERROR);
|
||||
channel->pid = pid;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
remove_logfile_remote_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
int seqno, retval;
|
||||
|
||||
call_parent_method(channel, remove_logfile, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(channel->connection, channel, DELETE_LOGFILE);
|
||||
retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int add_input_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
SbInputHandlerProc handler,
|
||||
void *data)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
SPC_Connection_Ptr conn=channel->connection;
|
||||
|
||||
call_parent_method(channel, add_input, (channel, handler, data), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if(conn->termination_id != -1)
|
||||
/* We already have a handler, don't need another one */
|
||||
return(TRUE);
|
||||
|
||||
SPC_XtAddInput(channel,
|
||||
&conn->termination_id,
|
||||
conn->sid,
|
||||
channel->class_ptr->input,
|
||||
SPC_Input);
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Debug_Mode(SPC_Channel_Ptr channel,
|
||||
XeString file)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int retval, seqno;
|
||||
|
||||
if(!channel->connection)
|
||||
return(SPC_ERROR);
|
||||
|
||||
retval=SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
SERVER_DEBUG, file);
|
||||
seqno=SPC_Waitfor_Reply(channel->connection, channel, retval);
|
||||
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
return(seqno);
|
||||
|
||||
}
|
||||
|
||||
int send_eof_remote_channel_object(SPC_Channel_Ptr channel)
|
||||
{
|
||||
int retval, seqno;
|
||||
|
||||
if(!channel->connection)
|
||||
return(SPC_ERROR);
|
||||
|
||||
retval =
|
||||
SPC_Write_Protocol_Request(channel->connection, channel, CHANNEL_SEND_EOF);
|
||||
seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
|
||||
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(seqno);
|
||||
|
||||
}
|
||||
|
||||
int set_termio_remote_channel_object(SPC_Channel_Ptr channel,
|
||||
int connector,
|
||||
int side,
|
||||
struct termios *termios)
|
||||
{
|
||||
int retval, seqno;
|
||||
|
||||
if(!channel->connection)
|
||||
return(SPC_ERROR);
|
||||
|
||||
retval =
|
||||
SPC_Write_Protocol_Request(channel->connection, channel,
|
||||
CHANNEL_TERMIOS,
|
||||
connector, side, termios);
|
||||
seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
|
||||
|
||||
if(retval==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(seqno);
|
||||
|
||||
}
|
||||
149
cde/lib/DtSvc/DtEncap/sbstdinc.c
Normal file
149
cde/lib/DtSvc/DtEncap/sbstdinc.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* File: sbstdinc.c $TOG: sbstdinc.c /main/5 1999/10/14 15:06:26 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define SBSTDINC_H_NO_REDEFINE
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static XeChar XESTRING_SAFE_NULL[1] = {(XeChar)0};
|
||||
|
||||
/************************************************************************/
|
||||
/* Routines from <string.h> */
|
||||
/************************************************************************/
|
||||
|
||||
XeString Xestrcat(XeString s1, ConstXeString s2)
|
||||
{
|
||||
if (!s1) return XeString_NULL;
|
||||
if (!s2) return s1;
|
||||
|
||||
return (XeString) strcat(s1, s2);
|
||||
}
|
||||
|
||||
XeString Xestrncat(XeString s1, ConstXeString s2, size_t n)
|
||||
{
|
||||
if (!s1) return XeString_NULL;
|
||||
if (!s2) return s1;
|
||||
|
||||
return (XeString) strncat(s1, s2, n);
|
||||
}
|
||||
|
||||
int Xestrcmp(ConstXeString s1, ConstXeString s2)
|
||||
{
|
||||
if (s1 == s2) return 0;
|
||||
{
|
||||
const XeChar * p1 = (s1) ? s1 : XESTRING_SAFE_NULL;
|
||||
const XeChar * p2 = (s2) ? s2 : XESTRING_SAFE_NULL;
|
||||
|
||||
return strcmp(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
int Xestrncmp(ConstXeString s1, ConstXeString s2, size_t n)
|
||||
{
|
||||
if (s1 == s2) return 0;
|
||||
{
|
||||
ConstXeString p1 = (s1) ? s1 : XESTRING_SAFE_NULL;
|
||||
ConstXeString p2 = (s2) ? s2 : XESTRING_SAFE_NULL;
|
||||
return strncmp( (char *) p1, (char *) p2, n);
|
||||
}
|
||||
}
|
||||
|
||||
XeString Xestrcpy(XeString s1, ConstXeString s2)
|
||||
{
|
||||
if (!s1) return s1;
|
||||
if (!s2) {
|
||||
*s1 = (XeChar)0;
|
||||
return s1;
|
||||
}
|
||||
|
||||
return (XeString) strcpy(s1, s2);
|
||||
}
|
||||
|
||||
XeString Xestrncpy(XeString s1, ConstXeString s2, size_t n)
|
||||
{
|
||||
if (!s1) return s1;
|
||||
if (!s2 && n) {
|
||||
*s1 = (XeChar)0;
|
||||
return s1;
|
||||
}
|
||||
|
||||
return (XeString) strncpy(s1, s2, n);
|
||||
}
|
||||
|
||||
int Xestrcoll(ConstXeString s1, ConstXeString s2)
|
||||
{
|
||||
if (s1 == s2) return 0;
|
||||
{
|
||||
XeString p1 = (s1) ? (XeString) s1 : XESTRING_SAFE_NULL;
|
||||
XeString p2 = (s2) ? (XeString) s2 : XESTRING_SAFE_NULL;
|
||||
return strcoll(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Xestrxfrm(XeString s1, ConstXeString s2, size_t n)
|
||||
{
|
||||
return strxfrm(s1, s2, n);
|
||||
}
|
||||
|
||||
XeString Xestrchr(ConstXeString s, int c)
|
||||
{
|
||||
if (!s) return XeString_NULL;
|
||||
|
||||
return (XeString) strchr(s, c);
|
||||
}
|
||||
|
||||
XeString Xestrrchr(ConstXeString s, int c)
|
||||
{
|
||||
if (!s) return XeString_NULL;
|
||||
|
||||
return (XeString) strrchr(s, c);
|
||||
}
|
||||
|
||||
XeString Xestrpbrk(ConstXeString s1, ConstXeString s2)
|
||||
{
|
||||
if (!s1) return XeString_NULL;
|
||||
if (!s2) return XeString_NULL;
|
||||
|
||||
return (XeString) strpbrk(s1, s2);
|
||||
}
|
||||
|
||||
XeString Xestrstr(ConstXeString s1, ConstXeString s2)
|
||||
{
|
||||
if (!s1) return XeString_NULL;
|
||||
if (!s2) return XeString_NULL;
|
||||
|
||||
return (XeString) strstr(s1, s2);
|
||||
}
|
||||
|
||||
XeString Xestrtok(XeString s1, ConstXeString s2)
|
||||
{
|
||||
/* s1 is null except after the first call */
|
||||
if (!s2) return XeString_NULL;
|
||||
|
||||
return (XeString) strtok(s1, s2);
|
||||
}
|
||||
|
||||
size_t Xestrlen(ConstXeString const s)
|
||||
{
|
||||
if (!s) return (size_t)0;
|
||||
|
||||
return strlen((char *) s);
|
||||
}
|
||||
|
||||
XeString Xestrdup(ConstXeString s)
|
||||
{
|
||||
if (!s) return XeString_NULL;
|
||||
|
||||
return (XeString) strdup(s);
|
||||
}
|
||||
182
cde/lib/DtSvc/DtEncap/scoop.c
Normal file
182
cde/lib/DtSvc/DtEncap/scoop.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* File: scoop.c $XConsortium: scoop.c /main/3 1995/10/26 15:38:19 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#ifdef DOMAIN_ALLOW_MALLOC_OVERRIDE
|
||||
#include "/usr/include/apollo/shlib.h"
|
||||
#endif
|
||||
|
||||
#include <bms/sbport.h> /* This must be the first file included */
|
||||
#include <bms/scoop.h>
|
||||
|
||||
static void system_class_init (object_clasp to_do, object_clasp on_behalf_of);
|
||||
static void system_object_init (object_clasp c, object *p);
|
||||
static void root_class_init (object_clasp c);
|
||||
static void root_object_init (object *p);
|
||||
static object *root_clone (object *this_ptr, object *clone);
|
||||
static object *root_new (object_clasp c);
|
||||
static void root_free (object *p);
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
void object_destroy (object *p)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
memf (p->, free_obj, (p)) ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
object *object_create (object_clasp c)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
object *p ;
|
||||
|
||||
if (! c->init) { system_class_init (c, c) ; }
|
||||
p = (*(c->new_obj))(c) ;
|
||||
if (p)
|
||||
object_init (c, p) ;
|
||||
return p ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
void object_init (object_clasp c, object *p)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (! c->init) { system_class_init (c, c) ; }
|
||||
p->class_ptr = c ;
|
||||
system_object_init (c, p) ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static void system_class_init (object_clasp to_do, object_clasp on_behalf_of)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
object_clasp base ;
|
||||
|
||||
if ( on_behalf_of && to_do && ! on_behalf_of->init )
|
||||
{ }
|
||||
else
|
||||
return ;
|
||||
|
||||
if (to_do == on_behalf_of && to_do != root_class)
|
||||
{ on_behalf_of->base = *((object_clasp *) (on_behalf_of->base)) ;
|
||||
} ;
|
||||
base = to_do->base ;
|
||||
system_class_init (base, base) ;
|
||||
system_class_init (base, on_behalf_of) ;
|
||||
|
||||
if (to_do == on_behalf_of)
|
||||
{ to_do->object_init = root_object_init ;
|
||||
to_do->new_obj = root_new ;
|
||||
to_do->free_obj = root_free ;
|
||||
} ;
|
||||
|
||||
#ifdef GLSDEBUG
|
||||
printf ("-> '%s' class for '%s'\n",
|
||||
to_do->name, on_behalf_of->name) ;
|
||||
#endif /* GLSDEBUG */
|
||||
|
||||
(*(to_do->class_init))(on_behalf_of);
|
||||
if (to_do == on_behalf_of) on_behalf_of->init = TRUE ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static void system_object_init (object_clasp c, object *p)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (!c) return ;
|
||||
|
||||
#ifdef GLSDEBUG
|
||||
printf (" '%s' object for '%s'\n", c->name, p->class_ptr->name) ;
|
||||
#endif /* GLSDEBUG */
|
||||
|
||||
system_object_init (c->base, p) ;
|
||||
|
||||
#ifdef GLSDEBUG
|
||||
printf ("-> '%s' object for '%s'\n", c->name, p->class_ptr->name) ;
|
||||
#endif /* GLSDEBUG */
|
||||
|
||||
(*(c->object_init))(p) ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static void root_class_init (object_clasp c)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
c->clone = root_clone ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static void root_object_init (object * UNUSED_PARM(p))
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
The clone (second) argument to the clone method may be either NULL or an
|
||||
object pointer. If NULL, a space of the size necessary for an object of
|
||||
the same class as the primary object (this) will be allocated. If the
|
||||
input argument is not null, it is assumed that the caller has verified
|
||||
there is sufficient space for a copy of the original object.
|
||||
If the clone procedure does allocate the space for the clone, it only
|
||||
allocates the space. It does not do object initialization.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static object *root_clone (object *this_ptr, object *clone)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
register XeString orig = (XeString) this_ptr ;
|
||||
register XeString copy ;
|
||||
|
||||
register object_clasp o_class = this_ptr->class_ptr ;
|
||||
register OSizeType size = o_class->object_size ;
|
||||
|
||||
if ( ! clone )
|
||||
clone = (*(o_class->new_obj))(o_class) ;
|
||||
if (clone) {
|
||||
copy = (XeString) clone ;
|
||||
while (size--)
|
||||
*copy++ = *orig++ ;
|
||||
}
|
||||
return clone ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static object *root_new (object_clasp c)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{ object *p = (object *)malloc((unsigned) c->object_size) ;
|
||||
|
||||
/* Don't use XeMalloc here, we want to be able to grab our Edit */
|
||||
/* widget without the rest of the world being pulled in. */
|
||||
if (!p)
|
||||
{
|
||||
fprintf(stderr, "scoop: malloc in root_new failed, out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return p ;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
static void root_free (object *p)
|
||||
/*--------------------------------------------------------------------------+*/
|
||||
{
|
||||
if (p) free ((char *)p) ;
|
||||
}
|
||||
|
||||
struct root_class root_class_struct = {
|
||||
(object_clasp) NULL, /* root has no base class */
|
||||
"root", /* class name */
|
||||
root_class_init,
|
||||
sizeof (object),
|
||||
0,
|
||||
} ;
|
||||
|
||||
object_clasp root_class = & root_class_struct ;
|
||||
407
cde/lib/DtSvc/DtEncap/spc-env.c
Normal file
407
cde/lib/DtSvc/DtEncap/spc-env.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* File: spc-env.c $TOG: spc-env.c /main/9 1998/04/10 08:27:04 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
|
||||
#include <bms/MemoryMgr.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
#include <XlationSvc.h>
|
||||
#include <LocaleXlate.h>
|
||||
|
||||
/* External declarations */
|
||||
|
||||
extern XeString official_hostname; /* from spc-net.c */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString SPC_Getenv(XeString var,
|
||||
XeString *envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int len;
|
||||
XeString *envidx;
|
||||
XeString idx;
|
||||
|
||||
/* First, check that we have real values */
|
||||
|
||||
if(!var || !envp || !*envp)
|
||||
return(XeString_NULL);
|
||||
|
||||
/* Look for '=' */
|
||||
|
||||
idx=strchr(var, Equal);
|
||||
|
||||
if(idx==0)
|
||||
/* No '='. Just use the entire var string */
|
||||
len=strlen(var);
|
||||
else
|
||||
/* found '='. Diddle pointers to get index of var */
|
||||
len=(strchr(var, Equal))-var;
|
||||
|
||||
for(envidx=envp; *envidx; envidx++) {
|
||||
if(!strncmp(*envidx, var, len))
|
||||
/* Found a match. Return value part */
|
||||
return(*envidx+len+1);
|
||||
}
|
||||
|
||||
return(XeString_NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** The purpose of SPC_Putenv is to maintain the environment pointers
|
||||
** associated with a given channel. It differs from the normal putenv
|
||||
** routine in the following ways:
|
||||
** 1. It copies its arguments (and frees any arguments which get a "hit")
|
||||
** 2. It takes an environment pointer which will be used to store the
|
||||
** new value. This new pointer may change (via realloc).
|
||||
**
|
||||
** Note: This routine makes a number of assumptions:
|
||||
** 1. The envp pointer was allocated via malloc.
|
||||
** 2. That it is okay to ignore error conditions. In particular,
|
||||
** it will ignore incorrect pointers (which is okay, as this
|
||||
** guy is an internal routine which means that these pointers
|
||||
** have been already checked), and it will ignore syntax errors
|
||||
** in the passed value. The latter ignore may be slightly
|
||||
** problematical, but it happens.
|
||||
** 3. That memory allocation errors cause the program to bomb.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString *SPC_Putenv(XeString val,
|
||||
XeString *envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
int len, newsize;
|
||||
XeString *envptr;
|
||||
char *pch;
|
||||
int remove_command = 0;
|
||||
#ifdef NLS16
|
||||
int is_multibyte = 0;
|
||||
#endif /* NLS16 */
|
||||
|
||||
#ifdef NLS16
|
||||
if (MB_CUR_MAX > 1)
|
||||
is_multibyte = 1;
|
||||
else
|
||||
is_multibyte = 0;
|
||||
#endif /* NLS16 */
|
||||
|
||||
/* Again, check for real values */
|
||||
|
||||
if(!val || !envp) {
|
||||
return(envp);
|
||||
}
|
||||
|
||||
/* Look for '=' */
|
||||
|
||||
len=(strchr(val, (XeChar)'='))-val;
|
||||
if(len<0) {
|
||||
/*
|
||||
* This string doesn't contain an '='. This may be OK if
|
||||
* the string contains a 'remove environment variable' keyword.
|
||||
* If this keyword is found, treat it like a variable and
|
||||
* the SPC daemon will find it and remove it from the
|
||||
* environment before it exec's a subprocess.
|
||||
*
|
||||
* If the string contains some white space before the variable
|
||||
* or keyword, skip the white space.
|
||||
*/
|
||||
pch = val;
|
||||
while (
|
||||
#ifdef NLS16
|
||||
(!is_multibyte || (mblen (pch, MB_CUR_MAX) == 1)) &&
|
||||
#endif
|
||||
isspace ((u_char)*pch))
|
||||
pch++;
|
||||
if (*pch == '\000')
|
||||
return (envp);
|
||||
if (strncmp (pch, SPC_REMOVE_VAR, strlen (SPC_REMOVE_VAR)))
|
||||
return(envp);
|
||||
remove_command = 1;
|
||||
val = pch;
|
||||
len = strlen (SPC_REMOVE_VAR);
|
||||
}
|
||||
|
||||
for(envptr=envp; *envptr; envptr++) {
|
||||
if(!strncmp(*envptr, val, len) && !remove_command) {
|
||||
/* Found a match. Replace this value with the one passed */
|
||||
free(*envptr);
|
||||
*envptr=SPC_copy_string(val);
|
||||
return(envp);
|
||||
}
|
||||
}
|
||||
|
||||
/* No match. We need to expand this env pointer, and stash the
|
||||
new value at the end */
|
||||
|
||||
len=envptr-envp;
|
||||
|
||||
/* calculate new size needed:
|
||||
len=ptr to null element
|
||||
newsize=len+2 (one for NULL, one for new element)
|
||||
*/
|
||||
|
||||
newsize=(len+2)*sizeof(XeString *);
|
||||
|
||||
/* Expand envp. This is a potentially expensive operation, if the
|
||||
realloc routine is not smart. */
|
||||
|
||||
if(!(envp=(XeString *)realloc((char *)envp, newsize))) {
|
||||
SPC_Error(SPC_Out_Of_Memory);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Okay. We got the new memory. Stash the new variable into it &
|
||||
return the new envp.*/
|
||||
|
||||
envp[len]=SPC_copy_string(val);
|
||||
envp[len+1]=XeChar_NULL;
|
||||
|
||||
return(envp);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString *SPC_Add_Env_File(XeString filename,
|
||||
XeString *envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
FILE *f;
|
||||
int n;
|
||||
XeChar fbuffer[BUFSIZ];
|
||||
|
||||
if(!filename)
|
||||
return(envp);
|
||||
|
||||
/* Open stream */
|
||||
|
||||
if(!(f=fopen(filename, "r")))
|
||||
return(envp);
|
||||
|
||||
while(fgets(fbuffer, BUFSIZ, f)) {
|
||||
n=strlen(fbuffer);
|
||||
if(fbuffer[n-1]==Newline)
|
||||
fbuffer[--n]=Pad; /* get rid of the extra newline */
|
||||
|
||||
/* Should we skip this line? */
|
||||
|
||||
if(n==XeChar_NULL || fbuffer[0]==Pad || fbuffer[0]==Pound) continue;
|
||||
|
||||
envp=SPC_Putenv(fbuffer, envp);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return(envp);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString *SPC_Create_Default_Envp(XeString *old_envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
XeString *envp;
|
||||
XeChar *display;
|
||||
XeString envVar;
|
||||
XeString sys_env_path = NULL;
|
||||
|
||||
if(old_envp)
|
||||
envp=old_envp;
|
||||
else {
|
||||
envp=(XeString *)XeMalloc(sizeof(XeString) * DEFAULT_ENVP_SIZE);
|
||||
envp[0]=XeChar_NULL;
|
||||
}
|
||||
|
||||
if(!(envVar=getenv("DISPLAY")))
|
||||
{
|
||||
display = (XeChar *)malloc(
|
||||
(strlen(official_hostname) + 11) * sizeof(XeChar));
|
||||
if (display != (XeChar *)NULL)
|
||||
sprintf(display, "DISPLAY=%s:0", official_hostname);
|
||||
}
|
||||
else
|
||||
{
|
||||
display = (XeChar *)malloc((strlen(envVar) + 9) * sizeof(XeChar));
|
||||
if (display != (XeChar *)NULL)
|
||||
sprintf(display, "DISPLAY=%s", envVar);
|
||||
}
|
||||
|
||||
if (display != (XeChar *)NULL)
|
||||
{
|
||||
envp=SPC_Putenv(display, envp);
|
||||
free(display);
|
||||
}
|
||||
|
||||
/*
|
||||
* Should we pick a default value for LANG (e.g. "C")?
|
||||
* For now we ignore it if it is not already set.
|
||||
*/
|
||||
if ((envVar = getenv("LANG")) != (XeString)NULL)
|
||||
{
|
||||
XeChar *langBuf;
|
||||
|
||||
if ((langBuf = (XeChar *)malloc((strlen(envVar) + 6) * sizeof(XeChar)))
|
||||
!= (XeChar *)NULL)
|
||||
{
|
||||
sprintf(langBuf, "LANG=%s", envVar);
|
||||
envp = SPC_Putenv(langBuf, envp);
|
||||
|
||||
free(langBuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* First add the installed environment file.
|
||||
*/
|
||||
sys_env_path = (XeString) malloc (strlen(SPCD_ENV_INSTALL_DIRECTORY) +
|
||||
strlen(SPCD_ENV_FILE) + 3);
|
||||
(void) sprintf (sys_env_path, "%s/%s",
|
||||
SPCD_ENV_INSTALL_DIRECTORY,
|
||||
SPCD_ENV_FILE);
|
||||
envp=SPC_Add_Env_File(sys_env_path, envp);
|
||||
|
||||
/*
|
||||
* Next add the configured environment file.
|
||||
*/
|
||||
sys_env_path = (XeString) realloc (sys_env_path,
|
||||
strlen(SPCD_ENV_CONFIG_DIRECTORY) +
|
||||
strlen(SPCD_ENV_FILE) + 3);
|
||||
(void) sprintf (sys_env_path, "%s/%s",
|
||||
SPCD_ENV_CONFIG_DIRECTORY,
|
||||
SPCD_ENV_FILE);
|
||||
envp=SPC_Add_Env_File(sys_env_path, envp);
|
||||
|
||||
/*
|
||||
* Now add the user environment file
|
||||
*/
|
||||
_DtSvcProcessLock();
|
||||
envp=SPC_Add_Env_File(spc_user_environment_file, envp);
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
free(sys_env_path);
|
||||
|
||||
return(envp);
|
||||
}
|
||||
|
||||
/* Final cleanup of environment pointer */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString *SPC_Fixup_Environment(XeString *envp,
|
||||
SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(!envp)
|
||||
return(envp);
|
||||
|
||||
if (IS_REMOTE(channel))
|
||||
{
|
||||
XeString disp, myLang;
|
||||
|
||||
disp=SPC_Getenv((XeString)"DISPLAY", envp);
|
||||
|
||||
/* I don't particularly like hard coding these values here.
|
||||
I have been bitten before by doing so, and probably will again... */
|
||||
if (!strncmp(disp, (XeString)"unix", 4) ||
|
||||
!strncmp(disp, (XeString)"local", 5) ||
|
||||
!strncmp(disp, (XeString)":", 1))
|
||||
{
|
||||
XeChar *dispBuf = NULL;
|
||||
XeString screenptr;
|
||||
XeChar null=XeChar_NULL;
|
||||
|
||||
dispBuf =
|
||||
(XeChar*) malloc(MAXHOSTNAMELEN + sizeof((XeString)"DISPLAY=:0.0") + 1);
|
||||
if (dispBuf)
|
||||
{
|
||||
screenptr=strchr(disp, Colon);
|
||||
sprintf(dispBuf, "DISPLAY=%s%s",
|
||||
official_hostname,
|
||||
screenptr ? screenptr : &null);
|
||||
|
||||
envp=SPC_Putenv(dispBuf, envp);
|
||||
free(dispBuf);
|
||||
}
|
||||
}
|
||||
|
||||
myLang = SPC_Getenv((XeString)"LANG", envp);
|
||||
if (myLang)
|
||||
{
|
||||
_DtXlateDb db = NULL;
|
||||
char platform[_DtPLATFORM_MAX_LEN];
|
||||
int execVer;
|
||||
int compVer;
|
||||
char *stdLang;
|
||||
XeChar *langBuf;
|
||||
|
||||
if (_DtLcxOpenAllDbs(&db) == 0)
|
||||
{
|
||||
if ((_DtXlateGetXlateEnv(db, platform, &execVer, &compVer) == 0) &&
|
||||
(_DtLcxXlateOpToStd(db, platform, compVer, DtLCX_OPER_SETLOCALE,
|
||||
myLang, &stdLang, NULL, NULL, NULL) == 0))
|
||||
{
|
||||
if ((langBuf = (XeChar *)malloc((strlen(stdLang) + 6) *
|
||||
sizeof(XeChar)))
|
||||
!= (XeChar *)NULL)
|
||||
{
|
||||
sprintf(langBuf, "LANG=%s", stdLang);
|
||||
envp = SPC_Putenv(langBuf, envp);
|
||||
free(langBuf);
|
||||
}
|
||||
|
||||
free(stdLang);
|
||||
}
|
||||
|
||||
_DtLcxCloseDb(&db);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(envp);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString *SPC_Merge_Envp(XeString *dest_envp,
|
||||
XeString *source_envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(!dest_envp || !source_envp)
|
||||
return(dest_envp);
|
||||
for(; *source_envp; source_envp++)
|
||||
dest_envp=SPC_Putenv(*source_envp, dest_envp);
|
||||
|
||||
return(dest_envp);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Free_Envp(XeString *envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString *envptr=envp;
|
||||
|
||||
if(!envptr)
|
||||
return;
|
||||
|
||||
while (*envptr)
|
||||
free(*envptr++);
|
||||
|
||||
free((char *)envp);
|
||||
}
|
||||
762
cde/lib/DtSvc/DtEncap/spc-error.c
Normal file
762
cde/lib/DtSvc/DtEncap/spc-error.c
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* $TOG: spc-error.c /main/10 1998/04/10 08:27:30 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <bms/MemoryMgr.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#define X_INCLUDE_TIME_H
|
||||
#define XOS_USE_XT_LOCKING
|
||||
#include <X11/Xos_r.h>
|
||||
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/*
|
||||
* Log file information (routines near bottom of file)
|
||||
*/
|
||||
|
||||
#define TEMPLATE_EXTENSION (XeString)".XXXXXX" /* For mktemp(3c) */
|
||||
|
||||
XeChar spc_logfile[MAXPATHLEN+1];
|
||||
XeChar spc_logging = FALSE;
|
||||
/* FILE *spc_logF = NULL; -- to bmsglob.c */
|
||||
|
||||
int spc_logfd = NULL;
|
||||
|
||||
/* This is the SPC error number variable */
|
||||
/* ------------------------------------- */
|
||||
/* int XeSPCErrorNumber = NULL; --- now in bmsglob.c */
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static XeString
|
||||
err_mnemonic(unsigned int errn, char *buff)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Since there is currently no standard way to get an err number */
|
||||
/* mnenonic from the system, we do it the hard way. We can't even */
|
||||
/* use a table as the actual numeric values may differ on machines. */
|
||||
/* Another potential problem is if one of these gets passed across */
|
||||
/* a network connection from a different type of machine that has */
|
||||
/* values that differ than the machine this routine runs on, we */
|
||||
/* could have problems. I don't think anycode does that now. */
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
XeString s;
|
||||
|
||||
switch (errn) {
|
||||
|
||||
/* These are all in POSIX 1003.1 and/or X/Open XPG3 */
|
||||
/* ---------------------------------------------------- */
|
||||
case EPERM : s = (XeString)"EPERM"; break;
|
||||
case ENOENT : s = (XeString)"ENOENT"; break;
|
||||
case ESRCH : s = (XeString)"ESRCH"; break;
|
||||
case EINTR : s = (XeString)"EINTR"; break;
|
||||
case EIO : s = (XeString)"EIO"; break;
|
||||
case ENXIO : s = (XeString)"ENXIO"; break;
|
||||
case E2BIG : s = (XeString)"E2BIG"; break;
|
||||
case ENOEXEC : s = (XeString)"ENOEXEC"; break;
|
||||
case EBADF : s = (XeString)"EBADF"; break;
|
||||
case ECHILD : s = (XeString)"ECHILD"; break;
|
||||
case EAGAIN : s = (XeString)"EAGAIN"; break;
|
||||
case ENOMEM : s = (XeString)"ENOMEM"; break;
|
||||
case EACCES : s = (XeString)"EACCES"; break;
|
||||
case EFAULT : s = (XeString)"EFAULT"; break;
|
||||
case ENOTBLK : s = (XeString)"ENOTBLK"; break;
|
||||
case EBUSY : s = (XeString)"EBUSY"; break;
|
||||
case EEXIST : s = (XeString)"EEXIST"; break;
|
||||
case EXDEV : s = (XeString)"EXDEV"; break;
|
||||
case ENODEV : s = (XeString)"ENODEV"; break;
|
||||
case ENOTDIR : s = (XeString)"ENOTDIR"; break;
|
||||
case EISDIR : s = (XeString)"EISDIR"; break;
|
||||
case EINVAL : s = (XeString)"EINVAL"; break;
|
||||
case ENFILE : s = (XeString)"ENFILE"; break;
|
||||
case EMFILE : s = (XeString)"EMFILE"; break;
|
||||
case ENOTTY : s = (XeString)"ENOTTY"; break;
|
||||
case ETXTBSY : s = (XeString)"ETXTBSY"; break;
|
||||
case EFBIG : s = (XeString)"EFBIG"; break;
|
||||
case ENOSPC : s = (XeString)"ENOSPC"; break;
|
||||
case ESPIPE : s = (XeString)"ESPIPE"; break;
|
||||
case EROFS : s = (XeString)"EROFS"; break;
|
||||
case EMLINK : s = (XeString)"EMLINK"; break;
|
||||
case EPIPE : s = (XeString)"EPIPE"; break;
|
||||
case ENOMSG : s = (XeString)"ENOMSG"; break;
|
||||
case EIDRM : s = (XeString)"EIDRM"; break;
|
||||
case EDEADLK : s = (XeString)"EDEADLK"; break;
|
||||
case ENOLCK : s = (XeString)"ENOLCK"; break;
|
||||
#ifndef __aix
|
||||
case ENOTEMPTY : s = (XeString)"ENOTEMPTY"; break;
|
||||
#endif
|
||||
case ENAMETOOLONG : s = (XeString)"ENAMETOOLONG"; break;
|
||||
case ENOSYS : s = (XeString)"ENOSYS"; break;
|
||||
|
||||
/* You could include machine specific stuff here ... */
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
default : s = XeString_NULL; break;
|
||||
}
|
||||
|
||||
|
||||
if (s)
|
||||
sprintf(buff, "%s (%d)",s,errn);
|
||||
else
|
||||
sprintf(buff, "(%d)",errn);
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString SPC_copy_string(XeString str)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int len;
|
||||
XeString tmp_str;
|
||||
|
||||
if(!str)
|
||||
return(XeString_NULL);
|
||||
|
||||
len=strlen(str);
|
||||
|
||||
tmp_str=(XeString)XeMalloc(len+1);
|
||||
strcpy(tmp_str, str);
|
||||
return(tmp_str);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Error (int error, ...)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
va_list ap;
|
||||
SPCError *err;
|
||||
XeChar *buffer;
|
||||
XeString arg1;
|
||||
long arg2;
|
||||
XeChar buff[40];
|
||||
|
||||
err=SPC_Lookup_Error(error);
|
||||
|
||||
if(!err)
|
||||
return;
|
||||
|
||||
if(err->text) {
|
||||
free(err->text);
|
||||
err->text = NULL;
|
||||
}
|
||||
|
||||
va_start(ap, error); /** Start varargs **/
|
||||
arg1=va_arg(ap, XeString);
|
||||
|
||||
if (arg1)
|
||||
{
|
||||
/* The argument on the stack may be holding an int or a char pointer. */
|
||||
/* Always popping off a long into the value of arg2 works fine */
|
||||
/* because the subsequent call to sprintf does the proper conversion via */
|
||||
/* "err->format". */
|
||||
arg2=va_arg(ap, long);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1 = XeString_Empty;
|
||||
arg2 = 0;
|
||||
}
|
||||
|
||||
buffer = (XeChar*) malloc(sizeof(XeChar) * SPC_BUFSIZ);
|
||||
if (buffer)
|
||||
{
|
||||
sprintf(buffer, err->format, arg1, arg2);
|
||||
err->text=SPC_copy_string(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
va_end(ap); /** End varargs **/
|
||||
|
||||
_DtSvcProcessLock();
|
||||
XeSPCErrorNumber=error;
|
||||
if (SPC_who_am_i == SPC_I_AM_A_DAEMON){
|
||||
|
||||
SPC_Format_Log((XeString)"DTSPCD error (%d): %s",
|
||||
XeSPCErrorNumber, err->text);
|
||||
if (err->use_errno){
|
||||
XeString errname;
|
||||
XeString errmsg;
|
||||
unsigned int errn = errno;
|
||||
|
||||
errname = err_mnemonic(errn, buff);
|
||||
|
||||
if (!(errmsg = strerror(errn)))
|
||||
errmsg = (XeString) "unknown";
|
||||
|
||||
SPC_Format_Log((XeString)" [%s] %s", errname, errmsg);
|
||||
}
|
||||
if(err->severity == XeFatalError || err->severity == XeInternalError) {
|
||||
SPC_Format_Log((XeString)"Exiting server ...");
|
||||
SPC_Close_Log();
|
||||
_DtSvcProcessUnlock();
|
||||
exit (3);
|
||||
}
|
||||
}
|
||||
else
|
||||
_DtSimpleError(XeProgName, XeError, XeString_NULL, err->text);
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log file routines
|
||||
*
|
||||
* Note: Current restriction of only one log file open at a time.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Make_Log_Filename(XeString name,
|
||||
int unique) /* When TRUE, make name unique */
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Make a log filename based on the passed name (and perhaps process id) */
|
||||
XeString cp;
|
||||
XeString log_file_path = NULL;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
/* first build the log file path */
|
||||
if (!name || !*name) {
|
||||
log_file_path = XeSBTempPath((XeString)"DTSPCD_log");
|
||||
strcpy(spc_logfile, log_file_path);
|
||||
}
|
||||
else {
|
||||
if (strlen(name) > MAXPATHLEN)
|
||||
_DtSimpleError(XeProgName, XeInternalError, XeString_NULL,
|
||||
(XeString)"String too long in DTSPCD_Make_Log_Filename()");
|
||||
|
||||
strcpy(spc_logfile, name);
|
||||
}
|
||||
|
||||
if (unique) {
|
||||
/* Add the extension. No strlen checking is done */
|
||||
strcat(spc_logfile, TEMPLATE_EXTENSION);
|
||||
|
||||
cp = (XeString) mktemp(spc_logfile);
|
||||
if (!cp || !*cp) {
|
||||
/* Sorry, but this is the best we can do */
|
||||
strcpy(spc_logfile, (log_file_path) ? log_file_path : name);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the strings allocated for the path */
|
||||
if (log_file_path) XeFree(log_file_path);
|
||||
_DtSvcProcessUnlock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Open_Log(XeString filename,
|
||||
int unique) /* When TRUE, make filename unique */
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Open the SPC log file */
|
||||
|
||||
/* Use the filename if one was passed to make a log filename */
|
||||
SPC_Make_Log_Filename(filename, unique);
|
||||
|
||||
/* Open the logfile */
|
||||
_DtSvcProcessLock();
|
||||
spc_logF = fopen(spc_logfile, "a+");
|
||||
if (!spc_logF) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
spc_logging = TRUE;
|
||||
|
||||
SPC_Format_Log((XeString)"*** DTSPCD logging started, file: `%s'", spc_logfile);
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Close_Log(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Close the current log file */
|
||||
|
||||
SPC_Format_Log((XeString)"*** DTSPCD logging stopped");
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (spc_logF) {
|
||||
fclose(spc_logF);
|
||||
}
|
||||
spc_logfd = NULL;
|
||||
spc_logF = NULL;
|
||||
spc_logging = FALSE;
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Write_Log(XeString str)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Write the passed message to the log file */
|
||||
time_t t;
|
||||
_Xctimeparams ctime_buf;
|
||||
char *result;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (spc_logging && spc_logF) {
|
||||
t = time(NULL);
|
||||
result = _XCtime(&t, ctime_buf);
|
||||
fprintf(spc_logF, "%s: %s", str, result);
|
||||
fflush(spc_logF);
|
||||
}
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int SPC_Format_Log (XeString format, ...)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Format the passed message to the log file */
|
||||
va_list args;
|
||||
time_t t;
|
||||
_Xctimeparams ctime_buf;
|
||||
char *result;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (spc_logging && spc_logF) {
|
||||
/* First the message */
|
||||
va_start(args, format);
|
||||
vfprintf(spc_logF, format, args);
|
||||
va_end(args);
|
||||
|
||||
/* Now a time stamp */
|
||||
t = time(NULL);
|
||||
result = _XCtime(&t, ctime_buf);
|
||||
fprintf(spc_logF, ": %s", result);
|
||||
fflush(spc_logF);
|
||||
}
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** This next routine used to be such a nice little guy... Once upon a
|
||||
** time I had all the error messages in a very
|
||||
** compact representation. It was a vector of SPCError structures.
|
||||
** When I wanted to go from the integer representation of an error to
|
||||
** its textual form, I simply did a table lookup. Unfortunately,
|
||||
** that method did not work at all well with the NLS scheme cooked up
|
||||
** by the Excalibur team. This scheme was nice for programs which
|
||||
** just had the strings in the text. It basically searched the
|
||||
** source program for a string with a funny symbol and replaced it
|
||||
** with a function call. Well, to make a long story short, I decided
|
||||
** to go with that scheme. Thus this function.
|
||||
**
|
||||
*/
|
||||
|
||||
SPCError spc_error_struct;
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPCError *SPC_Lookup_Error(int errornum)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
_DtSvcProcessLock();
|
||||
switch (errornum) {
|
||||
|
||||
case SPC_Out_Of_Memory:
|
||||
spc_error_struct.format = (XeString) "><Unable to allocate memory for internal SPC operation\n Perhaps you need to add more swap space to the system";
|
||||
spc_error_struct.severity = XeFatalError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Argument:
|
||||
spc_error_struct.format = (XeString) "><Bad argument to DTSPCD call";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Active_Channel:
|
||||
spc_error_struct.format = (XeString) "><Channel already active";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Inactive_Channel:
|
||||
spc_error_struct.format = (XeString) "><Channel is not active";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Internal_Error:
|
||||
spc_error_struct.format = (XeString) "><Internal SPC Error";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Cannot_Fork:
|
||||
spc_error_struct.format = (XeString) "><Cannot fork";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Cannot_Exec:
|
||||
spc_error_struct.format = (XeString) "><Cannot exec file %s.\nPerhaps your PATH variable is incorrect.\nUse the following errno value to further diagnose the problem.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_No_Pipe:
|
||||
spc_error_struct.format = (XeString) "><Cannot get pipe";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_No_Pty:
|
||||
spc_error_struct.format = (XeString) "><Unable to allocate pty for a DTSPCD channel.\nTry cleaning up some currently running processes to release their ptys,\nor reconfigure your kernel to increase the pty limit.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Connector:
|
||||
spc_error_struct.format = (XeString) "><Bad connector";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Reading:
|
||||
spc_error_struct.format = (XeString) "><Unexpected error reading data on connection to host %s.\nUse the following errno value to correct the problem.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Writing:
|
||||
spc_error_struct.format = (XeString) "><Unexpected error writing data on channel";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Service:
|
||||
spc_error_struct.format = (XeString) "><Unknown internet service %s/%s.\nMake an entry in your /etc/services file";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Unknown_Host:
|
||||
spc_error_struct.format = (XeString) "><Unable to find a host entry for %s.\nTry adding an entry in /etc/hosts for it.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Socket:
|
||||
spc_error_struct.format = (XeString) "><Socket failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Connect:
|
||||
spc_error_struct.format = (XeString) "><Connect call failed to remote host %s\nPerhaps the desktop is not installed on the remote host,\nor the remote inetd program needs to be restarted (via 'inetd -c'),\nor the remote file /etc/inetd.conf does not have an entry for the dtspcd process.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Bind:
|
||||
spc_error_struct.format = (XeString) "><Bind failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Accept:
|
||||
spc_error_struct.format = (XeString) "><Accept failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Reuse:
|
||||
spc_error_struct.format = (XeString) "><Reuse socket option failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Open:
|
||||
spc_error_struct.format = (XeString) "><Cannot open file";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Connection_EOF:
|
||||
if (SPC_who_am_i == SPC_I_AM_A_DAEMON)
|
||||
spc_error_struct.format = (XeString) "><Client has disconneted (received EOF).";
|
||||
else
|
||||
spc_error_struct.format = (XeString) "><The dtspcd process on host '%s' has terminated.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Timeout:
|
||||
spc_error_struct.format = (XeString) "><Internal timeout expired";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Protocol:
|
||||
spc_error_struct.format = (XeString) "><Illegal protocol request";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Unexpected_Reply:
|
||||
spc_error_struct.format = (XeString) "><Protocol error: unexpected reply";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_No_Channel:
|
||||
spc_error_struct.format = (XeString) "><Cannot initialize channel";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Illegal_Iomode:
|
||||
spc_error_struct.format = (XeString) "><Inconsistent iomode value specified";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_No_Signal_Handler:
|
||||
spc_error_struct.format = (XeString) "><Cannot set SIGCLD handler";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Operation:
|
||||
spc_error_struct.format = (XeString) "><Illegal operation";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Fd:
|
||||
spc_error_struct.format = (XeString) "><Bad file descriptor";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Ioctl:
|
||||
spc_error_struct.format = (XeString) "><ioctl call failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Select:
|
||||
spc_error_struct.format = (XeString) "><select call failed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bind_Timeout:
|
||||
spc_error_struct.format = (XeString) "><Timeout on bind";
|
||||
spc_error_struct.severity = XeWarning;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Arg_Too_Long:
|
||||
spc_error_struct.format = (XeString) "><Argument %.50s... to DTSPCD system call is too long, max. length is %d";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Write_Prot:
|
||||
spc_error_struct.format = (XeString) "><Error writing protocol request to host %s.\nPerhaps the remote server has crashed.\nUse the following errno value to diagnose the problem.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Username:
|
||||
spc_error_struct.format = (XeString) "><Incorrect user name";
|
||||
spc_error_struct.severity = XeFatalError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Password:
|
||||
spc_error_struct.format = (XeString) "><Incorrect password";
|
||||
spc_error_struct.severity = XeFatalError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Client_Not_Valid:
|
||||
spc_error_struct.format = (XeString) "><Client not valid";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Cannot_Open_Slave:
|
||||
spc_error_struct.format = (XeString) "><Unable to open slave pty %s.\nUse the following errno value to correct the problem";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Protocol_Abort:
|
||||
spc_error_struct.format = (XeString) "><Received ABORT protocol request on connection to %s.";
|
||||
spc_error_struct.severity = XeFatalError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Env_Too_Big:
|
||||
spc_error_struct.format = (XeString) "><Environment variable %.50s... too big,\nmaximum size is %d\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Unlink_Logfile:
|
||||
spc_error_struct.format = (XeString) "><Cannot unlink logfile";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Closed_Channel:
|
||||
spc_error_struct.format = (XeString) "><Channel already closed";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Authentication:
|
||||
spc_error_struct.format = (XeString) "><Cannot open user authentication file";
|
||||
spc_error_struct.severity = XeFatalError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Cannot_Open_Log:
|
||||
spc_error_struct.format = (XeString) "><Unable to open log file %s\nUse the following errno value to correct the problem";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Connection_Reset:
|
||||
spc_error_struct.format = (XeString) "><Remote data connection to %s reset by peer\nRemote host may not have an entry for the local host in /usr/adm/inetd.sec.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Register_Username:
|
||||
spc_error_struct.format = (XeString) "><Cannot register user --\nImproper password or uid for user '%s' on remote host '%s'.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Register_Netrc:
|
||||
spc_error_struct.format = (XeString) "><Cannot register user --\nUnable to create a pathname to the authentication file '%s' on host '%s'.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Register_Open:
|
||||
spc_error_struct.format = (XeString) "><Cannot register user --\nUnable to open authentication file '%s' on host '%s'.\nUse the following errno value to diagnose the problem.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Register_Handshake:
|
||||
spc_error_struct.format = (XeString) "><Cannot register user --\nPerhaps user '%s' does not have the same uid on host '%s'.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Termios_Mode :
|
||||
spc_error_struct.format = (XeString) "><An error has been detected in the TERMIOS_REQUEST data.\nThe item '%s' is not recognized as a valid item for the Mode flags.\nThe item has been ignored.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Termios_Speed :
|
||||
spc_error_struct.format = (XeString) "><An error has been detected in the TERMIOS_REQUEST data.\nThe item '%s' is not recognized as a valid item for a speed setting.\nThe item has been ignored.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Termios_CC :
|
||||
spc_error_struct.format = (XeString) "><An error has been detected in the TERMIOS_REQUEST data.\nThe item '%s' is not recognized as a valid item for a Control Character name/value pair.\nThe item has been ignored.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Termios_Proto :
|
||||
spc_error_struct.format = (XeString) "><An error has been detected in the TERMIOS_REQUEST data.\nThe string does not have the correct number of fields -- %s.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Signal_Name :
|
||||
spc_error_struct.format = (XeString) "><The signal '%s' is not supported on this machine.\nThe DTSPCD signal request has been ignored.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Signal_Value :
|
||||
spc_error_struct.format = (XeString) "><The signal %d is not supported by the XeSignalToName() routine.\nIt can not be sent via DTSPCD to a remote machine.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Signal_Format :
|
||||
spc_error_struct.format = (XeString) "><The APPLICATION_SIGNAL DTSPCD data '%s' is not recognized.\nIt is expected to be a signal name or a signal number.\n";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_tc_Call :
|
||||
spc_error_struct.format = (XeString) "><The terminal control call to '%s' failed.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_cannot_Chdir :
|
||||
spc_error_struct.format = (XeString) "><Cannot cd to directory '%s'.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Bad_Permission :
|
||||
spc_error_struct.format = (XeString) "><Incorrect permission on DTSPCD Authentication file.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = TRUE;
|
||||
break;
|
||||
|
||||
case SPC_Cannot_Create_Netfilename :
|
||||
spc_error_struct.format = (XeString) "><Cannot create a pathname to the current working\ndirectory '%s' from host '%s'.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
case SPC_Protocol_Version_Error:
|
||||
spc_error_struct.format = (XeString) "><SPC protocol version mismatch. The local version is %d, but the version of the SPC Daemon is %d. This operation requires equivalent protocol versions.";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
spc_error_struct.format = (XeString) "><Unknown error code";
|
||||
spc_error_struct.severity = XeError;
|
||||
spc_error_struct.use_errno = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(&spc_error_struct);
|
||||
}
|
||||
|
||||
978
cde/lib/DtSvc/DtEncap/spc-exec.c
Normal file
978
cde/lib/DtSvc/DtEncap/spc-exec.c
Normal file
@@ -0,0 +1,978 @@
|
||||
/*
|
||||
* File: spc-exec.c $TOG: spc-exec.c /main/9 1998/10/26 17:22:38 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/param.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
|
||||
#include <SPC/spc-proto.h>
|
||||
|
||||
#ifdef SVR4
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <Tt/tt_c.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* Global vars. */
|
||||
|
||||
SPC_Connection_Ptr write_terminator=NULL, read_terminator=NULL;
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
static char *get_path_from_context (
|
||||
char *context );
|
||||
static int remove_variable(
|
||||
char *string );
|
||||
static void resolve_variable_reference(
|
||||
char **string );
|
||||
|
||||
/*
|
||||
* This array contains the process id's of the sub-processes
|
||||
* started by the daemon. When a sub-process terminates, its
|
||||
* entry will be set to SPCD_DEAD_PROCESS. This list of pid's
|
||||
* is kept beause when the exit timer expires, if the daemon
|
||||
* has no sub-processes running, it will exit.
|
||||
*/
|
||||
pid_t *SPC_pid_list = NULL;
|
||||
|
||||
/*
|
||||
* This global variable is set by the daemon when the client
|
||||
* connects.
|
||||
*/
|
||||
int SPC_client_version_number = SPC_PROTOCOL_VERSION;
|
||||
|
||||
/*
|
||||
* If this variable is not NULL, it will contain the name of
|
||||
* the mount point environment variable plus its value thus it
|
||||
* ready for 'putenv'.
|
||||
*/
|
||||
char *SPC_mount_point_env_var = NULL;
|
||||
|
||||
/* External definitions */
|
||||
|
||||
extern XeChar spc_logging;
|
||||
extern XeString *environ;
|
||||
|
||||
/*
|
||||
* Routines for handling Sub-Processes
|
||||
*/
|
||||
|
||||
/*
|
||||
**
|
||||
** Initialize synchronous terminators.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Setup_Synchronous_Terminator(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int pipes[2];
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if(write_terminator) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if(pipe(pipes)<0) {
|
||||
SPC_Error(SPC_No_Pipe);
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if((write_terminator=SPC_Alloc_Connection())==SPC_ERROR) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
SPC_Add_Connection(write_terminator);
|
||||
|
||||
if((read_terminator=SPC_Alloc_Connection())==SPC_ERROR) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
SPC_Add_Connection(read_terminator);
|
||||
|
||||
write_terminator->sid=pipes[WRITE_SIDE];
|
||||
write_terminator->connected=TRUE;
|
||||
|
||||
read_terminator->sid=pipes[READ_SIDE];
|
||||
read_terminator->connected=TRUE;
|
||||
SPC_XtAddInput(NULL, &read_terminator->termination_id, read_terminator->sid,
|
||||
SPC_Conditional_Packet_Handler, SPC_Terminator);
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Connection_Ptr SPC_Channel_Terminator_Connection(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(IS_REMOTE(channel))
|
||||
return(channel->connection);
|
||||
else
|
||||
return(read_terminator);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Close_Unused(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Close any and all unused file descriptors */
|
||||
int fd;
|
||||
|
||||
for (fd = STDERR + 1; fd < max_fds; fd++) spc_close(fd);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_MakeSystemCommand(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
XeString shell;
|
||||
XeString *argv;
|
||||
XeString *tmp_argv;
|
||||
XeChar newargtwo[_POSIX_ARG_MAX];
|
||||
int argtwolen=0, tmplen=0;
|
||||
|
||||
/* Allocate our memory up front */
|
||||
|
||||
argv=Alloc_Argv(4);
|
||||
|
||||
newargtwo[argtwolen]=0;
|
||||
|
||||
/* copy path into newargtwo */
|
||||
|
||||
strncat(newargtwo, channel->path, _POSIX_ARG_MAX-1);
|
||||
strcat(newargtwo, (XeString)" ");
|
||||
argtwolen=strlen(newargtwo);
|
||||
|
||||
/* copy argv into newargtwo */
|
||||
for(tmp_argv=channel->argv; tmp_argv && *tmp_argv; tmp_argv++) {
|
||||
tmplen=strlen(*tmp_argv)+1; /* Room for extra space */
|
||||
if((tmplen+argtwolen)<_POSIX_ARG_MAX-1) {
|
||||
strcat(newargtwo, *tmp_argv);
|
||||
strcat(newargtwo, (XeString)" ");
|
||||
argtwolen += tmplen;
|
||||
} else {
|
||||
XeChar *errbuf;
|
||||
|
||||
errbuf = malloc(sizeof(XeChar) * 100);
|
||||
if (errbuf)
|
||||
{
|
||||
SPC_Free_Envp(argv);
|
||||
sprintf(errbuf,"(%d chars), max. length is %d",tmplen,_POSIX_ARG_MAX);
|
||||
SPC_Error(SPC_Arg_Too_Long, tmp_argv, _POSIX_ARG_MAX);
|
||||
free(errbuf);
|
||||
}
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* get a shell --
|
||||
First use the value of $SB_SHELL (if any),
|
||||
then try $SHELL,
|
||||
then use DEFAULT_SHELL
|
||||
*/
|
||||
|
||||
if(!(shell=getenv((XeString)"SB_SHELL")))
|
||||
if(!(shell=getenv((XeString)"SHELL")))
|
||||
shell = DEFAULT_SHELL;
|
||||
|
||||
/* setup argv properly */
|
||||
|
||||
argv[0]=SPC_copy_string(shell);
|
||||
argv[1]=SPC_copy_string((XeString)"-c");
|
||||
argv[2]=SPC_copy_string(newargtwo);
|
||||
argv[3]=NULL;
|
||||
channel->argv = argv;
|
||||
channel->IOMode |= SPCIO_DEALLOC_ARGV;
|
||||
|
||||
/* Now set this shell as the path */
|
||||
|
||||
channel->path = shell;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines for handling child process termination
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
/* This is the right way according to the Spec 1170 */
|
||||
void SPC_Child_Terminated(int i)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* This catches signals for sub-process termination */
|
||||
int type, cause, status;
|
||||
pid_t wait_pid, pid;
|
||||
SPC_Channel_Ptr channel;
|
||||
protocol_request req, *prot;
|
||||
buffered_data data, *pdata;
|
||||
int length;
|
||||
int indx;
|
||||
int saved_errno = errno;
|
||||
|
||||
prot = (&req);
|
||||
pdata = (&data);
|
||||
|
||||
prot->dataptr=pdata;
|
||||
|
||||
wait_pid = -1;
|
||||
while(pid = waitpid(wait_pid, &status, WNOHANG)) {
|
||||
if((pid == -1 && errno == ECHILD) || pid == 0) {
|
||||
/* no more children. Return */
|
||||
errno = saved_errno;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Okay, we got the process ID of a terminated child. Find the
|
||||
channel associated with this PID. */
|
||||
channel=SPC_Find_PID(pid);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, (XeString)"got SIGCHLD, pid: %d, channel: %p\n", pid, channel);
|
||||
#endif
|
||||
|
||||
if(!channel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_DtSvcProcessLock();
|
||||
/*
|
||||
* Look for this process in the pid list. If found, mark it
|
||||
* as done.
|
||||
*/
|
||||
if (SPC_pid_list != NULL) {
|
||||
for (indx=0; SPC_pid_list[indx] != NULL; indx++)
|
||||
if (SPC_pid_list[indx] == pid) {
|
||||
SPC_pid_list[indx] = SPCD_DEAD_PROCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
/* We have the channel. Mark it as being closed. */
|
||||
|
||||
channel->status = status;
|
||||
|
||||
/* If we this channel is set up for synchronous termination,
|
||||
write the protocol request to record that this guy died.
|
||||
Otherwise, call the termination handler directly. */
|
||||
|
||||
if(IS_SPCIO_SYNC_TERM(channel->IOMode)) {
|
||||
|
||||
/* This code is basically what SPC_Write_Protocol_Request does.
|
||||
It is replicated here because a call to SPC_W_P_R would have
|
||||
to be re-enterant if we called it here, and SPC_W_P_R is not
|
||||
re-enterant at this time. */
|
||||
|
||||
SPC_Reset_Protocol_Ptr(prot, channel, APPLICATION_DIED, 0);
|
||||
pdata->len=WRITE_APPLICATION_DIED(pdata, status);
|
||||
length=WRITE_HEADER(pdata, channel->cid,
|
||||
prot->request_type,
|
||||
pdata->len,
|
||||
0);
|
||||
pdata->data[length]=(XeChar)' ';
|
||||
length=pdata->len+REQUEST_HEADER_LENGTH;
|
||||
if(write(write_terminator->sid, pdata->data, length)==ERROR)
|
||||
SPC_Error(SPC_Internal_Error);
|
||||
pdata->offset=REQUEST_HEADER_LENGTH;
|
||||
print_protocol_request((XeString) (XeString)" <-- INTERNAL APPLICATION_DIED", prot);
|
||||
}
|
||||
else {
|
||||
SPC_Change_State(channel, NULL, -1, 0);
|
||||
if(channel->Terminate_Handler) {
|
||||
XeSPCGetProcessStatus(channel, &type, &cause);
|
||||
(* channel->Terminate_Handler)
|
||||
(channel, channel->pid, type, cause, channel->Terminate_Data);
|
||||
}
|
||||
}
|
||||
/* Loop around & get another PID */
|
||||
}
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Check to see if a given path names an executable file. Thus, we
|
||||
*** need to know if the file exists. If it is a directory, we want
|
||||
*** to fail. Otherwise, we want to us the system rules for checking
|
||||
*** on the file, and thus the 'access' call.
|
||||
***
|
||||
*/
|
||||
|
||||
static Boolean executable_predicate(XeString path, XeString dir, XeString file)
|
||||
{
|
||||
|
||||
struct stat file_status;
|
||||
|
||||
dir=dir;
|
||||
file=file;
|
||||
|
||||
if(stat(path, &file_status) != 0)
|
||||
return(FALSE);
|
||||
|
||||
if(S_ISDIR(file_status.st_mode))
|
||||
return(FALSE);
|
||||
|
||||
return(access(path, X_OK | F_OK) == 0);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int exec_proc_local_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
sigset_t newsigmask, oldsigmask;
|
||||
pid_t pid;
|
||||
int result;
|
||||
XeString *envp;
|
||||
XeString dir = XeString_NULL;
|
||||
int retval;
|
||||
int i, reuse_pid = 0;
|
||||
|
||||
call_parent_method(channel, exec_proc, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* Check to see if the channel pathname points to a valid executable.
|
||||
We do this by using the _path_search function. If the channel
|
||||
has a PATH variable set in its local environment, use it,
|
||||
otherwise use the "global" environment. We can accomplish this
|
||||
by using the spc_getenv call in the _path_search call. If the
|
||||
channel doesn't have a PATH variable, then spc_getenv will
|
||||
return NULL, which indicates use of the global environment.
|
||||
*/
|
||||
|
||||
if(!_path_search(SPC_Getenv("PATH", channel->envp),
|
||||
channel->path,
|
||||
executable_predicate)) {
|
||||
SPC_Error(SPC_Cannot_Exec, channel->path);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* If we were passed a host:dir to cd to, make sure it exists. */
|
||||
/* We want to do this before we fork the child. */
|
||||
|
||||
if((channel->context_dir) && (channel->context_dir[0])) {
|
||||
struct stat stat_info;
|
||||
Boolean ok = FALSE;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (SPC_client_version_number < SPC_PROTOCOL_VERSION_CDE_BASE)
|
||||
dir = get_path_from_context(channel->context_dir);
|
||||
else {
|
||||
/*
|
||||
* context_dir is actually a "netfile" so it needs to
|
||||
* be converted to a "real" path.
|
||||
*/
|
||||
dir = (char *) tt_netfile_file (channel->context_dir);
|
||||
if (tt_ptr_error (dir) != TT_OK)
|
||||
dir = NULL;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
if (dir == NULL)
|
||||
/* can't make connection ... */;
|
||||
else if (stat(dir,&stat_info) != 0)
|
||||
/* directory not there */;
|
||||
|
||||
else if ((stat_info.st_mode & S_IFDIR) == 0)
|
||||
/* path is not a directory ... */;
|
||||
else
|
||||
ok = TRUE;
|
||||
|
||||
if (!ok && IS_SPCIO_FORCE_CONTEXT(channel->IOMode)) {
|
||||
if (dir != NULL && (strcmp (dir, channel->context_dir) != 0))
|
||||
SPC_Error(SPC_cannot_Chdir, dir);
|
||||
SPC_Error(SPC_cannot_Chdir, channel->context_dir);
|
||||
XeFree(dir);
|
||||
dir = XeString_NULL;
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if(mempf0(channel, pre_fork)==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* When using HP NLIO (xj0input) we have a problem. Namely, */
|
||||
/* the xj0 processs uses signal() to deal with SIGCLD which */
|
||||
/* is incompatible with sigaction/sigprogmask/etc. Even */
|
||||
/* though xj0 resets the signal handler, since the signal */
|
||||
/* routines are incompatible, our original handler gets lost. */
|
||||
/* Hence, we need to reset it. We do it here everytime we */
|
||||
/* fork a child just to be on the safe side. */
|
||||
|
||||
SPC_ResetTerminator();
|
||||
|
||||
sigemptyset(&newsigmask);
|
||||
sigemptyset(&oldsigmask);
|
||||
sigaddset(&newsigmask, SIGCHLD);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask) == ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
pid = channel->pid = fork();
|
||||
|
||||
/*
|
||||
* Must save this pid so that when the daemon's timer goes off,
|
||||
* if there has been no activity and there are no sub-processes
|
||||
* running, the daemon can exit.
|
||||
*/
|
||||
i = 0;
|
||||
_DtSvcProcessLock();
|
||||
if (SPC_pid_list == NULL)
|
||||
/*
|
||||
* Create the first block plus the NULL terminator.
|
||||
*/
|
||||
SPC_pid_list = (pid_t *) malloc (2 * sizeof (pid_t));
|
||||
else {
|
||||
/*
|
||||
* If a dead pid entry exists, reuse it; otherwise, must create
|
||||
* room for the new pid.
|
||||
*/
|
||||
for (i = 0; SPC_pid_list[i] != NULL; i++)
|
||||
if (SPC_pid_list[i] == SPCD_DEAD_PROCESS) {
|
||||
SPC_pid_list[i] = pid;
|
||||
reuse_pid = 1;
|
||||
break;
|
||||
}
|
||||
if (!reuse_pid)
|
||||
SPC_pid_list = (pid_t *) realloc (SPC_pid_list,
|
||||
(i+2) * sizeof (pid_t));
|
||||
}
|
||||
if (!reuse_pid) {
|
||||
SPC_pid_list[i] = pid;
|
||||
SPC_pid_list[i+1] = NULL;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
if (pid) {
|
||||
XeFree(dir);
|
||||
|
||||
/* Did we really fork? */
|
||||
if (pid == ERROR) {
|
||||
SPC_Error(SPC_Cannot_Fork);
|
||||
retval = SPC_ERROR;
|
||||
} else {
|
||||
/* Do any set up for the parent process here */
|
||||
mempf1(channel, post_fork, pid);
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
/* Reinstate the old signal mask (unblock SIGCLD). */
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
return(retval);
|
||||
}
|
||||
else {
|
||||
/* Child process: connect wires, make environment and exec sub-process */
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
|
||||
/* Make sure the child is the process group leader. In the case of
|
||||
ptys, we also want to break the current terminal affiliation.
|
||||
We want to be the process group leader so XeSPCKillProcess (which
|
||||
does a kill(-pid, 9)) will kill all processes associated with us.
|
||||
|
||||
For PTY's, we need to break the terminal affiliation so the next
|
||||
open (which will be a pty) will cause us to become affiliated with
|
||||
the pty. We do this so when the parent process closes the master
|
||||
side of the pty, the slave side processes get SIGHUP. If they
|
||||
ignore SIGHUP, they will never die. So it goes...
|
||||
*/
|
||||
|
||||
if(IS_SPCIO_PTY(channel->IOMode))
|
||||
setsid();
|
||||
else {
|
||||
pid_t tmppid = getpid();
|
||||
if(setpgid(tmppid, tmppid) == -1)
|
||||
fprintf(stderr, (XeString)"setpgid failed, errno: %d\n", errno);
|
||||
}
|
||||
|
||||
/* Connect wires to sub-process standard files */
|
||||
result=mempf1(channel, post_fork, pid);
|
||||
|
||||
if(result!=SPC_ERROR) {
|
||||
int indx = -1;
|
||||
int i;
|
||||
char **ppch;
|
||||
|
||||
/*
|
||||
* Before adding in the list of environment variables
|
||||
* from the environment variable files, must search
|
||||
* the list for LANG definitions. If found, the
|
||||
* last definition must be putenv'ed to assure the
|
||||
* multi-byte parsing code is using the correct locale.
|
||||
*/
|
||||
for (i = 0, ppch = channel->envp; *ppch; *ppch++, i++)
|
||||
if (!strncmp (*ppch, "LANG=", 5))
|
||||
indx = i;
|
||||
|
||||
if (indx != -1)
|
||||
resolve_variable_reference (&channel->envp[indx]);
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (!setlocale (LC_CTYPE, ""))
|
||||
/*
|
||||
* setlocale failed - log a message but execute
|
||||
* the command anyway.
|
||||
*/
|
||||
if (SPC_Print_Protocol != NULL)
|
||||
(void) fprintf(SPC_Print_Protocol,
|
||||
"+++> Failed to 'setlocale'; LANG = %s\n",
|
||||
getenv("LANG"));
|
||||
/* Mix in the stashed environment */
|
||||
|
||||
for(envp=channel->envp; *envp; envp++)
|
||||
resolve_variable_reference(&*envp);
|
||||
|
||||
if (SPC_mount_point_env_var != NULL)
|
||||
/*
|
||||
* The mount point environment variable was
|
||||
* inherited by the daemon or was given to the
|
||||
* daemon via the command line. In either case
|
||||
* this subprocess must inherit the daemon's
|
||||
* value.
|
||||
*/
|
||||
(void) putenv (SPC_mount_point_env_var);
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
/* Connect to the context directory */
|
||||
/* We have already validated this guy exists */
|
||||
|
||||
if(dir)
|
||||
Xechdir(dir);
|
||||
}
|
||||
|
||||
XeFree(dir);
|
||||
|
||||
if(result!=SPC_ERROR) {
|
||||
/* Execute */
|
||||
/* Compiler barfs without cast ? */
|
||||
#if defined(__hpux_8_0) || defined(__aix)
|
||||
result=execvp(channel->path, channel->argv);
|
||||
#else
|
||||
result=execvp(channel->path, channel->argv);
|
||||
#endif
|
||||
/* If we return from exec, it failed */
|
||||
SPC_Error(SPC_Cannot_Exec, channel->path);
|
||||
}
|
||||
|
||||
/* We want to get rid of this child image (carefully) */
|
||||
_exit(42);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* get_path_from_context - given a 'context' string in the following form:
|
||||
*
|
||||
* [host:]path
|
||||
*
|
||||
* return the path component.
|
||||
*
|
||||
* NOTE - the caller must free the returned string.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* char *context - the context string to parse
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* A NULL if a pathname cannot be constructed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static char *get_path_from_context (
|
||||
char *context)
|
||||
{
|
||||
char *host = NULL;
|
||||
char *file = NULL;
|
||||
char *netfile = NULL;
|
||||
char *path = NULL;
|
||||
char tmp[MAXPATHLEN];
|
||||
char *pch;
|
||||
|
||||
/*
|
||||
* Break context into its host and file parts.
|
||||
*/
|
||||
if (context == NULL)
|
||||
return (NULL);
|
||||
|
||||
(void) strcpy (tmp, context);
|
||||
file = tmp;
|
||||
|
||||
if ((pch = (char *) strchr (tmp, ':')) != NULL) {
|
||||
host = tmp;
|
||||
file = pch + 1;
|
||||
*pch = '\000';
|
||||
}
|
||||
|
||||
if (!host)
|
||||
return (strdup (file));
|
||||
|
||||
netfile = (char *) tt_host_file_netfile (host, file);
|
||||
if (tt_ptr_error (netfile) != TT_OK) {
|
||||
SPC_Error (SPC_Cannot_Create_Netfilename, context, host);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
path = (char *) tt_netfile_file (netfile);
|
||||
tt_free (netfile);
|
||||
if (tt_ptr_error (path) != TT_OK) {
|
||||
SPC_Error (SPC_Cannot_Create_Netfilename, context, host);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* remove_variable ()
|
||||
*
|
||||
* This takes a string of the format:
|
||||
*
|
||||
* var_name=some_value | <remove_variable_keyword> var_name
|
||||
*
|
||||
* and if the second form is found, 'var_name' is removed from
|
||||
* the environment.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* char *string see the format above.
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* int 0 if 'string' contains a 'remove variable' command
|
||||
* 1 if string does not contain a 'remove variable' command
|
||||
*
|
||||
* Modified:
|
||||
*
|
||||
* char **environ 'var_name' is removed from the environment
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
static int
|
||||
remove_variable(
|
||||
char *string)
|
||||
{
|
||||
char *pch;
|
||||
char **ppch;
|
||||
char **ppch2;
|
||||
char *tmp_var;
|
||||
int tmp_len;
|
||||
|
||||
/*
|
||||
* If string contains some white space before the variable
|
||||
* or keyword, skip the white space.
|
||||
*/
|
||||
pch = string;
|
||||
while (
|
||||
#ifdef NLS16
|
||||
((mblen (pch, MB_CUR_MAX) == 1)) &&
|
||||
#endif /* NLS16 */
|
||||
isspace ((u_char)*pch))
|
||||
pch++;
|
||||
|
||||
if (*pch == '\000')
|
||||
return (1);
|
||||
if (strncmp (pch, SPC_REMOVE_VAR, strlen (SPC_REMOVE_VAR)))
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Skip the white space after the keyword and move to the
|
||||
* beginning of the variable.
|
||||
*/
|
||||
pch = pch + strlen (SPC_REMOVE_VAR);
|
||||
while (
|
||||
#ifdef NLS16
|
||||
((mblen (pch, MB_CUR_MAX) == 1)) &&
|
||||
#endif /* NLS16 */
|
||||
isspace ((u_char)*pch))
|
||||
pch++;
|
||||
|
||||
if (*pch == '\000')
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* pch should now point to the variable to be removed.
|
||||
*
|
||||
* tmp_var will be equal to the variable with a trailing '='.
|
||||
* This is added so the future comparison will not match
|
||||
* against variables that start with 'tmp_var' but then
|
||||
* have something else.
|
||||
*/
|
||||
tmp_var = malloc ((strlen (pch) + 2) * sizeof (char));
|
||||
(void) sprintf (tmp_var, "%s=", pch);
|
||||
tmp_len = strlen (tmp_var);
|
||||
|
||||
/*
|
||||
* Scan 'environ' for 'tmp_var'
|
||||
*/
|
||||
for (ppch = environ; *ppch; *ppch++) {
|
||||
if (!strncmp (tmp_var, *ppch, tmp_len)) {
|
||||
/*
|
||||
* Found the variable so remove it by moving all
|
||||
* variables after *ppch up.
|
||||
*/
|
||||
for (ppch2 = ppch; *ppch2; *ppch2++) {
|
||||
*ppch++;
|
||||
*ppch2 = *ppch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free ((char *) tmp_var);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* resolve_variable_reference ()
|
||||
*
|
||||
* This function takes a string of the format:
|
||||
*
|
||||
* var_name=some_value
|
||||
*
|
||||
* and if 'some_value' contains a reference to an environment
|
||||
* variable, the reference is replaced with the value of the
|
||||
* variable.
|
||||
*
|
||||
* For example, if 'string' is
|
||||
*
|
||||
* FOO=$VFA_TOP/foo
|
||||
*
|
||||
* and $VFA_TOP is '/some_tree', then 'string' will be changed to:
|
||||
*
|
||||
* FOO=/some_tree/foo
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* o 'putenv' will be invoked with argument 'string', even if 'string'
|
||||
* was not modified.
|
||||
*
|
||||
* o A valid variable name consists of alphanumerics and underscore
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* char **string MODIFIED - the environment variable
|
||||
* definition to be parsed
|
||||
*
|
||||
* Return Value:
|
||||
*
|
||||
* void
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
static void
|
||||
resolve_variable_reference(
|
||||
char **string ) /* MODIFIED */
|
||||
{
|
||||
char *string_end;
|
||||
char *var_start;
|
||||
char *pch;
|
||||
char *value;
|
||||
int n; /* number of bytes in a string */
|
||||
int len;
|
||||
int found_brace;
|
||||
char variable[256];
|
||||
char *buf = NULL;
|
||||
char *pbeg = *string;
|
||||
char *string_start = *string;
|
||||
|
||||
if (!remove_variable (*string))
|
||||
return;
|
||||
|
||||
pch = pbeg;
|
||||
|
||||
buf = malloc(2048);
|
||||
|
||||
while (*pbeg) {
|
||||
|
||||
/*
|
||||
* Look for '$' - the beginning of a variable reference.
|
||||
* If a '$' character is not found, exit the loop
|
||||
*/
|
||||
#ifdef NLS16
|
||||
while (*pch) {
|
||||
|
||||
if (((len = mblen (pch, MB_CUR_MAX)) == 1) && (*pch == '$'))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Move past this char
|
||||
*/
|
||||
if (len > 0)
|
||||
pch += len;
|
||||
else
|
||||
/*
|
||||
* pch is null or it points to an invalid mulit-byte
|
||||
* character.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
#else
|
||||
pch = strchr (pch, '$');
|
||||
#endif /* NLS16 */
|
||||
|
||||
if (pch == NULL || *pch == '\000')
|
||||
/*
|
||||
* The string doesn't contain any (more) variables
|
||||
*/
|
||||
break;
|
||||
|
||||
string_start = *string;
|
||||
|
||||
/*
|
||||
* Found a '$' - the beginning of an environment variable so
|
||||
* skip it and check the next char for '{' and if it is found
|
||||
* skip it and move to the real beginning of an env variable.
|
||||
*/
|
||||
string_end = pch;
|
||||
found_brace = 0;
|
||||
pch++;
|
||||
|
||||
#ifdef NLS16
|
||||
if ((mblen (pch, MB_CUR_MAX) == 1) && (*pch == '{')) {
|
||||
#else
|
||||
if (*pch == '{') {
|
||||
#endif /* NLS16 */
|
||||
pch++; /* input = ${ */
|
||||
found_brace = 1;
|
||||
}
|
||||
if (*pch == '\0') /* input = $\0 or ${\0 */
|
||||
break;
|
||||
|
||||
/*
|
||||
* Find the end of the variable name - it is assumed to
|
||||
* be the first character that is not an alpha-numeric
|
||||
* or '_'.
|
||||
*/
|
||||
var_start = pch;
|
||||
n = 0;
|
||||
|
||||
while (*pch) {
|
||||
#ifdef NLS16
|
||||
if ((mblen (pch, MB_CUR_MAX) > 1) ||
|
||||
((mblen (pch, MB_CUR_MAX) == 1) &&
|
||||
((*pch == '_') || (isalnum (*pch))))) {
|
||||
#else
|
||||
if (isalnum (*pch) || *pch == '_') {
|
||||
#endif /* NLS16 */
|
||||
|
||||
#ifdef NLS16
|
||||
len = mblen (pch, MB_CUR_MAX);
|
||||
#else
|
||||
len = 1;
|
||||
#endif /* NLS16 */
|
||||
n += len;
|
||||
pch += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef NLS16
|
||||
if (found_brace && (mblen (pch, MB_CUR_MAX) == 1) && (*pch == '}'))
|
||||
#else
|
||||
if (found_brace && *pch == '}')
|
||||
#endif /* NLS16 */
|
||||
/*
|
||||
* Move past the closing brace
|
||||
*/
|
||||
pch++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
/*
|
||||
* Nothing 'recognizable' follows the $ or ${
|
||||
*/
|
||||
pbeg = pch;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff the environment variable name in 'variable' and then
|
||||
* get its value. If the variable doesn't exist, leave its
|
||||
* name in the string.
|
||||
*/
|
||||
(void) strncpy (variable, var_start, n);
|
||||
variable[n] = '\0';
|
||||
|
||||
if ((value = getenv (variable)) == NULL) {
|
||||
/*
|
||||
* Leave what looks like an environment variable in place.
|
||||
*/
|
||||
pbeg = pch;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen (value) == 0) {
|
||||
pbeg = pch;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to replace the variable definition with the string
|
||||
* pointed to by 'value'. So create a string that contains the
|
||||
* characters before the environment variable, then the contents
|
||||
* of 'value' and finally, the characters after the environment
|
||||
* variable.
|
||||
*/
|
||||
if (string_end == string_start)
|
||||
/*
|
||||
* There is nothing to prepend before 'value'.
|
||||
*/
|
||||
buf[0] = '\0';
|
||||
else {
|
||||
(void) strncpy (buf, string_start, (string_end - string_start));
|
||||
buf[(string_end - string_start)] = '\0';
|
||||
}
|
||||
(void) strcat (buf, value);
|
||||
len = strlen (buf);
|
||||
if (*pch != '\0')
|
||||
(void) strcat (buf, pch);
|
||||
|
||||
/*
|
||||
* Now put 'buf' into 'string'.
|
||||
*/
|
||||
*string = realloc (*string, strlen (buf) + 1);
|
||||
(void) strcpy (*string, buf);
|
||||
pch = *string + len;
|
||||
pbeg = pch;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if no substitutions were made, the variable must
|
||||
* be put in the environment.
|
||||
*/
|
||||
(void) putenv (*string);
|
||||
if (buf) free(buf);
|
||||
}
|
||||
500
cde/lib/DtSvc/DtEncap/spc-net.c
Normal file
500
cde/lib/DtSvc/DtEncap/spc-net.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/* $XConsortium: spc-net.c /main/9 1996/11/21 19:53:44 drk $
|
||||
* File: spc-net.c
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define __need_timeval
|
||||
#define __need_fd_set
|
||||
#define __need_all_errors
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define X_INCLUDE_NETDB_H
|
||||
#define XOS_USE_XT_LOCKING
|
||||
#include <X11/Xos_r.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
#include <SPC/spc-proto.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
extern int SPC_Initialized;
|
||||
|
||||
/*
|
||||
****
|
||||
**** Client-side code
|
||||
****
|
||||
*/
|
||||
|
||||
/* Variables representing the local machine (initialized only once) */
|
||||
|
||||
static struct hostent *official_hp = NULL;
|
||||
XeString official_hostname = NULL;
|
||||
|
||||
/*
|
||||
* my_gethost will return a copy of the data returned by gethostbyname
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static struct hostent *my_gethost(XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
struct hostent *host_def, *copy;
|
||||
int alias_count, i, addr_count, addrlen;
|
||||
_Xgethostbynameparams host_buf;
|
||||
|
||||
host_def = _XGethostbyname(hostname, host_buf);
|
||||
if (host_def == NULL)
|
||||
return(FALSE);
|
||||
|
||||
copy=(struct hostent *)XeMalloc(sizeof(struct hostent));
|
||||
|
||||
/* Copy non-pointer info */
|
||||
memcpy((char *)copy, (char *)host_def, sizeof(struct hostent));
|
||||
|
||||
alias_count=0;
|
||||
|
||||
while(host_def->h_aliases[alias_count++]);
|
||||
|
||||
copy->h_aliases=(char **)XeMalloc(alias_count*(sizeof(XeString)));
|
||||
|
||||
addr_count=0;
|
||||
while(host_def->h_addr_list[addr_count++]);
|
||||
|
||||
copy->h_addr_list=(char **)XeMalloc(addr_count*(sizeof(XeString)));
|
||||
|
||||
/* Copy Hostname */
|
||||
|
||||
copy->h_name=SPC_copy_string(host_def->h_name);
|
||||
|
||||
/* Copy the host address. We do not use SPC_copy_string here,
|
||||
because the address is not a string, and may have embedded
|
||||
NULLs in it. */
|
||||
|
||||
addrlen = host_def->h_length;
|
||||
addr_count -= 1;
|
||||
copy->h_addr_list[addr_count]=XeChar_NULL;
|
||||
for (i=0; i < addr_count; i++) {
|
||||
copy->h_addr_list[i]=(char *)XeMalloc(addrlen);
|
||||
memcpy(copy->h_addr_list[i], host_def->h_addr_list[i], addrlen);
|
||||
}
|
||||
|
||||
while(alias_count--) {
|
||||
copy->h_aliases[alias_count]=SPC_copy_string(host_def->h_aliases[alias_count]);
|
||||
}
|
||||
|
||||
return(copy);
|
||||
}
|
||||
|
||||
/*
|
||||
* SPC_Lookup_Host will try its darndest to return a hostent structure
|
||||
* for the passed hostname.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static struct hostent *SPC_Lookup_Host(XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
struct hostent *official_def;
|
||||
|
||||
official_def = my_gethost(hostname);
|
||||
if(!official_def) {
|
||||
SPC_Error(SPC_Unknown_Host, hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(official_def);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SPC_Init_Local_Host_Info will initialize the local host info. It
|
||||
* is intended to be called only once.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
Boolean SPC_Init_Local_Host_Info(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
_DtSvcProcessLock();
|
||||
official_hostname=(XeString) XeMalloc(MAXHOSTNAMELEN+1);
|
||||
|
||||
Xegethostname(official_hostname, MAXHOSTNAMELEN);
|
||||
official_hostname[MAXHOSTNAMELEN]=0;
|
||||
|
||||
if(!official_hp)
|
||||
official_hp = SPC_Lookup_Host(official_hostname);
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return(official_hp != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* SPC_Local_Hostname takes a string indicating a hostname, and returns
|
||||
* TRUE if it represents a local host, and FALSE if it is remote.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Local_Hostname(XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Return TRUE if the specified hostname is local, otherwise it's remote */
|
||||
|
||||
/* If no hostname specified, then local by definition */
|
||||
|
||||
if (!hostname || !*hostname) return TRUE;
|
||||
|
||||
#ifdef DEBUG
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
return(XeIsLocalHostP(hostname));
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* SPC_Open_Connection will a connection pointer to be used for any
|
||||
* subsequent communication to the remote host. It will either return
|
||||
* an already opened connection, or create and initialize a new one.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Connection_Ptr SPC_Open_Connection(XeString hostname)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Connection_Ptr connection;
|
||||
int seqno;
|
||||
XeString canonical_hostname;
|
||||
int tmp_errorno;
|
||||
|
||||
/* I was told that XeFindShortHost was the correct routine to use here,
|
||||
but that may change in the future. */
|
||||
|
||||
canonical_hostname=XeFindShortHost(hostname);
|
||||
|
||||
/* check for a currently open connection */
|
||||
connection=SPC_Lookup_Connection(canonical_hostname);
|
||||
if(connection) {
|
||||
if(connection->connected) {
|
||||
XeFree(canonical_hostname);
|
||||
return(connection);
|
||||
}
|
||||
else {
|
||||
SPC_Close_Connection(connection);
|
||||
connection=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* None currently open. Grab a new one & initialize it. */
|
||||
|
||||
if((connection = SPC_Make_Connection(canonical_hostname))==SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
XeFree(canonical_hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
connection->local=official_hp;
|
||||
if((connection->remote = SPC_Lookup_Host(canonical_hostname)) == SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
XeFree(canonical_hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(SPC_Contact_Server(connection)==SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
XeFree(canonical_hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
connection->connected=TRUE;
|
||||
|
||||
if(SPC_Validate_User(canonical_hostname, connection)==SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
XeFree(canonical_hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
seqno=SPC_Write_Protocol_Request(connection, NULL, ENVIRON_RESET);
|
||||
_DtSvcProcessLock();
|
||||
tmp_errorno = XeSPCErrorNumber;
|
||||
if(SPC_Waitfor_Reply(connection, NULL, seqno) == SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
/*
|
||||
* XeSPCErrorNumber could have been changed but want to
|
||||
* return the value from Write_Protocol_Request to the
|
||||
* client.
|
||||
*/
|
||||
if (tmp_errorno != 0)
|
||||
XeSPCErrorNumber = tmp_errorno;
|
||||
XeFree(canonical_hostname);
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
/* We no long ever send a RESET_TERMIO request as this was hpux */
|
||||
/* specific and VERY non-portable. */
|
||||
|
||||
if (connection->protocol_version >= 2) {
|
||||
seqno=SPC_Write_Protocol_Request(connection, NULL, RESET_TERMIOS);
|
||||
if(SPC_Waitfor_Reply(connection, NULL, seqno) == SPC_ERROR) {
|
||||
SPC_Close_Connection(connection);
|
||||
XeFree(canonical_hostname);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
XeFree(canonical_hostname);
|
||||
return(connection);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Open_Socket(SPC_Connection_Ptr conn,
|
||||
int type)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
struct servent *service;
|
||||
|
||||
conn->sid=socket(type, SOCK_STREAM, NULL);
|
||||
if(conn->sid == ERROR) {
|
||||
SPC_Error(SPC_Bad_Socket);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
service=getservbyname(SPC_SERVICE, SPC_PROTOCOL);
|
||||
if (!service) {
|
||||
SPC_Error(SPC_Bad_Service, SPC_SERVICE, SPC_PROTOCOL);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(service->s_port);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* SPC_Contact_Server will attempt to contact the server specified by
|
||||
* the passed connection data structure. IT ASSUMES THAT ALL FIELDS
|
||||
* EXCEPT THE SOCKET ID ARE FILLED IN!!!
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Contact_Server(SPC_Connection_Ptr connection)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
short addrtype;
|
||||
struct hostent *remote;
|
||||
|
||||
|
||||
/* Check that the connection is initialized correctly */
|
||||
if(!connection)
|
||||
return(SPC_ERROR);
|
||||
if(!(remote=connection->remote))
|
||||
return(SPC_ERROR);
|
||||
if(connection->connected)
|
||||
return(TRUE);
|
||||
|
||||
addrtype=saddr.sin_family=remote->h_addrtype;
|
||||
if(!(saddr.sin_port=SPC_Open_Socket(connection, addrtype)))
|
||||
return(SPC_ERROR);
|
||||
memcpy(&saddr.sin_addr, remote->h_addr, remote->h_length);
|
||||
|
||||
if(connect(connection->sid, (struct sockaddr *)&saddr, sizeof(saddr)) == ERROR) {
|
||||
SPC_Error(SPC_Bad_Connect,
|
||||
XeFindShortHost(remote->h_name));
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
****
|
||||
**** Server (daemon) side code
|
||||
****
|
||||
*/
|
||||
|
||||
#define BACKLOG 50
|
||||
#define MAX_SERVER_BIND_ATTEMPTS 30
|
||||
#define SERVER_PAUSE_INTERVAL 10
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Connection_Ptr SPC_Init_Child(SPC_Connection_Ptr conn,
|
||||
int from)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* We are the child. Close the connection file descriptor
|
||||
(which is the socket, not our input). */
|
||||
close(conn->sid);
|
||||
|
||||
/* Make the from file descriptor correspond to STDIN/STDOUT */
|
||||
dup2(from, STDIN);
|
||||
close(from);
|
||||
dup2(STDIN, STDOUT);
|
||||
|
||||
/* make conn point to STDIN */
|
||||
|
||||
conn->sid=STDIN;
|
||||
|
||||
return(conn);
|
||||
}
|
||||
|
||||
SPC_Connection_Ptr SPC_Standalone_Daemon(SPC_Connection_Ptr conn)
|
||||
{
|
||||
struct sockaddr_in saddr, client_saddr;
|
||||
#ifdef USL
|
||||
/* Only UnixWare 2.02 uses the Spec1170 parameter profile for accept(). */
|
||||
size_t len=sizeof(client_saddr);
|
||||
#else
|
||||
int len=sizeof(client_saddr);
|
||||
#endif
|
||||
int server_bind_attempts = MAX_SERVER_BIND_ATTEMPTS;
|
||||
int server_bind_pause = SERVER_PAUSE_INTERVAL;
|
||||
int pid, from;
|
||||
#if defined(__aix)
|
||||
int on=1; /* required by setsockopt */
|
||||
#endif
|
||||
|
||||
saddr.sin_family=AF_INET;
|
||||
if(!(saddr.sin_port=SPC_Open_Socket(conn, saddr.sin_family)))
|
||||
return(SPC_ERROR);
|
||||
saddr.sin_addr.s_addr=INADDR_ANY; /* Any host address */
|
||||
|
||||
/* Reuse the socket address if it is still in a timeout state */
|
||||
|
||||
#if defined(__aix)
|
||||
if (setsockopt(conn->sid, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))==ERROR) {
|
||||
#else
|
||||
if (setsockopt(conn->sid, SOL_SOCKET, SO_REUSEADDR, NULL, NULL)==ERROR) {
|
||||
#endif
|
||||
SPC_Error(SPC_Bad_Reuse);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
while (bind(conn->sid, (struct sockaddr *)&saddr, sizeof(saddr)) == ERROR) {
|
||||
if (errno == EADDRINUSE) {
|
||||
SPC_Error(SPC_Bind_Timeout);
|
||||
/* Try to get the connection in a little while */
|
||||
if (server_bind_attempts > 0) {
|
||||
server_bind_attempts--;
|
||||
sleep(server_bind_pause);
|
||||
}
|
||||
else {
|
||||
/* We don't want to wait forever */
|
||||
SPC_Error(SPC_Timeout);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
} else {
|
||||
SPC_Error(SPC_Bad_Bind);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a queue for incoming connection requests */
|
||||
|
||||
listen(conn->sid, BACKLOG);
|
||||
|
||||
/* We are running standalone, so we need to loop forever waiting for
|
||||
requests. When we get one, we will fork a child to take care of
|
||||
the processing for us, and then the parent will listen some more */
|
||||
|
||||
for(;;) {
|
||||
struct hostent *addr_ret;
|
||||
_Xgethostbynameparams addr_buf;
|
||||
|
||||
/* Attempt to accept a connection with a client */
|
||||
|
||||
from = accept(conn->sid, (struct sockaddr *)&client_saddr, &len);
|
||||
if (from == ERROR) {
|
||||
SPC_Error(SPC_Bad_Accept);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
addr_ret = _XGethostbyaddr((char *)&client_saddr.sin_addr,
|
||||
sizeof(client_saddr.sin_addr),
|
||||
client_saddr.sin_family,
|
||||
addr_buf);
|
||||
|
||||
conn->remote = addr_ret;
|
||||
strncpy(conn->hostname, conn->remote->h_name, MAXHOSTNAMELEN);
|
||||
|
||||
#ifdef DEBUG
|
||||
pid = NULL;
|
||||
#else
|
||||
/* Fork a process to handle I/O from/to client */
|
||||
pid = fork();
|
||||
#endif
|
||||
|
||||
if (pid == ERROR) {
|
||||
SPC_Error(SPC_Cannot_Fork);
|
||||
/* We don't return here, but simply go around for a new try */
|
||||
}
|
||||
|
||||
if (!pid)
|
||||
/* We are the child. Do whatever processing we need to do
|
||||
on the connection & return */
|
||||
return(SPC_Init_Child(conn, from));
|
||||
/* Otherwise, we are still the parent. Loop around for another
|
||||
connection request */
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Inetd_Daemon(SPC_Connection_Ptr conn)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
conn->sid=0;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Connection_Ptr SPC_Start_Daemon(int standalone)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Connection_Ptr connection;
|
||||
|
||||
/* Do whatever it takes to initialize SPC */
|
||||
_DtSvcProcessLock();
|
||||
if (!SPC_Initialized)
|
||||
if(SPC_Initialize()==SPC_ERROR) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
/* Get ourselves a connection structure. We don't know the name
|
||||
of the remote client yet, so use the null string as hostname */
|
||||
|
||||
if((connection=SPC_Make_Connection(NULL))==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
connection->local=official_hp;
|
||||
if(standalone) {
|
||||
if((SPC_Standalone_Daemon(connection))==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
} else {
|
||||
if((SPC_Inetd_Daemon(connection))==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
connection->connected=TRUE;
|
||||
return(connection);
|
||||
}
|
||||
666
cde/lib/DtSvc/DtEncap/spc-obj.c
Normal file
666
cde/lib/DtSvc/DtEncap/spc-obj.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* File: spc-obj.c $TOG: spc-obj.c /main/6 1997/12/29 10:43:29 bill $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <signal.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
|
||||
#include <SPC/spc-proto.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* global declarations */
|
||||
|
||||
/* SPC_Initialized is in bmsglob.c */
|
||||
|
||||
extern int SPC_Initialized;
|
||||
|
||||
/* external declarations */
|
||||
|
||||
extern SPC_Channel_Ptr spc_activation_list;
|
||||
extern XeString spc_user_environment_file;
|
||||
|
||||
/*
|
||||
* Global variable to specifying whether the process using this
|
||||
* library is a SPC client or a SPC daemon. If the process is a
|
||||
* client, the SIGCLD signal handler will not be installed.
|
||||
* However, if the process is the daemon, the signal handler will
|
||||
* be installed.
|
||||
*
|
||||
* This will be set to 'SPC_I_AM_A_DAEMON' by the spcd process.
|
||||
*/
|
||||
int SPC_who_am_i = SPC_I_AM_A_CLIENT;
|
||||
|
||||
/* Initialization functions for class objects */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
object *alloc_channel_object(object_clasp c)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
object *p=(object *) XeMalloc((unsigned) c->object_size);
|
||||
memset(p, NULL, (int) c->object_size);
|
||||
return(p);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void channel_class_init(object_clasp t)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
channel_clasp c = (channel_clasp) t;
|
||||
|
||||
c->new_obj = alloc_channel_object;
|
||||
|
||||
c->open = open_channel_object;
|
||||
c->close = close_channel_object;
|
||||
c->read = read_channel_object;
|
||||
c->write = write_channel_object;
|
||||
c->reset = reset_channel_object;
|
||||
c->pre_fork = pre_fork_channel_object;
|
||||
c->post_fork = post_fork_channel_object;
|
||||
c->exec_proc = exec_proc_channel_object;
|
||||
c->signal = signal_channel_object;
|
||||
c->wait_for_termination = channel_object_wait_for_termination;
|
||||
c->attach = attach_channel_object;
|
||||
c->input = NULL;
|
||||
c->add_input = add_input_channel_object;
|
||||
c->remove_logfile = remove_logfile_channel_object;
|
||||
}
|
||||
|
||||
static struct channel_class channel_class_struct = {
|
||||
(root_clasp) &root_class, /* base class pointer */
|
||||
"channel", /* class name */
|
||||
channel_class_init, /* class initialize function */
|
||||
sizeof(SPC_Channel), /* size */
|
||||
0
|
||||
};
|
||||
|
||||
channel_clasp channel_class = &channel_class_struct;
|
||||
|
||||
static Wire dummy_wire={
|
||||
0, /* Flags */
|
||||
-1, -1, /* File Descriptors */
|
||||
(XeString) "/dev/null", /* Master PTY */
|
||||
(XeString) "/dev/null", /* Slave PTY */
|
||||
0, 0, /* Toolkit IDs */
|
||||
NULL /* pointer to next wire */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_ResetTerminator(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
struct sigaction svect;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (SPC_who_am_i == SPC_I_AM_A_DAEMON) {
|
||||
svect.sa_handler = SPC_Child_Terminated;
|
||||
sigemptyset(&svect.sa_mask);
|
||||
svect.sa_flags = 0;
|
||||
|
||||
if(sigaction(SIGCHLD, &svect, (struct sigaction *)NULL)==ERROR) {
|
||||
SPC_Error(SPC_No_Signal_Handler);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Initialize(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
XeString home;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if(SPC_Initialized) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
spc_init_fds();
|
||||
|
||||
if (!SPC_ResetTerminator()) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(!SPC_Init_Local_Host_Info()) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(SPC_Setup_Synchronous_Terminator()==SPC_ERROR) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(home=getenv("HOME")) {
|
||||
spc_user_environment_file=(XeString) XeMalloc(strlen(home)+
|
||||
strlen(SPCD_ENV_HOME_DIRECTORY)+strlen(SPCD_ENV_FILE)+3);
|
||||
sprintf(spc_user_environment_file, "%s/%s/%s",
|
||||
home, SPCD_ENV_HOME_DIRECTORY, SPCD_ENV_FILE);
|
||||
}
|
||||
|
||||
SPC_Initialized=TRUE;
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Initialize_Channel will create & return a channel object,
|
||||
** based on the values of hostname and iomode.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr SPC_Initialize_Channel(XeString hostname,
|
||||
int iomode)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Channel_Ptr channel;
|
||||
|
||||
/* Check for local or remote machine. If remote, create a
|
||||
remote channel object */
|
||||
if (!SPC_Local_Hostname(hostname)) {
|
||||
channel=(SPC_Channel_Ptr)object_create((object_clasp)remote_channel_class);
|
||||
|
||||
} else {
|
||||
|
||||
/* We are local. Create the appropriate object. */
|
||||
|
||||
if(IS_SPCIO_NOIOMODE(iomode))
|
||||
channel=(SPC_Channel_Ptr)object_create((object_clasp)noio_channel_class);
|
||||
|
||||
if(IS_SPCIO_PIPE(iomode))
|
||||
channel=(SPC_Channel_Ptr)object_create((object_clasp)pipe_channel_class);
|
||||
|
||||
if(IS_SPCIO_PTY(iomode))
|
||||
channel=(SPC_Channel_Ptr)object_create((object_clasp)pty_channel_class);
|
||||
|
||||
}
|
||||
|
||||
return(channel);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Channel_Terminated will do any work necessary on a channel when
|
||||
** we detect that a subprocess has terminated.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Channel_Terminated(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int type, cause;
|
||||
|
||||
SPC_Change_State(channel, NULL, -1, 0);
|
||||
|
||||
/* Set the close timeout. If we are on a PTY, we will return
|
||||
after two seconds if we are waiting for EOF */
|
||||
|
||||
channel->close_timeout=2;
|
||||
|
||||
if(IS_DATA(channel) && (channel->Input_Handler)) {
|
||||
while(IS_SPCIO_DATA(channel->wires[STDOUT]->flags))
|
||||
SPC_Input_Handler(channel, STDOUT);
|
||||
while(IS_SPCIO_DATA(channel->wires[STDERR]->flags))
|
||||
SPC_Input_Handler(channel, STDERR);
|
||||
}
|
||||
|
||||
if(channel->Terminate_Handler) {
|
||||
XeSPCGetProcessStatus(channel, &type, &cause);
|
||||
(* channel->Terminate_Handler)
|
||||
(channel, channel->pid, type, cause, channel->Terminate_Data);
|
||||
}
|
||||
|
||||
channel->close_timeout=0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Check style makes sure that we have a legal IOMode.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Check_Style(int iomode)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int stylecount=0;
|
||||
|
||||
/* First, make sure that we have only one style bit set */
|
||||
|
||||
/*** NOTE - We can probably do something more tricky here, to be more
|
||||
efficient. However, I am going to do this the slow way to be safe */
|
||||
|
||||
if(IS_SPCIO_NOIOMODE(iomode))
|
||||
stylecount++;
|
||||
if(IS_SPCIO_PIPE(iomode))
|
||||
stylecount++;
|
||||
if(IS_SPCIO_PTY(iomode))
|
||||
stylecount++;
|
||||
|
||||
if(stylecount != 1) {
|
||||
SPC_Error(SPC_Illegal_Iomode);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* Okay, now check to make sure we don't have any conflicting
|
||||
modes set */
|
||||
|
||||
if ((IS_SPCIO_LINEEDIT(iomode) && IS_SPCIO_PIPE(iomode)) ||
|
||||
(IS_SPCIO_PTY(iomode) && IS_SPCIO_WAIT(iomode) &&
|
||||
!IS_SPCIO_TOOLKIT(iomode)) ||
|
||||
(!IS_SPCIO_NOIO(iomode) && IS_SPCIO_USE_LOGFILE(iomode))
|
||||
)
|
||||
{
|
||||
SPC_Error(SPC_Illegal_Iomode);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Transform_Iomode will transform a user-specified iomode into
|
||||
** one that is suitable for use by SPC. It will then check the new
|
||||
** iomode to make sure that it is legal.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Transform_Iomode(int iomode)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(IS_SPCIO_NOIO(iomode))
|
||||
iomode |= SPCIO_NOIOMODE;
|
||||
if(IS_SPCIO_DEFAULT(iomode))
|
||||
iomode |= SPCIO_DEFAULT;
|
||||
if(IS_SPCIO_TOOLKIT(iomode))
|
||||
iomode |= SPCIO_SYNC_TERMINATOR;
|
||||
|
||||
/* Check to make sure that the iomode is consistent */
|
||||
|
||||
if(SPC_Check_Style(iomode)==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(iomode);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Newline_Filter will return only lines that end in newlines, or
|
||||
** 'ntoread' characters if no newline is found in time. It will also
|
||||
** return as many characters as have been read in the case of EOF.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Newline_Filter(SPC_Channel_Ptr channel,
|
||||
int connector,
|
||||
XeString buffer,
|
||||
int ntoread)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
buffered_data_ptr cbuf;
|
||||
XeString usrptr;
|
||||
XeString cbufptr;
|
||||
int nchars, nlcopied, scalarlen, nchars_this_buffer;
|
||||
|
||||
if(!(cbuf=channel->linebufs[connector])) {
|
||||
if((cbuf=SPC_New_Buffered_Data_Ptr())==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
channel->linebufs[connector]=cbuf;
|
||||
}
|
||||
|
||||
usrptr=buffer;
|
||||
cbufptr=cbuf->data+cbuf->offset;
|
||||
nchars=0;
|
||||
nlcopied = FALSE;
|
||||
channel->IOMode &= ~SPCIO_HAS_DATA;
|
||||
|
||||
do {
|
||||
|
||||
nchars_this_buffer=0;
|
||||
scalarlen=cbuf->len;
|
||||
|
||||
while(nchars<ntoread && nchars_this_buffer<scalarlen && !nlcopied) {
|
||||
nlcopied = (*cbufptr == Newline);
|
||||
*usrptr++ = (*cbufptr++);
|
||||
nchars++;
|
||||
nchars_this_buffer++;
|
||||
}
|
||||
|
||||
if(nchars == ntoread || nlcopied) {
|
||||
cbuf->offset += nchars_this_buffer;
|
||||
cbuf->len -= nchars_this_buffer;
|
||||
if(strchr(cbuf->data+cbuf->offset, Newline))
|
||||
channel->IOMode |= SPCIO_HAS_DATA;
|
||||
return(nchars);
|
||||
}
|
||||
|
||||
cbufptr = cbuf->data;
|
||||
cbuf->offset = 0;
|
||||
do {
|
||||
cbuf->len=mempf3(channel, read, connector, cbufptr, SPC_BUFSIZ);
|
||||
} while(cbuf->len == (EXCEPT_FLAG));
|
||||
|
||||
cbufptr[cbuf->len]=0;
|
||||
|
||||
} while((cbuf->len) > 0);
|
||||
|
||||
return(nchars);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Input_Handler(SPC_Channel_Ptr channel,
|
||||
int connector)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int nchars;
|
||||
XeChar spc_iobuffer[SPC_BUFSIZ+1];
|
||||
|
||||
channel->IOMode &= ~SPCIO_HAS_DATA;
|
||||
|
||||
do {
|
||||
|
||||
nchars=(*channel->read_filter)
|
||||
(channel, connector, spc_iobuffer, SPC_BUFSIZ);
|
||||
|
||||
/* Check nchars. If it is EXCEPT_FLAG, we had a special occurance (such
|
||||
as an ioctl on a PTY). In any case, don't do any more processing */
|
||||
|
||||
if(nchars==EXCEPT_FLAG)
|
||||
return(FALSE);
|
||||
|
||||
/* Call Read handlers */
|
||||
|
||||
spc_iobuffer[nchars]=XeChar_NULL;
|
||||
|
||||
if(channel->Input_Handler)
|
||||
(* channel->Input_Handler)
|
||||
(channel->client_data, spc_iobuffer, nchars, connector);
|
||||
|
||||
} while(HAS_DATA(channel));
|
||||
|
||||
return(nchars);
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Method definitions for channel objects
|
||||
***
|
||||
*/
|
||||
|
||||
/*
|
||||
* This routine handles initialization which must occur for every channel.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr open_channel_object(SPC_Channel_Ptr channel,
|
||||
int iomode,
|
||||
XeString UNUSED_PARM(hostname))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
|
||||
/* initialize local data structures */
|
||||
|
||||
/* If we are doing line-oriented IO, set the read filter
|
||||
to be the NL filter. Otherwise, set it to be the read
|
||||
method. */
|
||||
|
||||
if(IS_SPCIO_LINEORIENTED(iomode))
|
||||
channel->read_filter=SPC_Newline_Filter;
|
||||
else
|
||||
channel->read_filter=channel->class_ptr->read;
|
||||
|
||||
channel->cid=(int)channel;
|
||||
channel->identifier = Channel_Identifier;
|
||||
channel->IOMode = iomode;
|
||||
channel->wires[STDIN] = (&dummy_wire);
|
||||
channel->wires[STDOUT]= (&dummy_wire);
|
||||
channel->wires[STDERR]= (&dummy_wire);
|
||||
channel->file_descs[STDIN] = -1;
|
||||
channel->file_descs[STDOUT]= -1;
|
||||
channel->file_descs[STDERR]= -1;
|
||||
channel->wire_list=NULL;
|
||||
channel->logfile=NULL;
|
||||
|
||||
/* Link it into the activation list (at the front for now) */
|
||||
|
||||
channel->next = spc_activation_list;
|
||||
spc_activation_list = channel;
|
||||
|
||||
return(channel);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** This method will get called AFTER the work done in the child methods,
|
||||
** so's we can deallocate all memory associated with this channel
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int close_channel_object (SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *wirelist, *next_wire;
|
||||
int i;
|
||||
SPC_Channel_Ptr trail, ptr;
|
||||
|
||||
/* Remove the channel from the activation list */
|
||||
|
||||
if(spc_activation_list == channel)
|
||||
spc_activation_list = channel->next;
|
||||
else {
|
||||
trail = spc_activation_list;
|
||||
while(trail) {
|
||||
ptr = trail->next;
|
||||
if(ptr == channel) {
|
||||
trail->next = ptr->next;
|
||||
break;
|
||||
}
|
||||
trail=ptr;
|
||||
}
|
||||
if(!trail) {
|
||||
SPC_Error(SPC_Closed_Channel);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deallocate any memory allocated to the subfields */
|
||||
|
||||
if(IS_SPCIO_DEALLOC_ARGV(channel->IOMode))
|
||||
SPC_Free_Envp(channel->argv);
|
||||
SPC_Free_Envp(channel->envp);
|
||||
|
||||
wirelist=channel->wire_list;
|
||||
while(wirelist) {
|
||||
next_wire=wirelist->next;
|
||||
free_wire(wirelist);
|
||||
wirelist=next_wire;
|
||||
}
|
||||
|
||||
for(i=1; i<3; i++)
|
||||
if(channel->linebufs[i])
|
||||
free((char *)channel->linebufs[i]);
|
||||
|
||||
/* Free the queue associated with the channel */
|
||||
|
||||
SPC_Flush_Queued_Data(channel);
|
||||
Xe_release_queue(channel->queued_remote_data);
|
||||
|
||||
/* Deallocate the channel */
|
||||
|
||||
free((char *)channel);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int read_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(connector), /* STDOUT or STDERR */
|
||||
XeString UNUSED_PARM(buffer),
|
||||
int UNUSED_PARM(nbytes))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
/* need to check consistency between connector and READ/WRITE/ERROR here */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int write_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
XeString UNUSED_PARM(buffer),
|
||||
int UNUSED_PARM(nbytes))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
/* check for consistent arguments (channel open for WRITE) */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int reset_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
channel->IOMode &= ~SPCIO_DATA;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int pre_fork_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *wirelist;
|
||||
int flag=0;
|
||||
|
||||
/* Set all wires to be "data ready" */
|
||||
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
|
||||
wirelist->flags |= SPCIO_DATA;
|
||||
flag=1;
|
||||
}
|
||||
|
||||
/* Move to the "Running & (possibly) data ready" state */
|
||||
|
||||
SPC_Change_State(channel, NULL, flag, 1);
|
||||
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int post_fork_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(parentp))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int exec_proc_channel_object (SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
XeString *tmp_argv;
|
||||
int iomode=channel->IOMode;
|
||||
|
||||
/* If there is no argv specified, fix it up to be the convention
|
||||
(argv[0] = file pathname) */
|
||||
|
||||
if (channel->argv == NULL) {
|
||||
tmp_argv=Alloc_Argv(2);
|
||||
if(tmp_argv==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
tmp_argv[0]=SPC_copy_string(channel->path);
|
||||
tmp_argv[1]=NULL;
|
||||
channel->argv = tmp_argv;
|
||||
channel->IOMode |= SPCIO_DEALLOC_ARGV;
|
||||
}
|
||||
|
||||
if(IS_SPCIO_WAIT(channel->IOMode))
|
||||
XeSPCRegisterTerminator(channel, NULL, NULL);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
signal_channel_object (SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(sig))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int channel_object_wait_for_termination(SPC_Channel_Ptr UNUSED_PARM(channel))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
attach_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(pid))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
add_input_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
SbInputHandlerProc UNUSED_PARM(handler),
|
||||
void *UNUSED_PARM(data) )
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
remove_logfile_channel_object(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(IS_SPCIO_USE_LOGFILE(channel->IOMode))
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
1928
cde/lib/DtSvc/DtEncap/spc-proto.c
Normal file
1928
cde/lib/DtSvc/DtEncap/spc-proto.c
Normal file
File diff suppressed because it is too large
Load Diff
203
cde/lib/DtSvc/DtEncap/spc-sm.c
Normal file
203
cde/lib/DtSvc/DtEncap/spc-sm.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* File: spc-sm.c $XConsortium: spc-sm.c /main/4 1996/04/21 19:10:39 drk $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <signal.h>
|
||||
#include <SPC/spcP.h>
|
||||
|
||||
/*
|
||||
**
|
||||
** Definitions for blocking signals
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
static int (* spc_state_table[16]) (SPC_Channel_Ptr channel, int connector)= {
|
||||
|
||||
/* old_state new_state */
|
||||
|
||||
NULL, /* 00 00 */
|
||||
NULL, /* 00 01 */
|
||||
error_fun, /* 00 10 */
|
||||
NULL, /* 00 11 */
|
||||
sigcld_with_reset, /* 01 00 */
|
||||
NULL, /* 01 01 */
|
||||
error_fun, /* 01 10 */
|
||||
error_fun, /* 01 11 */
|
||||
connector_eof_with_reset, /* 10 00 */
|
||||
error_fun, /* 10 01 */
|
||||
NULL, /* 10 10 */
|
||||
error_fun, /* 10 11 */
|
||||
NULL, /* 11 00 */
|
||||
connector_eof, /* 11 01 */
|
||||
NULL, /* 11 10 */
|
||||
NULL /* 11 11 */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Change_State(SPC_Channel_Ptr channel,
|
||||
int connector,
|
||||
int data_line,
|
||||
int process_line)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int iomode=channel->IOMode;
|
||||
int old_state=CHANNEL_STATE(iomode);
|
||||
int new_state, state_index;
|
||||
int (*fun)(SPC_Channel_Ptr, int);
|
||||
int funretval;
|
||||
|
||||
sigset_t newsigmask, oldsigmask;
|
||||
|
||||
sigemptyset(&newsigmask);
|
||||
sigemptyset(&oldsigmask);
|
||||
|
||||
/* Process don't cares */
|
||||
sigaddset(&newsigmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
|
||||
|
||||
if(data_line == -1)
|
||||
data_line=DATA_LINE(old_state);
|
||||
if(process_line == -1)
|
||||
process_line = PROC_LINE(old_state);
|
||||
|
||||
/* create new state */
|
||||
|
||||
new_state=MAKE_STATE(data_line, process_line);
|
||||
|
||||
/* If no state change, return */
|
||||
|
||||
if(new_state == old_state) {
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Lookup & process transition function */
|
||||
|
||||
state_index=MAKE_STATE_INDEX(old_state, new_state);
|
||||
|
||||
fun=spc_state_table[state_index];
|
||||
|
||||
if(fun == error_fun) {
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
channel->IOMode=MAKE_CHANNEL_STATE(iomode, new_state);
|
||||
if(!fun) {
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
funretval=((*fun)(channel, connector));
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
|
||||
return funretval;
|
||||
|
||||
}
|
||||
|
||||
/* error_fun is not ever called. It is just a placeholder for an
|
||||
error condition in the state table */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
error_fun(SPC_Channel_Ptr UNUSED_PARM(channel),
|
||||
int UNUSED_PARM(connector))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**
|
||||
** This routine is called when an EOF is detected on a specific
|
||||
** connector within a channel, but the channel still has a subprocess
|
||||
** associated with it. It will clear the data ready flag on the
|
||||
** indicated wire. After that, it will look at all the wires
|
||||
** associated with the channel and set the channel's data flag to the
|
||||
** inclusive OR of the individual wire's data flags.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
connector_eof(SPC_Channel_Ptr channel,
|
||||
int connector)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *wire=channel->wires[connector];
|
||||
Wire *tmpwire;
|
||||
int channelflag=0;
|
||||
int iomode=channel->IOMode;
|
||||
|
||||
if(!wire)
|
||||
return(FALSE);
|
||||
|
||||
wire->flags &= ~SPCIO_DATA;
|
||||
|
||||
if(IS_SPCIO_STDOUT(iomode)) {
|
||||
tmpwire=channel->wires[STDOUT];
|
||||
channelflag |= IS_SPCIO_DATA(tmpwire->flags);
|
||||
}
|
||||
|
||||
if(IS_SPCIO_STDERR(iomode) && IS_SPCIO_SEPARATE(iomode)) {
|
||||
tmpwire=channel->wires[STDERR];
|
||||
channelflag |= IS_SPCIO_DATA(tmpwire->flags);
|
||||
}
|
||||
|
||||
if(channelflag)
|
||||
channel->IOMode |= SPCIO_DATA;
|
||||
else
|
||||
channel->IOMode &= ~SPCIO_DATA;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** This routine is called when there is no subprocess associated with
|
||||
** the channel, and an EOF is detected on a connector. It will first
|
||||
** call connector_eof on the channel/connector, and if the channel
|
||||
** does not have its data flag set, it will reset the channel.
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
connector_eof_with_reset(SPC_Channel_Ptr channel,
|
||||
int connector)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
connector_eof(channel, connector);
|
||||
if(!IS_DATA(channel))
|
||||
XeSPCReset(channel);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** This routine is called when the child associated with the channel
|
||||
** dies, and there is no data available to be read on the channel.
|
||||
** It will simply reset then channel.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
sigcld_with_reset(SPC_Channel_Ptr channel,
|
||||
int UNUSED_PARM(connector))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
mempf0(channel, reset);
|
||||
return(TRUE);
|
||||
}
|
||||
618
cde/lib/DtSvc/DtEncap/spc-termio.c
Normal file
618
cde/lib/DtSvc/DtEncap/spc-termio.c
Normal file
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
* File: spc-termio.c $TOG: spc-termio.c /main/5 1998/04/03 17:08:32 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1990, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h>
|
||||
#include <bms/stringbuf.h>
|
||||
|
||||
#include <termios.h>
|
||||
#if !defined(linux)
|
||||
#include <sys/termio.h>
|
||||
#endif
|
||||
#include <codelibs/stringx.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define STRTOKX(b,f) strtokx((b), (f))
|
||||
#else
|
||||
#define STRTOKX(b,f) strtokx((char **)(&b), (f))
|
||||
#endif
|
||||
|
||||
/***************************************************************************************
|
||||
|
||||
The routines in this file decode and encode a termios struct back and forth between the
|
||||
actual binary representation of the structure and an ASCII string representation which
|
||||
may be portably sent across the network.
|
||||
|
||||
<version>!<i-flags>!<o-flags>!<c-flags>!<l-flags>!<i-speed>!<o-speed>!<cc-array>
|
||||
|
||||
Where:
|
||||
|
||||
<version> == the termios struct protocal version (currently XPG3)
|
||||
|
||||
<i-flags> == comma separated list of input mode flags as defined in
|
||||
the termios.h header file.
|
||||
|
||||
<o-flags> == comma separated list of output mode flags as defined in
|
||||
the termios.h header file.
|
||||
|
||||
<c-flags> == comma separated list of control mode flags as defined in
|
||||
the termios.h header file. The terminal speed info is
|
||||
not part of this list.
|
||||
|
||||
<i-speed> == The input speed as defined in the termios.h header file.
|
||||
|
||||
<o-speed> == The output speed as defined in the termios.h header file.
|
||||
|
||||
<cc-array> == comma separated list of control control character names and
|
||||
values formatted as (<name>=<value),<name>=<value>...)
|
||||
|
||||
******************************************************************************************/
|
||||
|
||||
#define SPC_TERMIO_VER_FIELD 1 /* Define field indicies for above string */
|
||||
#define SPC_TERMIO_IMODE_FIELD 2
|
||||
#define SPC_TERMIO_OMODE_FIELD 3
|
||||
#define SPC_TERMIO_CMODE_FIELD 4
|
||||
#define SPC_TERMIO_LMODE_FIELD 5
|
||||
#define SPC_TERMIO_ISPEED_FIELD 6
|
||||
#define SPC_TERMIO_OSPEED_FIELD 7
|
||||
#define SPC_TERMIO_CC_FIELD 8
|
||||
#define SPC_TERMIO_LAST_FIELD SPC_TERMIO_CC_FIELD
|
||||
|
||||
#define SPC_TERMIO_SEP "!" /* These three MUST be only 1 char */
|
||||
#define SPC_TCFLAG_SEP ","
|
||||
#define SPC_CC_SEP "="
|
||||
|
||||
#define SPC_CC_FORMAT "%u" /* CC values are printed with this format */
|
||||
|
||||
struct modes_s
|
||||
{
|
||||
XeString name;
|
||||
tcflag_t value;
|
||||
};
|
||||
|
||||
struct baud_s
|
||||
{
|
||||
XeString name;
|
||||
speed_t speed;
|
||||
};
|
||||
|
||||
struct cc_s
|
||||
{
|
||||
XeString name;
|
||||
cc_t value;
|
||||
};
|
||||
|
||||
/* The following lists are the valid componants of a "struct termios" */
|
||||
/* as defined in XPG3. These MUST be kept up to date with the X/Open */
|
||||
/* standard. No platform specific items can exist here as we pass this */
|
||||
/* data to other systems on the network and they be from any vendor. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#define SPC_TERMIO_VERSION "XPG3"
|
||||
|
||||
#define END_OF_LIST "End_Of_List"
|
||||
|
||||
static struct modes_s Input_modes[] = {
|
||||
"BRKINT", BRKINT,
|
||||
"ICRNL", ICRNL,
|
||||
"IGNBRK", IGNBRK,
|
||||
"IGNCR", IGNCR,
|
||||
"IGNPAR", IGNPAR,
|
||||
"INLCR", INLCR,
|
||||
"INPCK", INPCK,
|
||||
"ISTRIP", ISTRIP,
|
||||
"IXOFF", IXOFF,
|
||||
"IXON", IXON,
|
||||
"PARMRK", PARMRK,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
static struct modes_s Output_modes[] = {
|
||||
"OPOST", OPOST,
|
||||
"ONLCR", ONLCR,
|
||||
"OCRNL", OCRNL,
|
||||
"ONOCR", ONOCR,
|
||||
"ONLRET", ONLRET,
|
||||
"OFILL", OFILL,
|
||||
"OFDEL", OFDEL,
|
||||
"NLDLY", NLDLY,
|
||||
"NL0", NL0,
|
||||
"NL1", NL1,
|
||||
"CRDLY", CRDLY,
|
||||
"CR0", CR0,
|
||||
"CR1", CR1,
|
||||
"CR2", CR2,
|
||||
"CR3", CR3,
|
||||
"TABDLY", TABDLY,
|
||||
"TAB0", TAB0,
|
||||
"TAB1", TAB1,
|
||||
"TAB2", TAB2,
|
||||
"TAB3", TAB3,
|
||||
"BSDLY", BSDLY,
|
||||
"BS0", BS0,
|
||||
"BS1", BS1,
|
||||
"VTDLY", VTDLY,
|
||||
"VT0", VT0,
|
||||
"VT1", VT1,
|
||||
"FFDLY", FFDLY,
|
||||
"FF0", FF0,
|
||||
"FF1", FF1,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
|
||||
static struct baud_s Baud_rates[] = {
|
||||
"B0", B0,
|
||||
"B50", B50,
|
||||
"B75", B75,
|
||||
"B110", B110,
|
||||
"B134", B134,
|
||||
"B150", B150,
|
||||
"B200", B200,
|
||||
"B300", B300,
|
||||
"B600", B600,
|
||||
"B1200", B1200,
|
||||
"B1800", B1800,
|
||||
"B2400", B2400,
|
||||
"B4800", B4800,
|
||||
"B9600", B9600,
|
||||
"B19200", B19200,
|
||||
"B38400", B38400,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
|
||||
static struct modes_s Control_modes[] = {
|
||||
"CSIZE", CSIZE,
|
||||
"CS5", CS5,
|
||||
"CS6", CS6,
|
||||
"CS7", CS7,
|
||||
"CS8", CS8,
|
||||
"CSTOPB", CSTOPB,
|
||||
"CREAD", CREAD,
|
||||
"PARENB", PARENB,
|
||||
"PARODD", PARODD,
|
||||
"HUPCL", HUPCL,
|
||||
"CLOCAL", CLOCAL,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
|
||||
static struct modes_s Local_modes[] = {
|
||||
"ECHO", ECHO,
|
||||
"ECHOE", ECHOE,
|
||||
"ECHOK", ECHOK,
|
||||
"ECHONL", ECHONL,
|
||||
"ICANON", ICANON,
|
||||
"IEXTEN", IEXTEN,
|
||||
"ISIG", ISIG,
|
||||
"NOFLSH", NOFLSH,
|
||||
"TOSTOP", TOSTOP,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
|
||||
static struct cc_s CC_Array[] = {
|
||||
"VEOF", VEOF,
|
||||
"VEOL", VEOL,
|
||||
"VERASE", VERASE,
|
||||
"VINTR", VINTR,
|
||||
"VKILL", VKILL,
|
||||
"VMIN", VMIN,
|
||||
"VQUIT", VQUIT,
|
||||
"VSTART", VSTART,
|
||||
"VSTOP", VSTOP,
|
||||
"VSUSP", VSUSP,
|
||||
"VTIME", VTIME,
|
||||
END_OF_LIST, 0
|
||||
};
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static void
|
||||
SPC_Decode_TCflag(tcflag_t flag,
|
||||
struct modes_s modes[],
|
||||
XeStringBuffer buff)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Boolean first_time = TRUE;
|
||||
|
||||
/* Given a binary representation of flag (tcflag_t), convert */
|
||||
/* it into a comma separated list of ASCII flag names. */
|
||||
|
||||
while (strcmp(modes->name, END_OF_LIST) != 0)
|
||||
{
|
||||
if ( (modes->value & flag) == modes->value)
|
||||
{
|
||||
if (first_time)
|
||||
first_time = FALSE;
|
||||
else
|
||||
XeAppendToStringBuffer(buff, SPC_TCFLAG_SEP);
|
||||
|
||||
XeAppendToStringBuffer(buff, modes->name);
|
||||
}
|
||||
modes++;
|
||||
}
|
||||
|
||||
/* We need at least one blank for strtokx to work when */
|
||||
/* we take this string apart on the other side. */
|
||||
/* --------------------------------------------------- */
|
||||
if (first_time)
|
||||
XeAppendToStringBuffer(buff, (XeString)" ");
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static tcflag_t
|
||||
SPC_Encode_TCflag(XeString buff,
|
||||
struct modes_s modes[])
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Given a comma separated list of flag names, convert the list */
|
||||
/* into a "tcflag_t" (binary) representation of that list. */
|
||||
|
||||
XeString item;
|
||||
tcflag_t flag = (tcflag_t)0;
|
||||
struct modes_s *orig_modes = modes;
|
||||
|
||||
if (!*buff)
|
||||
return flag;
|
||||
|
||||
while (item = (XeString)STRTOKX(buff, SPC_TCFLAG_SEP))
|
||||
{
|
||||
Boolean found = FALSE;
|
||||
|
||||
modes = orig_modes;
|
||||
while (strcmp(modes->name, END_OF_LIST) != 0)
|
||||
{
|
||||
if (strcmp(modes->name, item) == 0)
|
||||
{
|
||||
flag |= modes->value;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
modes++;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
SPC_Error(SPC_Bad_Termios_Mode, item);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static void
|
||||
SPC_Decode_Speed(speed_t speed,
|
||||
struct baud_s bauds[],
|
||||
XeStringBuffer buff)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Given a binary "speed_t" speed specification, convert it into */
|
||||
/* a single ASCII string. */
|
||||
|
||||
while (strcmp(bauds->name, END_OF_LIST) != 0)
|
||||
{
|
||||
if (bauds->speed == speed)
|
||||
{
|
||||
XeAppendToStringBuffer(buff, bauds->name);
|
||||
return;
|
||||
}
|
||||
bauds++;
|
||||
}
|
||||
|
||||
/* We need at least one blank for strtokx to work when */
|
||||
/* we take this string apart on the other side. */
|
||||
/* --------------------------------------------------- */
|
||||
XeAppendToStringBuffer(buff, (XeString)" ");
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static speed_t
|
||||
SPC_Encode_Speed(XeString buff,
|
||||
struct baud_s bauds[])
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
#define DEFAULT_SPEED B9600
|
||||
|
||||
/* Given a single ASCII name of a termio speed item, convert it into */
|
||||
/* a binary (speed_t) representation. */
|
||||
|
||||
if (!*buff)
|
||||
return DEFAULT_SPEED;
|
||||
|
||||
while (strcmp(bauds->name, END_OF_LIST) != 0)
|
||||
{
|
||||
if (strcmp(bauds->name, buff) == 0)
|
||||
return bauds->speed;
|
||||
bauds++;
|
||||
}
|
||||
|
||||
SPC_Error(SPC_Bad_Termios_Speed, buff);
|
||||
return DEFAULT_SPEED;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static void
|
||||
SPC_Decode_CC(cc_t ccs[],
|
||||
struct cc_s cc_array[],
|
||||
XeStringBuffer buff)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Boolean first_time = TRUE;
|
||||
|
||||
/* Given an array of cc_s from a termios struct (binary */
|
||||
/* representation), convert it into a comma sepearted list of */
|
||||
/* CC names and values of the form <name>=<value> */
|
||||
|
||||
while (strcmp(cc_array->name, END_OF_LIST) != 0)
|
||||
{
|
||||
int index = ccs[cc_array->value];
|
||||
if ( index != 0 )
|
||||
{
|
||||
XeChar num[30];
|
||||
|
||||
if (first_time)
|
||||
first_time = FALSE;
|
||||
else
|
||||
XeAppendToStringBuffer(buff, SPC_TCFLAG_SEP);
|
||||
|
||||
XeAppendToStringBuffer(buff, cc_array->name);
|
||||
XeAppendToStringBuffer(buff, SPC_CC_SEP);
|
||||
sprintf(num, SPC_CC_FORMAT, index);
|
||||
XeAppendToStringBuffer(buff, num);
|
||||
}
|
||||
cc_array++;
|
||||
}
|
||||
|
||||
/* We need at least one blank for strtokx to work when */
|
||||
/* we take this string apart on the other side. */
|
||||
/* --------------------------------------------------- */
|
||||
if (first_time)
|
||||
XeAppendToStringBuffer(buff, (XeString)" ");
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
static void
|
||||
SPC_Encode_CC(XeString buff,
|
||||
cc_t ccs[],
|
||||
struct cc_s cc_array[])
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* we should have gotten a string that looks like this: */
|
||||
/* */
|
||||
/* <V-Name>=<value>,<V-Name>=<value>... */
|
||||
/* */
|
||||
/* For example: VEOF=4,VKILL=8 */
|
||||
/* */
|
||||
/* Parse this array and store the values in the "ccs" array passed in */
|
||||
/* to us. It is assumed that the <V-name> strings are all defined in */
|
||||
/* the "cc_array" list passed to us. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
XeString cc_name, cc_value;
|
||||
int i;
|
||||
unsigned int a_cc;
|
||||
struct cc_s *orig_cc_array = cc_array;
|
||||
|
||||
for(i=0; i<NCCS; i++)
|
||||
ccs[i] = 0;
|
||||
|
||||
if (!*buff) return;
|
||||
|
||||
while (cc_name = (XeString)STRTOKX(buff, SPC_TCFLAG_SEP))
|
||||
{
|
||||
Boolean found = FALSE;
|
||||
|
||||
cc_value = strchr(cc_name, SPC_CC_SEP[0]); /* Go find the "=" */
|
||||
if (!cc_value)
|
||||
{
|
||||
SPC_Error(SPC_Bad_Termios_CC, cc_name);
|
||||
continue;
|
||||
}
|
||||
*cc_value++ = XeChar_NULL; /* Replace "=" with null */
|
||||
|
||||
|
||||
/* Look for "V-Name" in table ... */
|
||||
/* ------------------------------ */
|
||||
cc_array = orig_cc_array;
|
||||
while (strcmp(cc_array->name, END_OF_LIST) != 0)
|
||||
{
|
||||
if (strcmp(cc_array->name, cc_name) == 0)
|
||||
{
|
||||
if (sscanf(cc_value, SPC_CC_FORMAT, &a_cc) != 1)
|
||||
{
|
||||
*(cc_value-1) = SPC_CC_SEP[0];
|
||||
SPC_Error(SPC_Bad_Termios_CC, cc_name);
|
||||
}
|
||||
else
|
||||
ccs[cc_array->value] = a_cc;
|
||||
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
cc_array++;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
*(cc_value-1) = SPC_CC_SEP[0];
|
||||
SPC_Error(SPC_Bad_Termios_CC, cc_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString SPC_Decode_Termios(struct termios *tio)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Given a termios struct, return an ascii string representation of */
|
||||
/* it as defined at the front of this file. */
|
||||
|
||||
#define RESULT_BUFF_SIZE 32
|
||||
|
||||
XeString all;
|
||||
speed_t speed;
|
||||
XeStringBuffer result = XeMakeStringBuffer(RESULT_BUFF_SIZE);
|
||||
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_VERSION);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
SPC_Decode_TCflag(tio->c_iflag, Input_modes, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
SPC_Decode_TCflag(tio->c_oflag, Output_modes, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
SPC_Decode_TCflag(tio->c_cflag, Control_modes, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
SPC_Decode_TCflag(tio->c_lflag, Local_modes, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
speed = cfgetispeed(tio);
|
||||
SPC_Decode_Speed(speed, Baud_rates, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
speed = cfgetospeed(tio);
|
||||
SPC_Decode_Speed(speed, Baud_rates, result);
|
||||
XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
|
||||
|
||||
SPC_Decode_CC(tio->c_cc, CC_Array, result);
|
||||
|
||||
all = strdup(result->buffer);
|
||||
|
||||
XeFree(result->buffer);
|
||||
XeFree(result);
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Encode_Termios(XeString buff, struct termios *tio)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Decodes the ascii representation of the termios struct. The format */
|
||||
/* of the string is defined at the front of this file. */
|
||||
|
||||
XeString item;
|
||||
XeString protocol_version;
|
||||
int item_cnt = 0;
|
||||
speed_t speed;
|
||||
|
||||
while (item = (XeString)STRTOKX(buff, SPC_TERMIO_SEP))
|
||||
{
|
||||
/* We can possibly have an all blank field. Walk past them */
|
||||
/* because the routines we will be calling don't expect any */
|
||||
/* blanks in the string (but they do check for empty stings).*/
|
||||
while (*item == (XeChar)' ') item++;
|
||||
|
||||
switch(++item_cnt)
|
||||
{
|
||||
case SPC_TERMIO_VER_FIELD :
|
||||
protocol_version = item;
|
||||
/* Check this some day ??? */
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_IMODE_FIELD :
|
||||
tio->c_iflag = SPC_Encode_TCflag(item, Input_modes);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_OMODE_FIELD :
|
||||
tio->c_oflag = SPC_Encode_TCflag(item, Output_modes);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_CMODE_FIELD :
|
||||
tio->c_cflag = SPC_Encode_TCflag(item, Control_modes);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_LMODE_FIELD :
|
||||
tio->c_lflag = SPC_Encode_TCflag(item, Local_modes);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_ISPEED_FIELD :
|
||||
speed = SPC_Encode_Speed(item, Baud_rates);
|
||||
cfsetispeed(tio, speed);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_OSPEED_FIELD :
|
||||
speed = SPC_Encode_Speed(item, Baud_rates);
|
||||
cfsetospeed(tio, speed);
|
||||
break;
|
||||
|
||||
case SPC_TERMIO_CC_FIELD :
|
||||
SPC_Encode_CC(item, tio->c_cc, CC_Array);
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
|
||||
} /* while */
|
||||
|
||||
if (item_cnt != SPC_TERMIO_LAST_FIELD)
|
||||
SPC_Error(SPC_Bad_Termios_Proto,
|
||||
(XeString) ((item_cnt < SPC_TERMIO_LAST_FIELD) ? "Too Few" : "Too Many"));
|
||||
|
||||
}
|
||||
|
||||
#ifdef TESTING
|
||||
/*----------------------------------------------------------------------+*/
|
||||
main()
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString s, s1, s2;
|
||||
int i;
|
||||
struct termios tio, tio2;
|
||||
speed_t speed;
|
||||
|
||||
tio.c_iflag = BRKINT | IGNPAR | ICRNL | IXON;
|
||||
tio.c_oflag = OPOST | ONLCR;
|
||||
tio.c_cflag = CS7 | CREAD | CLOCAL;
|
||||
tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
|
||||
|
||||
tio.c_reserved = 0;
|
||||
for(i=0; i<NCCS; i++)
|
||||
tio.c_cc[i] = 0;
|
||||
tio.c_cc[VERASE] = 101;
|
||||
tio.c_cc[VEOF] = 102;
|
||||
tio.c_cc[VSTOP] = 103;
|
||||
|
||||
|
||||
tio2.c_iflag = 0;
|
||||
tio2.c_oflag = 0;
|
||||
tio2.c_cflag = 0;
|
||||
tio2.c_lflag = 0;
|
||||
|
||||
tio2.c_reserved = 0;
|
||||
for(i=0; i<NCCS; i++)
|
||||
tio2.c_cc[i] = 0;
|
||||
|
||||
cfsetispeed(&tio, B9600);
|
||||
cfsetospeed(&tio, B1200);
|
||||
|
||||
s1 = strdup(s = SPC_Decode_Termios(&tio));
|
||||
printf("Decoded string=\n<%s>\n\n", s);
|
||||
|
||||
|
||||
SPC_Encode_Termios(s, &tio2);
|
||||
s2 = strdup(s = SPC_Decode_Termios(&tio2));
|
||||
printf("String after Encoding/decoding=\n<%s>\n\n", s2);
|
||||
|
||||
if (strcmp(s1, s2) == 0)
|
||||
printf("...Identical ...\n");
|
||||
else
|
||||
printf("...Mismatch ...\n");
|
||||
|
||||
}
|
||||
#endif /* TESTING */
|
||||
289
cde/lib/DtSvc/DtEncap/spc-util.c
Normal file
289
cde/lib/DtSvc/DtEncap/spc-util.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* File: spc-util.c $XConsortium: spc-util.c /main/5 1996/06/21 17:33:16 ageorge $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <SPC/spcP.h>
|
||||
#include <bms/MemoryMgr.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* The application's SPC activation list */
|
||||
SPC_Channel_Ptr spc_activation_list = NULL;
|
||||
|
||||
/* Allocate us up a wire */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
Wire *get_new_wire(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
Wire *tmp_wire;
|
||||
|
||||
tmp_wire=(Wire *)XeMalloc(sizeof(Wire));
|
||||
memset(tmp_wire, NULL, sizeof(Wire));
|
||||
|
||||
tmp_wire->master_name=(XeString)XeMalloc(PTY_NAMLEN);
|
||||
memset(tmp_wire->master_name, NULL, PTY_NAMLEN);
|
||||
tmp_wire->slave_name =(XeString)XeMalloc(PTY_NAMLEN);
|
||||
memset(tmp_wire->slave_name, NULL, PTY_NAMLEN);
|
||||
tmp_wire->fd[0] = tmp_wire->fd[1] = (-1);
|
||||
tmp_wire->read_toolkit_id = (-1);
|
||||
tmp_wire->except_toolkit_id = (-1);
|
||||
return(tmp_wire);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void free_wire(Wire *wire)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
free(wire->master_name);
|
||||
free(wire->slave_name);
|
||||
free((char *)wire);
|
||||
}
|
||||
|
||||
/*
|
||||
* Channel object access
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr SPC_Find_PID(int pid)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Attempt to return a channel which currently handles process number PID */
|
||||
SPC_Channel_Ptr spc;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
for (spc = spc_activation_list; spc != NULL; spc = spc->next) {
|
||||
if (spc->pid == pid) break;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
return spc; /* NULL when not found */
|
||||
}
|
||||
|
||||
/*
|
||||
* Miscellaneous
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
spc_close(int fd)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Close a file descriptor which was referenced through an SPC structure */
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
|
||||
return(fd);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
spc_dup2(int from, int to)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int retval;
|
||||
|
||||
/* Dup file descriptors. If a null descriptor, then use /dev/null */
|
||||
static int devnull = NULL;
|
||||
|
||||
if (from == to)
|
||||
return(TRUE);
|
||||
|
||||
if (from == -1) {
|
||||
_DtSvcProcessLock();
|
||||
if (!devnull)
|
||||
devnull = open("/dev/null", 0);
|
||||
/* Use /dev/null when no source file descriptor */
|
||||
from = devnull;
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/* Now do the dup2 */
|
||||
retval=dup2(from, to);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_fd_to_connector(SPC_Channel_Ptr channel,
|
||||
int fd)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(Stdout(channel) == fd)
|
||||
return(STDOUT);
|
||||
if(Stdin(channel) == fd)
|
||||
return(STDIN);
|
||||
if(Stderr(channel) == fd)
|
||||
return(STDERR);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
XeString *Alloc_Argv(int n)
|
||||
{
|
||||
/* Allocate an array to hold argv list */
|
||||
XeString *av;
|
||||
|
||||
av = (XeString *)XeMalloc((n + 1) * sizeof(XeString));
|
||||
|
||||
/* Zero the space so we don't have to worry about trailing NULL */
|
||||
memset((XeString) av, NULL, (n + 1) * sizeof(XeString));
|
||||
|
||||
return(av);
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Toolkit integration stuff, without direct calls to the toolkit.
|
||||
***
|
||||
*/
|
||||
|
||||
int break_on_termination=FALSE;
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void SPC_Conditional_Packet_Handler(void * UNUSED_PARM(client_data),
|
||||
int * source,
|
||||
SPCInputId * UNUSED_PARM(id))
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Channel_Ptr channel;
|
||||
|
||||
channel = XeSPCHandleTerminator(*source);
|
||||
|
||||
/* Okay, blast out of our wait */
|
||||
_DtSvcProcessLock();
|
||||
if( (channel==SPC_ERROR || !IS_ACTIVE(channel)) &&
|
||||
break_on_termination)
|
||||
SPC_XtBreak();
|
||||
_DtSvcProcessUnlock();
|
||||
/* return(TRUE); */
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int sprintf_len (XeString s, XeString format, ...)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
if (s) *s = XeChar_NULL;
|
||||
vsprintf(s, format, ap);
|
||||
return(strlen(s));
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** _path_search is a generalized function used for parsing the PATH
|
||||
*** environment variable wrt a passed filename. It will run down the
|
||||
*** passed path variable looking for ':'. When it finds one (or hits
|
||||
*** the end of the string), it will concatenate the substring with
|
||||
*** filename, passing the result to the passed path_search_predicate.
|
||||
*** If this predicate returns true, the function will return with a
|
||||
*** true value. If all elements of the path are processed with no
|
||||
*** true result from the predicate, the function will return false.
|
||||
***
|
||||
*** A few special cases:
|
||||
*** - If the filename begins with '/' (an absolute path), the
|
||||
*** funciton will return the value of the predicate on the
|
||||
*** filename (e.g. PATH processing will not be done).
|
||||
*** - a NULL value of any path component will be interpreted as the
|
||||
*** current directory ('.').
|
||||
*** - a NULL value for the path parameter means use the PATH
|
||||
*** environment variable.
|
||||
*** - a NULL value for filename will return FALSE
|
||||
***
|
||||
*/
|
||||
|
||||
/*
|
||||
***
|
||||
*** MAXPATHLEN is defined in sbstdinc.h
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
Boolean _path_search (XeString path, XeString filename, path_search_predicate p)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
XeString path_rest, next_colon=NULL;
|
||||
XeChar buffer[MAXPATHLEN+1];
|
||||
XeChar path_component[MAXPATHLEN+1];
|
||||
int path_component_len;
|
||||
int filename_len;
|
||||
int component_seperator=(int)':'; /* this is here because strchr takes an in */
|
||||
|
||||
if(!filename)
|
||||
return(FALSE);
|
||||
|
||||
if(*filename == '/')
|
||||
return((*p)(filename, NULL, filename));
|
||||
|
||||
filename_len = strlen(filename);
|
||||
if(!path)
|
||||
path=getenv("PATH");
|
||||
|
||||
for( (path_rest=path ,
|
||||
next_colon=strchr(path_rest, component_seperator));
|
||||
path_rest && *path_rest;
|
||||
next_colon=strchr(path_rest, component_seperator)) {
|
||||
|
||||
/*
|
||||
** Copy path component into buffer
|
||||
*/
|
||||
|
||||
if(next_colon) { /* found colon */
|
||||
path_component_len = next_colon-path_rest;
|
||||
strncpy(buffer, path_rest, path_component_len);
|
||||
buffer[path_component_len]=NULL;
|
||||
path_rest=next_colon+1;
|
||||
if(!*path_rest)
|
||||
/* We've seen a ':' at the end of the string. Make path_rest be "."
|
||||
next go-round */
|
||||
path_rest=".";
|
||||
} else { /* no colon */
|
||||
path_component_len = strlen(path_rest);
|
||||
strcpy(buffer, path_rest);
|
||||
path_rest=NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** if path component is NULL, use default ('.');
|
||||
*/
|
||||
|
||||
if(!buffer[0]) {
|
||||
buffer[0] = '.';
|
||||
buffer[1] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Concatenate filename
|
||||
*/
|
||||
|
||||
if((path_component_len + filename_len + 1) < MAXPATHLEN) {
|
||||
path_component[0]=0;
|
||||
strcat(path_component, buffer);
|
||||
strcat(buffer, "/");
|
||||
strcat(buffer, filename);
|
||||
|
||||
/*
|
||||
** Check this file. If the predicate returns true, we return true.
|
||||
*/
|
||||
|
||||
if((*p)(buffer, path_component, filename))
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** We've checked all components. Return False.
|
||||
*/
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
242
cde/lib/DtSvc/DtEncap/spc-xt.c
Normal file
242
cde/lib/DtSvc/DtEncap/spc-xt.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* File: spc-xt.c $TOG: spc-xt.c /main/6 1998/03/16 14:41:02 mgreess $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define __need_fd_set
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <time.h>
|
||||
#include <SPC/spcP.h>
|
||||
/* #include <bms/SbEvent.h> */ /* This file now included by spcP.h */
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* Externals */
|
||||
|
||||
extern int break_on_termination;
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
/* First, declarations */
|
||||
|
||||
typedef struct {
|
||||
SbInputId read_id;
|
||||
SbInputId except_id;
|
||||
} SPC_Callback_Struct;
|
||||
|
||||
static SPC_Callback_Struct **SPC_Fd_Mapping = NULL;
|
||||
|
||||
#define SPC_LOOKUP_FD_MAPPING(fd) SPC_Fd_Mapping[(fd)]
|
||||
|
||||
static Boolean spc_xe_termination_flag;
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
static int SPC_AddInput(int source,
|
||||
SPC_Callback_Condition condition,
|
||||
SbInputId id)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Callback_Struct *structptr = NULL;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (SPC_Fd_Mapping == NULL) {
|
||||
SPC_Fd_Mapping = (SPC_Callback_Struct **)
|
||||
XeMalloc (FD_SETSIZE * sizeof (SPC_Callback_Struct *));
|
||||
memset(SPC_Fd_Mapping, NULL, FD_SETSIZE * sizeof(SPC_Callback_Struct *));
|
||||
}
|
||||
structptr=SPC_LOOKUP_FD_MAPPING(source);
|
||||
|
||||
if(!structptr) {
|
||||
structptr=(SPC_Callback_Struct *) XeMalloc(sizeof(SPC_Callback_Struct));
|
||||
SPC_LOOKUP_FD_MAPPING(source)=structptr;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
switch (condition) {
|
||||
|
||||
case SPC_Input:
|
||||
case SPC_Terminator:
|
||||
case SPC_Client:
|
||||
structptr->read_id = id;
|
||||
break;
|
||||
|
||||
case SPC_Exception:
|
||||
structptr->except_id = id;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(source);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
static SbInputId SPC_RemoveInput(int source,
|
||||
SPC_Callback_Condition condition)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Callback_Struct *structptr = NULL;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (SPC_Fd_Mapping == NULL) {
|
||||
SPC_Fd_Mapping = (SPC_Callback_Struct **)
|
||||
XeMalloc (FD_SETSIZE * sizeof (SPC_Callback_Struct *));
|
||||
memset(SPC_Fd_Mapping, NULL, FD_SETSIZE * sizeof(SPC_Callback_Struct *));
|
||||
}
|
||||
structptr=SPC_LOOKUP_FD_MAPPING(source);
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
switch(condition) {
|
||||
|
||||
case SPC_Input:
|
||||
case SPC_Terminator:
|
||||
case SPC_Client:
|
||||
return structptr->read_id;
|
||||
|
||||
case SPC_Exception:
|
||||
return structptr->except_id;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
static SPC_Select(void )
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
break_on_termination=TRUE;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
spc_xe_termination_flag= FALSE;
|
||||
|
||||
/* Use a function pointer so we don't have explict dependancy */
|
||||
/* on libXe.a */
|
||||
/* ---------------------------------------------------------- */
|
||||
if (SbMainLoopUntil_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbMainLoopUntil = NULL\n");
|
||||
else
|
||||
(*SbMainLoopUntil_hookfn)(&spc_xe_termination_flag);
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
break_on_termination=FALSE;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
int SPC_Wait_For_Termination(SPC_Channel_Ptr channel)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
int result;
|
||||
|
||||
call_parent_method(channel, wait_for_termination, (channel), result);
|
||||
|
||||
if(result==SPC_ERROR) return(SPC_ERROR);
|
||||
|
||||
do {
|
||||
|
||||
if(SPC_Select() == SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
} while(IS_ACTIVE(channel));
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
void SPC_XtBreak(void)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
_DtSvcProcessLock();
|
||||
if(!spc_xe_termination_flag) {
|
||||
spc_xe_termination_flag = TRUE;
|
||||
if (SbBreakMainLoop_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbBreakMainLoop = NULL\n");
|
||||
else
|
||||
(*SbBreakMainLoop_hookfn)();
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
void SPC_XtAddInput(SPC_Channel_Ptr channel,
|
||||
int *id_addr,
|
||||
int fd,
|
||||
spc_handler_func_type handler,
|
||||
SPC_Callback_Condition condition)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
SbInputId id;
|
||||
|
||||
switch(condition) {
|
||||
|
||||
case SPC_Input:
|
||||
case SPC_Terminator:
|
||||
case SPC_Client:
|
||||
/* fprintf(stderr, "SPC add input/terminator for %d\n", fd); */
|
||||
if (SbAddInput_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbAddInput = NULL\n");
|
||||
else
|
||||
id = (*SbAddInput_hookfn)(fd, handler, channel);
|
||||
break;
|
||||
|
||||
case SPC_Exception:
|
||||
/* fprintf(stderr, "SPC add exception for %d\n", fd); */
|
||||
if (SbAddException_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbAddException = NULL\n");
|
||||
else
|
||||
id = (*SbAddException_hookfn)(fd, handler, channel);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
*id_addr=SPC_AddInput(fd, condition, id);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
void SPC_XtRemoveInput(int *id_addr,
|
||||
SPC_Callback_Condition condition)
|
||||
/*-----------------------------------------------------------------------+*/
|
||||
{
|
||||
if((*id_addr) != -1) {
|
||||
|
||||
switch(condition) {
|
||||
|
||||
case SPC_Input:
|
||||
case SPC_Terminator:
|
||||
case SPC_Client:
|
||||
/* fprintf(stderr, "SPC remove input/terminator\n"); */
|
||||
if (SbRemoveInput_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbRemoveInput = NULL\n");
|
||||
else
|
||||
(*SbRemoveInput_hookfn)(SPC_RemoveInput(*id_addr, condition));
|
||||
break;
|
||||
|
||||
case SPC_Exception:
|
||||
/* fprintf(stderr, "SPC remove exception"); */
|
||||
if (SbRemoveException_hookfn == NULL)
|
||||
(void) fprintf (stderr, "Error: SbRemoveException = NULL\n");
|
||||
else
|
||||
(*SbRemoveException_hookfn)(SPC_RemoveInput(*id_addr, condition));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
*id_addr=(-1);
|
||||
}
|
||||
}
|
||||
860
cde/lib/DtSvc/DtEncap/spc.c
Normal file
860
cde/lib/DtSvc/DtEncap/spc.c
Normal file
@@ -0,0 +1,860 @@
|
||||
/*
|
||||
* File: spc.c $XConsortium: spc.c /main/6 1996/06/21 17:33:08 ageorge $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
#include <signal.h>
|
||||
#include <SPC/spcP.h>
|
||||
#include <SPC/spc-proto.h>
|
||||
#include <bms/spc.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
/* spc.c */
|
||||
int SPC_Process_Single_Prot_Request (protocol_request_ptr req, SPC_Channel_Ptr channel);
|
||||
|
||||
|
||||
/* This is the SPC error number variable */
|
||||
/* extern int XeSPCErrorNumber; */
|
||||
|
||||
/* Externals */
|
||||
|
||||
extern int SPC_Initialized;
|
||||
extern SPC_Channel_Ptr spc_activation_list;
|
||||
extern SPC_Connection_Ptr connection_list;
|
||||
extern SPC_Connection_Ptr read_terminator;
|
||||
extern XeString official_hostname;
|
||||
|
||||
int max_fds = 0; /* Set up below. */
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void
|
||||
spc_init_fds(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
_DtSvcProcessLock();
|
||||
if (!max_fds)
|
||||
# ifdef __bsd
|
||||
max_fds = getdtablesize();
|
||||
# else
|
||||
max_fds = (int)sysconf(_SC_OPEN_MAX);
|
||||
# endif
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Sub-Process Control access routines. These are just functional
|
||||
*** interfaces to the underlying methods.
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr XeSPCOpen(XeString hostname,
|
||||
int iomode)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Attempt to open an SPC channel - return TRUE if we succeed */
|
||||
SPC_Channel_Ptr channel;
|
||||
|
||||
/* Check for initialization */
|
||||
_DtSvcProcessLock();
|
||||
if(!SPC_Initialized)
|
||||
if(SPC_Initialize() == SPC_ERROR) {
|
||||
_DtSvcProcessUnlock();
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
|
||||
/* The user specified iomode needs to be processed before we can use it.
|
||||
Process the puppy. */
|
||||
|
||||
iomode=SPC_Transform_Iomode(iomode);
|
||||
if(iomode==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* Get a new channel object */
|
||||
|
||||
channel=SPC_Initialize_Channel(hostname, iomode);
|
||||
|
||||
/* check that everything was okay */
|
||||
|
||||
if(channel==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* call the open method for it */
|
||||
|
||||
return((SPC_Channel_Ptr) mempf2(channel, open, iomode, hostname));
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCClose(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(IS_ACTIVE(channel))
|
||||
XeSPCKillProcess(channel, FALSE);
|
||||
|
||||
if(IS_SPCIO_DELAY_CLOSE(channel->IOMode)) {
|
||||
channel->IOMode |= SPCIO_DO_CLOSE;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
channel->IOMode &= ~SPCIO_DO_CLOSE;
|
||||
|
||||
return(mempf0(channel, close));
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCReset(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(IS_ACTIVE(channel))
|
||||
XeSPCKillProcess(channel, FALSE);
|
||||
|
||||
channel->IOMode &= ~SPCIO_ACTIVE;
|
||||
|
||||
if(mempf0(channel, reset)==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCRead(SPC_Channel_Ptr channel,
|
||||
int connector, /* STDOUT or STDERR */
|
||||
XeString buffer,
|
||||
int length)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
int n;
|
||||
|
||||
/* check for legal arguments */
|
||||
|
||||
if (channel==SPC_ERROR || !buffer ||
|
||||
!(connector==STDOUT || connector==STDERR) ||
|
||||
(length < 0)) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* check state of the channel */
|
||||
if (!IS_DATA(channel) || !IS_SPCIO_DATA(channel->wires[connector]->flags))
|
||||
return(0);
|
||||
|
||||
/* call the read filter */
|
||||
|
||||
do {
|
||||
n=(*channel->read_filter)(channel, connector, buffer, length);
|
||||
} while(n == (EXCEPT_FLAG));
|
||||
|
||||
/* Check for an error */
|
||||
|
||||
if (n == SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCWrite(SPC_Channel_Ptr channel,
|
||||
XeString buffer,
|
||||
int length)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int n;
|
||||
|
||||
/* check for legal arguments */
|
||||
|
||||
if (channel==SPC_ERROR || !buffer || (length<0)) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* check the state of the channel */
|
||||
|
||||
if(!IS_ACTIVE(channel)) {
|
||||
SPC_Error(SPC_Inactive_Channel);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* call the write method */
|
||||
|
||||
n=mempf2(channel, write, buffer, length);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCActive(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if (channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* Is the passed channel active? */
|
||||
return (IS_ACTIVE(channel));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCData(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(IS_DATA(channel));
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCExecuteProcess(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(IS_ACTIVE(channel) || IS_DATA(channel)) {
|
||||
SPC_Error(SPC_Active_Channel);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if((retval=mempf0(channel, exec_proc))==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if (IS_SPCIO_WAIT(channel->IOMode)) {
|
||||
/* Wait for sub-process to finish */
|
||||
SPC_Wait_For_Termination(channel);
|
||||
}
|
||||
|
||||
return(retval);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCSignalProcess(SPC_Channel_Ptr channel,
|
||||
int sig)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if ((channel==SPC_ERROR) ||
|
||||
(channel->pid <= 0) ||
|
||||
(sig < 0)
|
||||
#ifdef NOT_IN_XPG3_YET
|
||||
|| (sig>=NSIG) /* Not a good idea for interoperability anyway */
|
||||
#endif
|
||||
) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* This routine does not check to see if the channel is active. */
|
||||
|
||||
return(mempf1(channel, signal, sig));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCAddInput(SPC_Channel_Ptr channel,
|
||||
SbInputHandlerProc handler,
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void * client_data)
|
||||
{
|
||||
if(!channel) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(!handler && !channel->Input_Handler)
|
||||
return(TRUE);
|
||||
|
||||
if(handler) {
|
||||
channel->Input_Handler = handler;
|
||||
channel->client_data = client_data;
|
||||
}
|
||||
|
||||
return(mempf2(channel, add_input, handler, client_data));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCRegisterTerminator(SPC_Channel_Ptr channel,
|
||||
SPC_TerminateHandlerType terminator,
|
||||
void * client_data)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Connection_Ptr conn;
|
||||
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* Okay. If we have a pty channel, we have to check that we
|
||||
have an input handler. I don't like doing this here, but ther
|
||||
are no methods for this routine, so it has to be done. */
|
||||
|
||||
if(IS_SPCIO_PTY(channel->IOMode) && !channel->Input_Handler) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
channel->IOMode |= SPCIO_SYNC_TERMINATOR;
|
||||
if(terminator) {
|
||||
channel->Terminate_Handler = terminator;
|
||||
channel->Terminate_Data = client_data;
|
||||
}
|
||||
|
||||
conn=SPC_Channel_Terminator_Connection(channel);
|
||||
if(conn->termination_id == -1)
|
||||
SPC_XtAddInput(channel, &conn->termination_id, conn->sid,
|
||||
SPC_Conditional_Packet_Handler, SPC_Terminator);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCAttach(SPC_Channel_Ptr channel,
|
||||
int pid)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
|
||||
{
|
||||
if(channel==SPC_ERROR || pid<=0) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(mempf1(channel, attach, pid));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCDetach(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(channel == SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
channel->pid = 0;
|
||||
channel->IOMode &= ~SPCIO_ACTIVE;
|
||||
|
||||
return XeSPCReset(channel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
***
|
||||
*** "Composite" functions -- Those which are defined in terms of the
|
||||
*** above primitives. One assumption is that the above primitives check
|
||||
*** their arguments, so the composite functions need only check any
|
||||
*** additional arguments.
|
||||
***
|
||||
*/
|
||||
|
||||
/*
|
||||
**
|
||||
** Start with subprocess creation routines
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCSpawn(XeString pathname,
|
||||
XeString context_dir,
|
||||
XeString *argv,
|
||||
XeString *envp,
|
||||
SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* Assign the command arguments to this channel and attempt to Execute */
|
||||
|
||||
if(channel->envp) {
|
||||
SPC_Free_Envp(channel->envp);
|
||||
channel->envp=NULL;
|
||||
}
|
||||
if(channel->argv && IS_SPCIO_DEALLOC_ARGV(channel->IOMode)) {
|
||||
SPC_Free_Envp(channel->argv);
|
||||
channel->IOMode &= ~SPCIO_DEALLOC_ARGV;
|
||||
channel->argv=NULL;
|
||||
}
|
||||
|
||||
channel->context_dir=context_dir;
|
||||
channel->argv = argv;
|
||||
channel->path = pathname;
|
||||
|
||||
channel->envp=SPC_Create_Default_Envp(channel->envp);
|
||||
channel->envp=SPC_Merge_Envp(channel->envp, envp);
|
||||
channel->envp=SPC_Fixup_Environment(channel->envp, channel);
|
||||
|
||||
if(IS_SPCIO_SYSTEM(channel->IOMode))
|
||||
if(SPC_MakeSystemCommand(channel)==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
/* Execute the process (XeSPCExecuteProcess will check arguments */
|
||||
|
||||
return(XeSPCExecuteProcess(channel));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr XeSPCOpenAndSpawn(XeString hostname,
|
||||
int iomode,
|
||||
XeString pathname,
|
||||
XeString context_dir,
|
||||
XeString *argv,
|
||||
XeString *envp)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* This simply wraps together the two steps: Open and Spawn */
|
||||
SPC_Channel_Ptr channel;
|
||||
|
||||
channel = XeSPCOpen(hostname, iomode);
|
||||
if(channel==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
|
||||
if (XeSPCSpawn(pathname, context_dir, argv, envp, channel)!=SPC_ERROR)
|
||||
return(channel);
|
||||
|
||||
/* Close the channel and return SPC_ERROR */
|
||||
XeSPCClose(channel);
|
||||
return(SPC_ERROR);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Signalling routines
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void
|
||||
XeSPCKillProcesses(int wait)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Attempt to KILL all the sub-process that we know of */
|
||||
SPC_Channel_Ptr spc;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
for (spc = spc_activation_list; spc != (SPC_Channel_Ptr) NULL; spc = spc->next)
|
||||
XeSPCKillProcess(spc, wait);
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCKillProcess(SPC_Channel_Ptr channel,
|
||||
int wait)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Attempt to KILL the sub-process (should we nullify the pid?) */
|
||||
int result;
|
||||
|
||||
if(!channel)
|
||||
return(FALSE);
|
||||
|
||||
if(IS_ACTIVE(channel)) {
|
||||
result = XeSPCSignalProcess(channel, SIGKILL);
|
||||
if(result==SPC_ERROR)
|
||||
return(SPC_ERROR);
|
||||
if (wait || IS_SPCIO_SYNC_TERM(channel->IOMode))
|
||||
SPC_Wait_For_Termination(channel);
|
||||
return result;
|
||||
} else
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCInterruptProcess(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Attempt to INTerrupt the sub-process */
|
||||
|
||||
return(XeSPCSignalProcess(channel, SIGINT));
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Process information routines.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeString XeSPCGetDevice(SPC_Channel_Ptr channel,
|
||||
int connector,
|
||||
int side)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(!channel) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/* Return the device name which corresponds to the side of a channel */
|
||||
if (connector>=STDIN && connector<=STDERR) {
|
||||
if (side == MASTER_SIDE)
|
||||
return(channel->wires[connector]->master_name);
|
||||
if (side == SLAVE_SIDE)
|
||||
return(channel->wires[connector]->slave_name);
|
||||
}
|
||||
|
||||
/* For no channel or incorrect side, return SPC_ERROR */
|
||||
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCGetProcessStatus(SPC_Channel_Ptr channel,
|
||||
int *type,
|
||||
int *cause)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
/* Fill in the type and cause of a process termination */
|
||||
int high, low;
|
||||
|
||||
if(!channel || !type || !cause) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
low = channel->status & WAIT_STATUS_MASK;
|
||||
high = (channel->status >> 8) & WAIT_STATUS_MASK;
|
||||
|
||||
*cause = high;
|
||||
|
||||
switch (low) {
|
||||
|
||||
case IS_WAIT_STATUS_STOPPED:
|
||||
*type = SPC_PROCESS_STOPPED;
|
||||
break;
|
||||
|
||||
case IS_WAIT_STATUS_EXITED:
|
||||
*type = SPC_PROCESS_EXITED;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!*cause) {
|
||||
*cause = low;
|
||||
*type = SPC_PROCESS_SIGNALLED;
|
||||
}
|
||||
break;
|
||||
|
||||
} /* End switch on status */
|
||||
|
||||
/* When a process is still active return FALSE */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCGetPID(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(!channel) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
return (channel->pid);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int XeSPCGetLogfile(SPC_Channel_Ptr channel,
|
||||
XeString *host,
|
||||
XeString *file)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(!channel || !IS_SPCIO_USE_LOGFILE(channel->IOMode)) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
*file=channel->logfile;
|
||||
_DtSvcProcessLock();
|
||||
if(IS_REMOTE(channel))
|
||||
*host=channel->connection->hostname;
|
||||
else
|
||||
*host= official_hostname;
|
||||
_DtSvcProcessUnlock();
|
||||
return(TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
int XeSPCRemoveLogfile(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
if(!channel) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(mempf0(channel, remove_logfile));
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Synchronous termination
|
||||
**
|
||||
*/
|
||||
|
||||
#define SINGLE_PROT_DATA(req, channel, connector) \
|
||||
if(!channel->queued_remote_data) \
|
||||
channel->queued_remote_data=Xe_make_queue(FALSE); \
|
||||
Xe_push_queue(channel->queued_remote_data, req); \
|
||||
if(channel->Input_Handler) { \
|
||||
SPC_Input_Handler(channel, connector); \
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** SPC_Process_Single_Prot_Request will return TRUE if it is okay
|
||||
** for the caller to free the protocol request.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Process_Single_Prot_Request(protocol_request_ptr req, SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
switch(req->request_type) {
|
||||
|
||||
case APPLICATION_DIED:
|
||||
|
||||
READ_APPLICATION_DIED(req->dataptr, channel->status);
|
||||
SPC_Channel_Terminated(channel);
|
||||
return(TRUE);
|
||||
|
||||
case APPLICATION_STDOUT:
|
||||
SINGLE_PROT_DATA(req, channel, STDOUT);
|
||||
return(FALSE);
|
||||
|
||||
case APPLICATION_STDERR:
|
||||
SINGLE_PROT_DATA(req, channel, STDERR);
|
||||
return(FALSE);
|
||||
|
||||
default:
|
||||
SPC_Error(SPC_Internal_Error);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPC_Channel_Ptr XeSPCHandleTerminator(int fd)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Connection_Ptr connection;
|
||||
SPC_Channel_Ptr channel;
|
||||
protocol_request_ptr prot;
|
||||
XeQueue connection_queue;
|
||||
|
||||
if(!(connection=SPC_Lookup_Connection_Fd(fd))) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
if(!(prot=SPC_Read_Protocol(connection))) {
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
connection_queue=connection->queued_remote_data;
|
||||
Xe_push_queue(connection_queue, prot);
|
||||
|
||||
while(prot=(protocol_request_ptr)Xe_pop_queue(connection_queue)) {
|
||||
|
||||
channel=prot->channel;
|
||||
|
||||
if(channel) {
|
||||
channel->IOMode |= SPCIO_DELAY_CLOSE;
|
||||
|
||||
if(SPC_Process_Single_Prot_Request(prot, channel))
|
||||
SPC_Free_Protocol_Ptr(prot);
|
||||
|
||||
channel->IOMode &= ~SPCIO_DELAY_CLOSE;
|
||||
if(IS_SPCIO_DO_CLOSE(channel->IOMode)) {
|
||||
XeSPCClose(channel);
|
||||
channel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(channel);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Use this call to get the file descriptor for
|
||||
** Synchronous termination.
|
||||
**
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSPCGetChannelSyncFd(SPC_Channel_Ptr channel)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
SPC_Connection_Ptr conn;
|
||||
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
conn=SPC_Channel_Terminator_Connection(channel);
|
||||
return(conn->sid);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Error Handling routines.
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
SPCError *XeSPCLookupError(int errnum)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
if(errnum<SPC_Min_Error || errnum > SPC_Max_Error) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(SPC_Lookup_Error(errnum));
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Temporarily shutdown input handlers
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void XeSPCShutdownCallbacks(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Channel_Ptr channel;
|
||||
SPC_Connection_Ptr conn;
|
||||
Wire *wirelist;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
channel=spc_activation_list;
|
||||
conn=connection_list;
|
||||
|
||||
while(channel) {
|
||||
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
|
||||
if(wirelist->read_toolkit_id != -1)
|
||||
SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
|
||||
if(wirelist->except_toolkit_id != -1)
|
||||
SPC_XtRemoveInput(&wirelist->except_toolkit_id, SPC_Exception);
|
||||
}
|
||||
channel=channel->next;
|
||||
}
|
||||
|
||||
while(conn) {
|
||||
if(conn->termination_id != -1)
|
||||
SPC_XtRemoveInput(&conn->termination_id, SPC_Terminator);
|
||||
conn=conn->next;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
void XeSPCRestartCallbacks(void)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
SPC_Channel_Ptr channel;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
channel=spc_activation_list;
|
||||
|
||||
while(channel) {
|
||||
if(channel->Input_Handler)
|
||||
XeSPCAddInput(channel, (SbInputHandlerProc)NULL, NULL);
|
||||
if(channel->Terminate_Handler)
|
||||
XeSPCRegisterTerminator(channel, NULL, NULL);
|
||||
channel=channel->next;
|
||||
}
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
/*
|
||||
***
|
||||
*** Okay, now for a non-SPC routine. This one is dealing with setpgrp,
|
||||
*** but it is here because it uses internal SPC routines.
|
||||
***
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------+*/
|
||||
XeSetpgrp(int read_current_termio)
|
||||
/*----------------------------------------------------------------------+*/
|
||||
{
|
||||
|
||||
return(SPC_Setpgrp(read_current_termio));
|
||||
}
|
||||
|
||||
int XeSPCSendEOF(SPC_Channel_Ptr channel)
|
||||
{
|
||||
if(channel==SPC_ERROR) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(mempf0(channel, send_eof));
|
||||
}
|
||||
|
||||
int XeSPCSetTermio(SPC_Channel_Ptr channel, int connection, int side,
|
||||
struct termios *termio)
|
||||
{
|
||||
if(channel==SPC_ERROR || termio == NULL) {
|
||||
SPC_Error(SPC_Bad_Argument);
|
||||
return(SPC_ERROR);
|
||||
}
|
||||
|
||||
return(mempf3(channel, set_termio, connection, side, termio));
|
||||
}
|
||||
|
||||
133
cde/lib/DtSvc/DtEncap/stringbuf.c
Normal file
133
cde/lib/DtSvc/DtEncap/stringbuf.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* File: stringbuf.c $XConsortium: stringbuf.c /main/3 1995/10/26 15:41:59 rswiston $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <bms/bms.h>
|
||||
#include <bms/stringbuf.h> /* public declarations */
|
||||
#include <bms/MemoryMgr.h> /* Xe_make_struct ... */
|
||||
|
||||
/* Forwards */
|
||||
static int ExpandStringBuffer (XeStringBuffer buffer);
|
||||
|
||||
#ifndef DEBUG
|
||||
# define DEBUG 0
|
||||
#endif
|
||||
|
||||
#define EXPANSION_FACTOR 4
|
||||
|
||||
/**
|
||||
BUFFER_MIN_SIZE was chosen to be 16 so
|
||||
BUFSIZE % EXPANSION_FACTOR > 0
|
||||
and
|
||||
(BUFSIZE + (BUFSIZE % EXPANSION_FACTOR)) % EXPANSION_FACTOR
|
||||
> (BUFSIZE % EXPANSION_FACTOR)
|
||||
**/
|
||||
|
||||
#define BUFFER_MIN_SIZE 16
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
static int
|
||||
ExpandStringBuffer(XeStringBuffer buffer)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
int new_size = buffer->size + buffer->increment;
|
||||
XeString new_string = Xe_make_ntype(new_size, XeChar);
|
||||
|
||||
# if DEBUG >= 3
|
||||
sprintf(debug_string, "expanding string buffer. current size is: %d", buffer->size);
|
||||
print_debug_info(3, debug_string);
|
||||
# endif
|
||||
|
||||
memcpy(new_string, buffer->buffer, buffer->last_char + 1);
|
||||
XeFree(buffer->buffer);
|
||||
buffer->size = new_size;
|
||||
buffer->buffer = new_string;
|
||||
buffer->increment += (buffer->increment % EXPANSION_FACTOR);
|
||||
# if DEBUG >= 3
|
||||
sprintf(debug_string, "new size is: %d", buffer->size);
|
||||
print_debug_info(4, debug_string);
|
||||
# endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
int
|
||||
XeAppendToStringBuffer(XeStringBuffer buffer, XeString string)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
int size = buffer->size;
|
||||
XeString buffer_position; /* so operations are pointer based */
|
||||
int i;
|
||||
|
||||
# if DEBUG >= 5
|
||||
sprintf(debug_string, "appending: \"%s\" to: \"%s\"", string, buffer->buffer);
|
||||
print_debug_info(5, debug_string);
|
||||
# endif
|
||||
|
||||
if (!(string && string[0])) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
buffer_position = &(buffer->buffer[buffer->last_char]);
|
||||
for (i = buffer->last_char; *string ; i++) {
|
||||
if (i == size) {
|
||||
buffer->last_char = i - 1;
|
||||
if (-1 == ExpandStringBuffer(buffer)) return(-1);
|
||||
size = buffer->size;
|
||||
buffer_position = &(buffer->buffer[i]);
|
||||
}
|
||||
*buffer_position++ = *string++;
|
||||
}
|
||||
if (i == size) {
|
||||
buffer->last_char = i - 1;
|
||||
if (-1 == ExpandStringBuffer(buffer)) return(-1);
|
||||
}
|
||||
buffer->buffer[i] = (XeChar) NULL;
|
||||
buffer->last_char = i;
|
||||
# if DEBUG >= 5
|
||||
sprintf(debug_string, "new string is: \"%s\"", buffer->buffer);
|
||||
print_debug_info(6, debug_string);
|
||||
# endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
void
|
||||
XeClearStringBuffer(XeStringBuffer buffer)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeString string = buffer->buffer;
|
||||
string[0] = (XeChar) NULL;
|
||||
buffer->last_char = 0;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------+*/
|
||||
XeStringBuffer
|
||||
XeMakeStringBuffer(int increment_size)
|
||||
/*------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeStringBuffer new_buffer;
|
||||
increment_size = (increment_size > BUFFER_MIN_SIZE)
|
||||
? increment_size
|
||||
: BUFFER_MIN_SIZE;
|
||||
|
||||
new_buffer = Xe_make_struct(_XeStringBuffer);
|
||||
new_buffer->buffer = Xe_make_ntype(increment_size, XeChar);
|
||||
new_buffer->increment = increment_size;
|
||||
new_buffer->size = increment_size;
|
||||
XeClearStringBuffer(new_buffer);
|
||||
return(new_buffer);
|
||||
}
|
||||
245
cde/lib/DtSvc/DtEncap/usersig.c
Normal file
245
cde/lib/DtSvc/DtEncap/usersig.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* File: usersig.c $XConsortium: usersig.c /main/4 1996/06/21 17:33:04 ageorge $
|
||||
* Language: C
|
||||
*
|
||||
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
|
||||
*
|
||||
* (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. *
|
||||
*/
|
||||
|
||||
#define __need_all_signals
|
||||
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <bms/bms.h>
|
||||
#include <bms/Symbolic.h>
|
||||
#include <bms/usersig.h>
|
||||
#include "DtSvcLock.h"
|
||||
|
||||
static XeSymTable Xe_sig_table = (XeSymTable) NULL;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
static void Xe_addsig(XeString name, int value)
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
{
|
||||
XeSymbol sym = Xe_intern(Xe_sig_table, name);
|
||||
sym->value = (void *)value;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
static void Xe_init_sig_table(void)
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
{
|
||||
# define SIG_HASH_SIZE 32
|
||||
|
||||
_DtSvcProcessLock();
|
||||
Xe_sig_table = Xe_new_symtab(SIG_HASH_SIZE);
|
||||
|
||||
Xe_addsig((XeString)"SIGABRT", SIGABRT); /* Add the XOPEN XPG3 signals */
|
||||
Xe_addsig((XeString)"SIGALRM", SIGALRM);
|
||||
Xe_addsig((XeString)"SIGFPE", SIGFPE);
|
||||
Xe_addsig((XeString)"SIGHUP", SIGHUP);
|
||||
Xe_addsig((XeString)"SIGILL", SIGILL);
|
||||
Xe_addsig((XeString)"SIGINT", SIGINT);
|
||||
Xe_addsig((XeString)"SIGKILL", SIGKILL);
|
||||
Xe_addsig((XeString)"SIGPIPE", SIGPIPE);
|
||||
Xe_addsig((XeString)"SIGQUIT", SIGQUIT);
|
||||
Xe_addsig((XeString)"SIGSEGV", SIGSEGV);
|
||||
Xe_addsig((XeString)"SIGTERM", SIGTERM);
|
||||
Xe_addsig((XeString)"SIGUSR1", SIGUSR1);
|
||||
Xe_addsig((XeString)"SIGUSR2", SIGUSR2);
|
||||
Xe_addsig((XeString)"SIGCHLD", SIGCHLD);
|
||||
Xe_addsig((XeString)"SIGCONT", SIGCONT);
|
||||
Xe_addsig((XeString)"SIGSTOP", SIGSTOP);
|
||||
Xe_addsig((XeString)"SIGTSTP", SIGTSTP);
|
||||
Xe_addsig((XeString)"SIGTTIN", SIGTTIN);
|
||||
Xe_addsig((XeString)"SIGTTOU", SIGTTOU);
|
||||
|
||||
/* 0 is a valid XPG3 signal, but it doesn't have a name. */
|
||||
|
||||
Xe_addsig((XeString)"ZERO", 0);
|
||||
|
||||
/* Now add signals that may or may not be around on a given platform */
|
||||
|
||||
# ifdef SIGIO
|
||||
Xe_addsig((XeString)"SIGIO", SIGIO); /* hpux sun apollo */
|
||||
# else
|
||||
# ifdef SIGPOLL
|
||||
Xe_addsig((XeString)"SIGIO", SIGPOLL); /* hpux sun apollo */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef SIGPOLL
|
||||
Xe_addsig((XeString)"SIGPOLL", SIGPOLL); /* hpux sun apollo */
|
||||
# else
|
||||
# ifdef SIGIO
|
||||
Xe_addsig((XeString)"SIGPOLL", SIGIO); /* hpux sun apollo */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef SIGEMT
|
||||
Xe_addsig((XeString)"SIGEMT", SIGEMT); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGBUS
|
||||
Xe_addsig((XeString)"SIGBUS", SIGBUS); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGIOT
|
||||
Xe_addsig((XeString)"SIGIOT", SIGIOT); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGURG
|
||||
Xe_addsig((XeString)"SIGURG", SIGURG); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGSYS
|
||||
Xe_addsig((XeString)"SIGSYS", SIGSYS); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGTRAP
|
||||
Xe_addsig((XeString)"SIGTRAP", SIGTRAP); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGPROF
|
||||
Xe_addsig((XeString)"SIGPROF", SIGPROF); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGCLD
|
||||
Xe_addsig((XeString)"SIGCLD", SIGCLD); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGVTALRM
|
||||
Xe_addsig((XeString)"SIGVTALRM", SIGVTALRM); /* hpux sun apollo */
|
||||
# endif
|
||||
|
||||
# ifdef SIGWINCH
|
||||
Xe_addsig((XeString)"SIGWINCH", SIGWINCH);
|
||||
# endif
|
||||
_DtSvcProcessUnlock();
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
int XeNameToSignal(XeString name)
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
|
||||
/* Return SIG_NOT_IN_TABLE if signal name is not in hash table */
|
||||
|
||||
{
|
||||
XeSymbol sym;
|
||||
|
||||
_DtSvcProcessLock();
|
||||
if (!Xe_sig_table) Xe_init_sig_table();
|
||||
|
||||
sym = Xe_lookup(Xe_sig_table, name);
|
||||
|
||||
_DtSvcProcessUnlock();
|
||||
return (sym) ? (int) sym->value : XE_SIG_NOT_IN_TABLE;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
XeString XeSignalToName(int sig)
|
||||
/*-------------------------------------------------------------------------+*/
|
||||
{
|
||||
switch (sig)
|
||||
{
|
||||
/* These are XOPEN XPG3 signals */
|
||||
/* ---------------------------- */
|
||||
case SIGABRT: return (XeString)"SIGABRT"; /* "SIGIOT" is an alias */
|
||||
case SIGALRM: return (XeString)"SIGALRM";
|
||||
case SIGFPE: return (XeString)"SIGFPE";
|
||||
case SIGHUP: return (XeString)"SIGHUP";
|
||||
case SIGILL: return (XeString)"SIGILL";
|
||||
case SIGINT: return (XeString)"SIGINT";
|
||||
case SIGKILL: return (XeString)"SIGKILL";
|
||||
case SIGPIPE: return (XeString)"SIGPIPE";
|
||||
case SIGQUIT: return (XeString)"SIGQUIT";
|
||||
case SIGSEGV: return (XeString)"SIGSEGV";
|
||||
case SIGTERM: return (XeString)"SIGTERM";
|
||||
case SIGUSR1: return (XeString)"SIGUSR1";
|
||||
case SIGUSR2: return (XeString)"SIGUSR2";
|
||||
case SIGCHLD: return (XeString)"SIGCHLD"; /* "SIGCLD" is an alias */
|
||||
case SIGCONT: return (XeString)"SIGCONT";
|
||||
case SIGSTOP: return (XeString)"SIGSTOP";
|
||||
case SIGTSTP: return (XeString)"SIGTSTP";
|
||||
case SIGTTIN: return (XeString)"SIGTTIN";
|
||||
case SIGTTOU: return (XeString)"SIGTTOU";
|
||||
|
||||
/* 0 is a valid signal under XPG3, but it doesn't have a signal name */
|
||||
|
||||
case 0: return (XeString)"ZERO";
|
||||
|
||||
|
||||
/* NOTE: we have ifdef's for cases that are duplicated by other values */
|
||||
/* included but contain no code. This is so when you compare this */
|
||||
/* code to the stuff in Xe_init_sig_table() above, you see a one */
|
||||
/* to one correspondance. */
|
||||
|
||||
# ifdef SIGIO /* hpux sun apollo */
|
||||
/* (SIGPOLL, SIGTINT are aliases) */
|
||||
case SIGIO: return (XeString)"SIGIO";
|
||||
# endif
|
||||
|
||||
# ifdef SIGPOLL /* hpux sun apollo */
|
||||
/* ----> Duplicated by SIGIO above
|
||||
case SIGPOLL: return (XeString)"SIGPOLL";
|
||||
*/
|
||||
# endif
|
||||
|
||||
|
||||
# ifdef SIGEMT /* hpux sun apollo */
|
||||
case SIGEMT: return (XeString)"SIGEMT";
|
||||
# endif
|
||||
|
||||
# ifdef SIGBUS /* hpux sun apollo */
|
||||
case SIGBUS: return (XeString)"SIGBUS";
|
||||
# endif
|
||||
|
||||
# ifdef SIGIOT /* hpux sun apollo */
|
||||
/* ----> Duplicated by SIGABRT above
|
||||
|
||||
case SIGIOT: return (XeString)"SIGIOT";
|
||||
*/
|
||||
# endif
|
||||
|
||||
# ifdef SIGURG /* hpux sun apollo */
|
||||
case SIGURG: return (XeString)"SIGURG";
|
||||
# endif
|
||||
|
||||
# ifdef SIGSYS /* hpux sun apollo */
|
||||
case SIGSYS: return (XeString)"SIGSYS";
|
||||
# endif
|
||||
|
||||
# ifdef SIGTRAP /* hpux sun apollo */
|
||||
case SIGTRAP: return (XeString)"SIGTRAP";
|
||||
# endif
|
||||
|
||||
# ifdef SIGPROF /* hpux sun apollo */
|
||||
case SIGPROF: return (XeString)"SIGPROF";
|
||||
# endif
|
||||
|
||||
# ifdef SIGCLD /* hpux sun apollo */
|
||||
/* ----> Duplicated by SIGCHLD above
|
||||
case SIGCLD: return (XeString)"SIGCLD";
|
||||
*/
|
||||
# endif
|
||||
|
||||
# ifdef SIGVTALRM /* hpux sun apollo */
|
||||
case SIGVTALRM: return (XeString)"SIGVTALRM";
|
||||
# endif
|
||||
|
||||
# ifdef SIGWINCH /* sun apollo */
|
||||
case SIGWINCH: return (XeString)"SIGWINCH";
|
||||
# endif
|
||||
|
||||
|
||||
default: return XeString_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user