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

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

View File

@@ -0,0 +1,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()

View 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);
}

View 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);
}

View 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);
}
}

View 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;

View 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;
}

View 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);
}

View 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;
}

View 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);
}

View 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];
}

View 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

File diff suppressed because it is too large Load Diff

View 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);
}

View 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);
}

View 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 ;

View 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);
}

View 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);
}

View 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);
}

View 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);
}

View 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);
}

File diff suppressed because it is too large Load Diff

View 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);
}

View 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 */

View 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);
}

View 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
View 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));
}

View 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);
}

View 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;
}
}