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,53 @@
XCOMM $XConsortium: Imakefile /main/6 1996/08/20 14:48:43 drk $
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
#define CplusplusSource YES
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
#include <Threads.tmpl>
#ifndef DtSvcDefines
# define DtSvcDefines -DXK_MISCELLANY -DMULTIBYTE
#endif
DEFINES = DtSvcDefines
INCLUDES = -I. -I../include
#if defined(RsArchitecture)
CXXEXTRA_DEFINES = -qlanglvl=compat
#endif
SRCS = buf.C filegen.C mbschr.C \
pathcollapse.C shellscan.C strend.C \
strhash.C stringio.C strtokx.C \
strwcmp.C privbuf.C strcase.C
/* WARNING!!!!
* Any .o's added to this list need to be added to DTCODELIBS_OBJS3
* and SHARED_DTCODELIBS_OBJS3 in the DtSvc Imakefile.
*/
OBJS = buf.o filegen.o mbschr.o \
pathcollapse.o shellscan.o strend.o \
strhash.o stringio.o strtokx.o \
strwcmp.o privbuf.o strcase.o
#include <Library.tmpl>
SubdirLibraryRule($(OBJS))
DependTarget()

View File

@@ -0,0 +1,105 @@
/*
* File: buf.C $TOG: buf.C /main/5 1998/01/21 18:01:14 mgreess $
*
* (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 <stdio.h>
#include <stdlib.h>
#include <codelibs/nl_hack.h>
#include "buf.h"
void
_SHXbuf::start_token()
{
vec[vec.size()] = (char *)buf.size();
is_pattern = FALSE;
_new_token = FALSE;
}
void
_SHXbuf::quote(Quote q)
{
_quote ^= q;
if (_new_token)
start_token();
}
void
_SHXbuf::append(int const ch, char flag)
{
flag |= _quote;
if (ch == '\0' && !_new_token)
_new_token = TRUE;
else if (_new_token)
start_token();
if (flag == NOQUOTE)
if (ch == '*' || ch == '?' || ch == '[')
if (glob)
is_pattern = TRUE;
else
flag |= SINGLEQUOTE;
if (ch <= 0xFF)
{
// 8-bit char
flags[buf.size()] = flag;
buf[buf.size()] = (unsigned char)ch;
}
else
{
// multibyte char
long sz = buf.size();
for (int i=0; i<MB_CUR_MAX; i++) flags[sz+i] = flag;
buf.reset(sz + MB_CUR_MAX);
char *cp = &buf.elt(sz);
WCHAR(ch, cp);
}
// expand token into filename(s) if appropriate
if (ch == '\0' && (is_pattern || completion))
if (!(flag & EXPANDQUOTE))
filegen();
}
void
_SHXbuf::append(char const *cp, char flag)
{
wchar_t __nlh_char[1];
do
append((int)CHARAT(cp), flag);
while (CHARADV(cp) != '\0');
}
void
_SHXbuf::reset(boolean g, boolean comp)
{
glob = (boolean) !!g;
completion = (boolean ) !!comp;
is_pattern = FALSE;
_new_token = TRUE;
_quote = NOQUOTE;
buf.reset(0);
flags.reset(0);
vec.reset(0);
}
// Convert the subscripts that are stored in vec[] into
// char pointers. The only legal operation on _SHXbuf after
// calling vector is to call reset.
char **
_SHXbuf::vector()
{
for (int i = 0; i < vec.size(); i++)
vec[i] = &buf[long(vec[i])];
vec[i] = NULL;
return vec.getarr();
}

View File

@@ -0,0 +1,49 @@
/*
* File: buf.h $XConsortium: buf.h /main/3 1995/10/26 16:07:20 rswiston $
*
* (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 <codelibs/boolean.h>
#define __PRIVATE_
#include <codelibs/privbuf.h>
#define NOQUOTE 0
#define SINGLEQUOTE 1
#define DOUBLEQUOTE 2
#define EXPANDQUOTE 4
typedef unsigned char Quote;
class _SHXcomponents;
class _SHXbuf
{
boolean glob;
boolean completion;
boolean is_pattern;
Quote _quote;
boolean _new_token;
privbuf_charbuf buf;
privbuf_charbuf flags;
privbuf_strvec vec;
void start_token();
void filegen();
void expand(_SHXcomponents&, char* const, char*, int);
public:
_SHXbuf() {reset(TRUE, FALSE);}
void reset(boolean glob, boolean completion);
void append(int const ch, char flag = 0);
void append(char const *cp, char flag = 0);
int ntokens() {return vec.size();}
boolean new_token() {return _new_token;}
Quote quote() {return _quote;}
void quote(Quote);
char **vector();
};
#ifndef NULL
#define NULL 0
#endif

View File

@@ -0,0 +1,281 @@
/*
* File: filegen.C $TOG: filegen.C /main/7 1999/10/14 15:05:25 mgreess $
*
* (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 <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#define X_INCLUDE_DIRENT_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <codelibs/stringx.h>
#include <codelibs/nl_hack.h>
#include "buf.h"
#include "DtSvcLock.h"
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
#ifdef XTHREADS
extern "C" {
extern void XtProcessLock(void);
extern void XtProcessUnlock(void);
}
#endif
struct _SHXcomponent
{
boolean is_pattern;
long offset; // subscript in path buffer
char *ptr; // pointer into path buffer
};
declare_array(_SHXcomponents, _SHXcomponent, 4)
// recursive routine to expand the wildcard path represented in stack into
// all possible expansions. The expansions are appended to _SHXbuf::vec.
// filebuf is a scratch buffer passed in by the caller and is used to build
// intermediate paths. end is a pointer to the position in filebuf where
// the calling routine left off.
void
_SHXbuf::expand(_SHXcomponents &stack,
char *const filebuf, char *end, int compnum)
{
*end = '\0';
if (compnum == stack.size())
return;
_SHXcomponent &comp = stack[compnum];
// double-slash?
if (comp.ptr[0] == '\0')
{
if (compnum + 1 == stack.size())
append(filebuf, EXPANDQUOTE);
else
{
*end++ = '/';
expand(stack, filebuf, end, compnum + 1);
}
return;
}
// performance optimization: if this path component
// doesn't contain a wildcard, avoid doing an opendir()
if (!comp.is_pattern)
{
strcpy(end, comp.ptr);
if (compnum + 1 == stack.size())
{
// last component, just see if the path really points to something
if (access(filebuf, F_OK) != -1)
append(filebuf, EXPANDQUOTE);
}
else
{
// intermediate directory just append this component and keep going
char *end2 = strend(end);
*end2++ = '/';
expand(stack, filebuf, end2, compnum + 1);
}
return;
}
// We have a wildcard component, open and scan its parent directory
// and look for matches.
DIR *dir = opendir(filebuf[0] == '\0' ? "." : filebuf);
if (dir == NULL)
return;
_Xreaddirparams dir_buf;
struct dirent *ent;
memset((char*) &dir_buf, 0, sizeof(_Xreaddirparams));
while ((ent = _XReaddir(dir, dir_buf)) != NULL)
{
// deleted file?
if (ent->d_ino == 0 || ent->d_name[0] == '\0')
continue;
// right name?
if (comp.is_pattern)
{
wchar_t __nlh_char[1];
// Must have explicit match for leading '.'
if (CHARAT(ent->d_name) == '.' && CHARAT(comp.ptr) != '.')
continue;
if (strwcmp(comp.ptr, ent->d_name) != 0)
continue;
}
else if (strcmp(comp.ptr, ent->d_name) != 0)
continue;
strcpy(end, ent->d_name);
if (compnum + 1 == stack.size())
append(filebuf, EXPANDQUOTE);
else
{
char *end2 = end + strlen (ent->d_name);
*end2++ = '/';
expand(stack, filebuf, end2, compnum + 1);
}
}
closedir(dir);
}
//extern "C" { void qsort(void *, unsigned, int, ...); };
static char *bufptr;
static int
//compar(int &v1, int &v2)
compar(const void *v1, const void *v2)
{
int result;
_DtSvcProcessLock();
result = strcmp(&bufptr[*(int*)v1], &bufptr[*(int*)v2]);
_DtSvcProcessUnlock();
return (result);
}
void
_SHXbuf::filegen()
{
privbuf_charbuf path;
_SHXcomponents stack;
long vecstart = vec.size() - 1;
if (vecstart < 0)
return;
long bufstart = long(vec[vecstart]);
// Parse the file path, breaking it up into individual components.
// Each component is marked as being either a wildcard component
// or not. The wildcard components will have a '\' placed before
// any quoted wildcard characters. The non-wildcard components
// will be left unchanged.
int bufpos = (int) bufstart;
while (bufpos < buf.size())
{
_SHXcomponent & comp = stack[stack.size()];
comp.is_pattern = FALSE;
comp.offset = path.size();
comp.ptr = NULL;
int startpos = bufpos;
int ch;
do
{
ch = buf[bufpos];
switch (ch)
{
case '/':
ch = '\0';
break;
case '*':
case '?':
case '[':
if (flags[bufpos] == NOQUOTE)
comp.is_pattern = TRUE;
else
path[path.size()] = '\\';
break;
}
path[path.size()] = ch;
bufpos++;
} while (ch != '\0');
// Add a '*' to the end of the last component if needed
// for completion.
if (bufpos >= buf.size()) // last component?
if (bufpos > bufstart + 1) // non-null string?
if (completion && !is_pattern)
{
path[path.size() - 1] = '*';
path[path.size()] = '\0';
comp.is_pattern = TRUE;
break;
}
// If it wasn't a pattern, remove all of the '\' characters
// that were added.
if (!comp.is_pattern)
{
int len = bufpos - startpos - 1;
strncpy(&path[comp.offset], &buf[startpos], len);
path[comp.offset + len] = '\0';
}
}
// Fill in the character pointer values for all of the components.
// We couldn't do this in the first pass because path is a
// dynamic array.
char *pathbuf = path.getarr();
for (int i = 0; i < stack.size(); i++)
stack[i].ptr = &pathbuf[stack[i].offset];
// Remove the token that we just copied from the return vector
// so that we can replace it with its expansion.
vec.reset(vecstart);
char filebuf[MAXPATHLEN];
expand(stack, filebuf, filebuf, 0);
if (vec.size() == vecstart) // no matches?
{
vec[vecstart] = (char *)bufstart; // restore orig. token
return;
}
// alphabetize the expansion to make it look pretty like ksh does.
_DtSvcProcessLock();
bufptr = buf.getarr();
qsort(&vec[vecstart], (unsigned int)(vec.size() - vecstart),
sizeof (char *), compar);
// Find the longest match if we are doing completion:
if (completion)
{
// compare all entries to a copy of the first entry
strcpy(filebuf, &bufptr[long(vec[0])]);
for (long i = 1; i < vec.size(); i++)
{
register char *ref = filebuf;
register char *ptr = &bufptr[long(vec[i])];
while (*ref == *ptr && *ref != '\0' && *ptr != '\0')
ref++, ptr++;
*ref = '\0'; // shorten the reference copy
}
// Now store the best match as the first token. We will
// have to shift the expansion vector down by one to
// make room.
for (i = vec.size(); i > 0; --i)
{
register char *val = vec[i - 1];
vec[i] = val;
}
vec[0] = (char *)buf.size();
append(filebuf, EXPANDQUOTE);
vec.reset(vec.size() - 1); // adjust for the append
}
_DtSvcProcessUnlock();
}
implement_array(_SHXcomponents, _SHXcomponent, 4)

View File

@@ -0,0 +1,36 @@
/*
* $XConsortium: mbschr.C /main/5 1996/06/21 17:36:36 ageorge $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <codelibs/mbstring.h>
#include <codelibs/nl_hack.h>
#ifdef __cplusplus
extern "C"
#endif
#if defined(__cplusplus) || defined(__STDC__)
char *
_mb_schr(const char *str, wchar_t ch)
#else
char *
_mb_schr(str, ch)
register unsigned char *str;
register wchar_t ch;
#endif
{
wchar_t __nlh_char[1];
for (; *str != '\0'; ADVANCE(str))
if (CHARAT(str) == ch)
return (char *)str;
return (char *)0;
}

View File

@@ -0,0 +1,162 @@
/*
* $XConsortium: pathcollapse.C /main/5 1996/06/21 17:36:32 ageorge $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#ifdef DOMAIN_ALLOW_MALLOC_OVERRIDE
#include "/usr/include/apollo/shlib.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/param.h>
#include <codelibs/nl_hack.h>
#include <codelibs/pathutils.h>
#define SEP(P) (CHARAT(P) == '\0' || CHARAT(P) == '/')
#define DOT(P) (CHARAT(P) == '.' && SEP((P) + 1))
#define DOTDOT(P) (CHARAT(P) == '.' && DOT((P) + 1))
#ifdef __cplusplus
extern "C"
#endif
char *
pathcollapse(const char *src, char *dst, boolean show_dir)
{
int ch;
const char *srcp;
char *dstp, *sep;
char *components[MAXPATHLEN / 2 + 1];
char **comp = components;
int length = src == NULL ? 0 : strlen(src);
int dir_comp; /* TRUE if last component was . or .. */
#ifdef apollo
int double_slash = 0;
#endif
wchar_t __nlh_char[1];
if (length == 0 || length > MAXPATHLEN)
{
errno = EINVAL;
return NULL;
}
if (dst == NULL)
if ((dst = (char *)malloc(length + 1)) == NULL)
return NULL;
#ifdef apollo
/*
* On apollo, a leading double-slash must be preserved, so we
* copy the first slash and hide it from the rest of the code.
*/
if (CHARAT(src) == '/' && CHARAT(src + 1) == '/')
{
*dst++ = '/';
src++;
double_slash = 1;
}
#endif
srcp = src;
dstp = dst;
do /* for each component of src */
{
*comp = dstp;
/* copy the component and trailing separator to dst */
do
{
ch = (int)CHARAT(srcp);
sep = dstp;
WCHARADV(ch, dstp);
if (ch == '\0')
break;
ADVANCE(srcp);
} while (ch != '/');
dir_comp = ch == '/'; /* true if trailing '/' */
/* skip all adjacent '/' characters [the first is preserved] */
while (CHARAT(srcp) == '/')
ADVANCE(srcp);
/* remove redundant trailing slash */
if (CHARAT(srcp) == '\0')
if (sep > dst)
*sep = ch = '\0';
if (DOT(*comp))
{
dir_comp = 1;
dstp = *comp;
if (dstp > dst)
{
sep = dstp - 1;
*dstp = '\0';
}
continue;
}
else if (DOTDOT(*comp))
{
dir_comp = 1;
if (*comp > dst)
{
comp--;
if (!DOTDOT(*comp))
{
dstp = *comp;
if (dstp > dst)
{
sep = dstp - 1;
*dstp = '\0';
}
else
{
if (CHARAT(dst) == '/')
{
/* /.. is same as / */
dstp = dst + 1;
*dstp = '\0';
comp++;
}
else
dst[0] = '.';
sep = dst + 1;
*sep = '\0';
}
continue;
}
}
}
comp++;
} while (ch != '\0');
if (show_dir)
{
if (dir_comp && (sep > dst + 1 || dst[0] != '/'))
{
*sep++ = '/';
*sep = '\0';
}
}
else if (sep > dst)
*sep = '\0'; /* remove trailing '/' */
#ifdef apollo
if (double_slash)
dst--;
#endif
return dst;
}

View File

@@ -0,0 +1,43 @@
/*
* $XConsortium: privbuf.C /main/4 1996/04/21 19:09:31 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#define __PRIVATE_
#include <codelibs/privbuf.h>
implement_array(privbuf_charbuf, char, 128)
implement_array(privbuf_strvec, char*, 128)
void privbuf_release(void **var)
{
if (var == NULL || *var == NULL)
return;
char *buf = (char*)*var;
privbuf_func *p = (privbuf_func*)(void*)buf;
*var = NULL;
(*p)((void*)buf);
}
void privbuf_freeprivbuf(void *buf)
{
privbuf_buffer *b = (privbuf_buffer*)buf;
//delete b->buf;
//delete b->vec;
delete b;
}
privbuf_buffer *privbuf_allocprivbuf()
{
privbuf_buffer *b = new privbuf_buffer;
b->func = privbuf_freeprivbuf;
//b->buf = new privbuf_charbuf;
//b->vec = new privbuf_strvec;
return b;
}

View File

@@ -0,0 +1,480 @@
/*
* $TOG: shellscan.C /main/9 1999/10/14 15:05:42 mgreess $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
# if defined(apollo) && !defined(___GID_T)
// This kludge is needed for the include conflicts mentioned below
// Remove when no longer necessary
# define _NEED___PID_T
# endif
#ifdef DOMAIN_ALLOW_MALLOC_OVERRIDE
#include "/usr/include/apollo/shlib.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define X_INCLUDE_PWD_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <codelibs/nl_hack.h>
#ifdef apollo
// This kludge because of include conflicts between stdlib.h and unistd.h
// Remove when problem is fixed
# ifdef __cplusplus
extern "C" {
# endif
_DECL_FUNC(__pid_t, getpid, (void))
# ifdef __cplusplus
}
# endif
#else /* not apollo */
# include <unistd.h>
#endif /* not apollo */
#include "stringio.h"
#include "buf.h"
#include <codelibs/shellutils.h>
#include <codelibs/boolean.h>
#include <codelibs/stringx.h>
#include "DtSvcLock.h"
#ifdef XTHREADS
extern "C" {
extern void XtProcessLock(void);
extern void XtProcessUnlock(void);
}
#endif
#define ISIDENT(CH) (isalnum(CH) || (CH) == '_')
static _SHXbuf *buf = NULL;
static const char *getvar(const char *var, char *);
// Make this a global someday:
static const char *(*shellvarfn)(const char *, char *) = getvar;
// Parse a sequence of the ksh meta-characters ;&|<> and whitespace
// into a single ksh token. Return a pointer to the token as a
// string. All whitespace characters are mapped to a single space
// character. If ch is not a meta-character, return a NULL pointer.
static char *
parsemeta(int ch, _StringIO &in, char *ifs, unsigned opts, char *meta)
{
if (ch == '\0')
return " "; // whitespace
_DtSvcProcessLock();
if (buf->quote() != NOQUOTE) {
_DtSvcProcessUnlock();
return NULL; // normal character
}
if (!(opts & SHX_NOSPACE) && strchr(ifs, ch) != NULL) {
_DtSvcProcessUnlock();
return " "; // whitespace
}
if (!(opts & SHX_NOMETA))
{
int len = 0;
if (buf->new_token() && isascii(ch) && isdigit(ch))
if (in.next() == '<' || in.next() == '>')
{
meta[len++] = (char)ch;
ch = in.get();
}
switch (meta[len++] = (char)ch, ch)
{
case ';':
case '&':
case '(':
case ')':
meta[len++] = (in.next() == ch) ? in.get() : '\0';
meta[len] = '\0';
_DtSvcProcessUnlock();
return meta;
case '|':
meta[len++] = (in.next() == '|' || in.next() == '&') ?
in.get() : '\0';
meta[len] = '\0';
_DtSvcProcessUnlock();
return meta;
case '>':
case '<':
if (in.next() == ch || in.next() == '&')
meta[len++] = (char)in.get();
meta[len] = '\0';
_DtSvcProcessUnlock();
return meta;
}
}
_DtSvcProcessUnlock();
return NULL; // normal character
}
// Takes the name of a variable, and looks up it's value. Someday,
// this will be replaceable by the user.
static const char *
getvar(const char *name, char *buff)
{
if (name[0] != '\0' && name[1] == '\0')
switch (name[0])
{
case '$':
sprintf(buff, "%d", getpid());
return buff;
case '#':
case '?':
return "0";
}
return getenv(name);
}
// Parse an environment variable name from the _StringIO stream,
// and push its value into the _StringIO stream stack.
static boolean
pushvar(_StringIO &in, char *buff)
{
_StringIO tmp;
privbuf_charbuf name;
tmp = in;
int ch = tmp.get(); // get the first character after the $
if (!isascii(ch))
return FALSE;
if (ch == '{')
while ((ch = tmp.get()) != '\0')
{
// ${foo!bar} form, grab everything inside {} as name
if (ch == '\\') // Only \ does quoting inside ${}
ch = tmp.get();
else if (ch == '}')
break;
name.end() = ch;
}
else if (ispunct(ch))
switch (ch) // Special non-alnum shell variables
{
case '#':
case '?':
case '$':
case '!':
case '-':
case '*':
case '@':
case '_':
name.end() = ch;
break;
default:
return FALSE;
}
else if (isdigit(ch))
name.end() = ch; // single-digit variables
else if (ISIDENT(ch))
{
// normal variable
do
name.end() = ch;
while (isascii(ch = tmp.get()) && ISIDENT(ch));
tmp.unget();
}
else
return FALSE;
name.end() = '\0';
in = tmp;
in.push(shellvarfn(name.getarr(), buff));
return TRUE;
}
static boolean
pushenv(_StringIO &in, char const *name)
{
register char *str = getenv(name);
if (str == NULL || *str == '\0')
return FALSE;
else
{
in.push(str);
return TRUE;
}
}
static boolean
pushtilde(_StringIO &in)
{
_StringIO tmp;
int namelen = 0;
privbuf_charbuf name;
tmp = in;
int ch;
while ((ch = tmp.get()) != '\0' && ch != '/')
name[namelen++] = ch;
name[namelen] = '\0';
tmp.unget();
char *str = name.getarr();
switch (*str)
{
case '\0':
if (!pushenv(tmp, "HOME"))
return FALSE;
break;
case '+':
if (!pushenv(tmp, "PWD"))
return FALSE;
break;
case '-':
if (!pushenv(tmp, "OLDPWD"))
return FALSE;
break;
default:
{
_Xgetpwparams pwd_buf;
memset((char*) &pwd_buf, 0, sizeof(_Xgetpwparams));
struct passwd * pwd_ret = _XGetpwnam(str, pwd_buf);
if (pwd_ret == NULL)
return FALSE;
tmp.push(pwd_ret->pw_dir);
}
break;
}
in = tmp;
return TRUE;
}
void
pushgrave(_StringIO &in, const char endchar, boolean quotes, privbuf_charbuf &result)
{
int ch;
char quote = NOQUOTE;
privbuf_charbuf cmd;
do
{
ch = in.get();
if (quotes)
switch (ch)
{
case '"':
quote = DOUBLEQUOTE;
continue;
case '\'':
if (quote == '"')
break; // not recognized inside of ""
do
cmd.end() = ch;
while ((ch = in.get()) != '\'' && ch != '\0');
cmd.end() = '\'';
quote = NOQUOTE;
continue;
case '\\':
cmd.end() = ch;
ch = in.get();
if (ch != '\0')
cmd.end() = ch;
continue;
}
if (ch == endchar)
ch = '\0';
cmd.end() = ch;
} while (ch != '\0');
result.reset();
FILE *fp = popen(cmd.getarr(), "r");
if (fp == NULL)
return;
while ((ch = getc(fp)) != EOF)
result.end() = ch;
pclose(fp);
// Remove trailing newline, if any
long end = result.size() - 1;
if (result[end] == '\n')
result.reset(end);
result.end() = '\0';
in.push(result.getarr());
}
char const *const *
shellscan(char const *str, int *argc, unsigned opts)
{
if (opts & SHX_COMPLETE)
opts |= SHX_NOSPACE | SHX_NOMETA;
char *ifs = getenv("IFS");
if (ifs == NULL)
ifs = " \t\n";
_DtSvcProcessLock();
if (buf == NULL)
buf = new _SHXbuf;
buf->reset((boolean)!(opts & SHX_NOGLOB), (boolean)(opts & SHX_COMPLETE));
_StringIO in(str);
int ch;
char buff[10], meta_buff[4];
privbuf_charbuf result;
do
{
ch = in.get();
// Don't recognize special characters if this is a shell
// variable or command substitution.
if (!in.in_expansion())
{
// Handle quoting rules, setting the flag array and
// quote variable appropriately.
if (!(opts & SHX_NOQUOTES))
switch (ch)
{
case '"':
buf->quote(DOUBLEQUOTE);
continue;
case '\'':
if (buf->quote() == DOUBLEQUOTE)
break; // not recognized inside of ""
buf->quote(SINGLEQUOTE);
while ((ch = in.get()) != '\'' && ch != '\0')
buf->append(ch);
buf->quote(SINGLEQUOTE);
continue;
case '\\':
ch = in.get();
if (ch == '\n') // ignore \<newline>
continue;
if (ch == '\0')
{
#if defined(__aix) /* Our Macro doesn't like '\\' (ignores rest of line) */
buf->append('\\',
SINGLEQUOTE);
#else
buf->append('\\', SINGLEQUOTE);
#endif
break;
}
if (buf->quote() == NOQUOTE)
{
buf->append(ch, SINGLEQUOTE);
continue;
}
else
{
// inside "", \ only quotes these 4 characters:
switch (ch)
{
case '$':
case '\\':
case '`':
case '"':
buf->append(ch, SINGLEQUOTE);
continue;
default:
// treat the \ and the following char normally
buf->append('\\');
break;
}
}
break;
}
if (!(opts & SHX_NOCMD))
switch (ch)
{
case '`':
pushgrave(in, '`', (boolean)!(opts & SHX_NOQUOTES), result);
continue;
case '$':
if (in.next() != '(')
break;
in.get(); // skip the '('
pushgrave(in, ')', (boolean)!(opts & SHX_NOQUOTES), result);
continue;
}
if (ch == '~' && buf->new_token() && buf->quote() == NOQUOTE)
if (!(opts & SHX_NOTILDE))
{
if (pushtilde(in))
continue;
buf->append('~');
continue;
}
if (ch == '$' && !(opts & SHX_NOVARS))
{
if (pushvar(in, buff))
continue;
buf->append('$');
continue;
}
}
// If the next item is an unquoted whitespace character or
// metacharacter token, terminate the current token. The NUL
// character is considered to be whitespace.
{
int curr_opts = opts;
if (in.in_expansion())
curr_opts |= SHX_NOMETA;
char *meta = parsemeta(ch, in, ifs, curr_opts, meta_buff);
if (meta != NULL) // is it a meta-character?
{
// Terminate current token, if any
if (!buf->new_token())
buf->append('\0');
if (*meta == ' ') // whitespace
{
// ignore contiguous whitespace chars
if (buf->new_token())
continue;
}
else // append the metachar token
buf->append(meta);
continue;
}
}
buf->append(ch);
} while (ch != '\0');
if (argc != NULL)
*argc = buf->ntokens();
_DtSvcProcessUnlock();
return ( (char const *const *) buf->vector() );
/* !!! error 1325: `)' missing at end of input */
}

View File

@@ -0,0 +1,46 @@
/*
* $XConsortium: strcase.C /main/4 1996/04/21 19:09:37 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <codelibs/nl_hack.h>
#include <codelibs/stringx.h>
char *strupper(char *str)
{
int len;
if (str != NULL)
{
for (register char *s = str; *s != '\0'; s++)
if ((len = mblen(s, MB_CUR_MAX)) > 1)
s += len;
else
*s = toupper((unsigned char)*s);
}
return str;
}
char *strlower(char *str)
{
int len;
if (str != NULL)
{
for (register char *s = str; *s != '\0'; s++)
if ((len = mblen(s, MB_CUR_MAX)) > 1)
s += len;
else
*s = tolower((unsigned char)*s);
}
return str;
}

View File

@@ -0,0 +1,24 @@
/*
* $XConsortium: strend.C /main/4 1996/04/21 19:09:40 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <codelibs/stringx.h>
char *
strend(register const char *str)
{
if (str == NULL)
return NULL;
while (*str != '\0')
str++;
return (char *)str;
}

View File

@@ -0,0 +1,112 @@
/*
* $XConsortium: strhash.C /main/5 1996/06/21 17:36:23 ageorge $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <codelibs/nl_hack.h>
#include <codelibs/stringx.h>
/**************************************************
// This is quick but does a pretty crummy job
unsigned strhash(register const unsigned char *key)
{
register unsigned hash = 0;
while (*key != '\0')
hash = (hash << 3) + *key++;
return hash;
}
**************************************************/
#include <limits.h>
#define BITS(type) (CHAR_BIT * (int)sizeof(type))
// This is from the "dragon" Compilers book.
// It is much better than the above but somewhat slower.
//
unsigned strhash(register const char *p)
{
register unsigned h = 0;
register unsigned g;
wchar_t __nlh_char[1];
if (p != NULL)
while (*p != '\0')
{
h = (h << 4) + (unsigned)CHARADV(p);
if (g = h & ((unsigned)0xF << BITS(unsigned) - 4))
{
h ^= g >> BITS(unsigned) - 4;
h ^= g;
}
}
return h;
}
// Same as above but case insensitive. Returns the same value as the
// above function if there are no upper case letters in the string.
//
unsigned strhashi(register const char *p)
{
register unsigned h = 0;
register unsigned g;
wchar_t __nlh_char[1];
if (p != NULL)
while (*p != '\0')
{
if (mblen(p, MB_CUR_MAX) > 1)
h = (h << 4) + (unsigned)CHARADV(p);
else
{
h = (h << 4) + (unsigned)tolower(*p++);
}
if (g = h & ((unsigned)0xF << BITS(unsigned) - 4))
{
h ^= g >> BITS(unsigned) - 4;
h ^= g;
}
}
return h;
}
/**************************************************
// This is about twice as slow as the above but
// does a slightly better hash.
// by TJ Merritt
unsigned int
hashfunc(buf, len)
register unsigned char *buf;
register int len;
{
register unsigned int in;
register unsigned int xor;
register unsigned int t;
xor = len << 8;
in = 0;
while (len-- > 0)
{
in <<= 8;
in += *buf++;
xor ^= in;
t = ((xor & 0x3) << 29) | (xor >> 3);
xor ^= t;
}
return xor ^ (xor >> 16);
}
**************************************************/

View File

@@ -0,0 +1,38 @@
/*
* File: stringio.C $XConsortium: stringio.C /main/5 1996/06/21 17:36:19 ageorge $
*
* (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 <codelibs/nl_hack.h>
#include "stringio.h"
int
_StringIO::doit(register int commit)
{
register wchar_t ch;
register int cu = curr;
register char *ccp;
wchar_t __nlh_char[1];
for (; cu >= 0; cu--)
{
ccp = ptr[cu];
ch = ccp ? CHARAT(ccp) : '\0';
if (ch != '\0')
break;
}
if (commit)
{
old_curr = curr;
if ((curr = cu) >= 0)
{
old_ccp = (const char *)ccp;
ADVANCE(ccp);
ptr[curr] = ccp;
}
}
return ch;
}

View File

@@ -0,0 +1,75 @@
/*
* File: stringio.h $XConsortium: stringio.h /main/3 1995/10/26 16:10:00 rswiston $
*
* (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 <codelibs/boolean.h>
#define __PRIVATE_
#include <codelibs/privbuf.h>
class _StringIO
{
privbuf_strvec ptr;
int curr;
int old_curr;
char const *old_ccp;
int doit(int commit);
public:
void push(char const *ccp);
_StringIO();
_StringIO(char const *ccp);
void unget();
int get();
int next();
boolean in_expansion();
};
inline
_StringIO::_StringIO()
{
curr = old_curr = -1;
old_ccp = 0;
}
inline void
_StringIO::push(char const *ccp)
{
ptr[++curr] = (char*)ccp;
}
inline
_StringIO::_StringIO(char const *ccp)
{
curr = old_curr = -1;
old_ccp = 0;
push(ccp);
}
inline void
_StringIO::unget()
{
if (curr >= 0)
ptr[curr] = (char*)old_ccp;
curr = old_curr;
}
inline int
_StringIO::get()
{
return doit(1);
}
inline int
_StringIO::next()
{
return doit(0);
}
inline boolean
_StringIO::in_expansion()
{
return ((boolean)(curr > 0));
}

View File

@@ -0,0 +1,46 @@
/*
* $XConsortium: strtokx.C /main/4 1996/04/21 19:09:46 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <codelibs/nl_hack.h>
#include <codelibs/mbstring.h>
#include <codelibs/stringx.h>
char *
strtokx(register char *&ptr, register const char *sep)
{
if (ptr == NULL)
return NULL;
// find the beginning of the token
register char *ret = ptr;
while (*ret != '\0' && _mb_schr(sep, *ret) != NULL)
ADVANCE(ret);
// find the end of the token
register char *end = ret;
while (*end != '\0' && _mb_schr(sep, *end) == NULL)
ADVANCE(end);
ptr = end;
// If this isn't the last token, advance pointer and terminate
// current token.
if (*end != '\0')
{
ADVANCE(ptr);
WCHAR('\0', end);
}
if (*ret == '\0')
return NULL;
return ret;
}

View File

@@ -0,0 +1,283 @@
/*
* $TOG: strwcmp.C /main/7 1998/04/17 11:25:04 mgreess $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <codelibs/nl_hack.h>
#include <string.h>
#include <codelibs/stringx.h>
#define QUOTE 0x40000000
#ifdef DEBUG
static char tabs[] = " ";
# define TABS (&tabs[10 - depth])
static int
RETURN(int ret, int depth)
{
printf("%sreturning %s\n", TABS,
(ret ? "SUCCEEDED" : "FAILED"));
return ret;
}
#else
#define RETURN(x,y) (x)
#endif
/* FORWARD */
static int match(const char *, const char *, int);
static const char *next_patt(const char *, int advance = 1);
static int match_class(const char *, char);
/* INLINE */
static int
next_char(register const char *pattern, const char **cpp = NULL)
{
register int ret;
wchar_t __nlh_char[1];
ret = pattern ? (int)CHARAT(pattern) : '\0';
if (ret != '\0')
{
ADVANCE(pattern);
/* AIX needs line broken to get around macro bug (Temporary Fix) */
if (ret == '\\' &&
CHARAT(pattern) != '\0')
ret = QUOTE | (int)CHARADV(pattern);
}
if (cpp != NULL)
*cpp = pattern;
return ret;
}
int
strwcmp(const char *pattern, const char *string)
/*
* String 'pattern' is matched against string 'string'. Zero is
* returned if the match is successful. 'pattern' may contain the
* shell metas * and ? and the semantics are the same. ? and * may
* be escaped with \
*/
{
return !match(pattern, string, 0);
}
// stwpat returns a pointer to the first meta-character if the string
// is a pattern, else NULL
char *
strwpat(register const char *pattern)
{
register int ch;
register char *prev_pattern = (char *)pattern;
wchar_t __nlh_char[1];
while ((ch = next_char(pattern, &pattern)) != '\0')
{
switch (ch)
{
case '*':
return prev_pattern;
case '?':
return prev_pattern;
case '[': {
register const char *eop = next_patt(prev_pattern, 0);
if (CHARAT(eop) == ']')
return prev_pattern;
break;
}
}
prev_pattern = (char *)pattern;
}
return NULL;
}
/*
* match will check to see if pattern can successfully be applied to
* the beginning of string.
*/
static int
match(register const char *pattern, register const char *string, int depth)
{
#ifdef DEBUG
printf("%smatch(\"%s\", \"%s\")\n", TABS, pattern, string);
#endif
int ch;
const char *cp;
wchar_t __nlh_char[1];
while ((ch = next_char(pattern, &cp)) != '\0')
{
const char *laststr = string;
register int testchar = (int)CHARADV(string);
switch (ch)
{
case '*': {
pattern = cp; /* skip over '*' */
string = laststr; /* reverse - testchar not used */
const char *s = string;
do
if (match(pattern, s, depth + 1))
return RETURN(1, depth);
while (CHARADV(s) != '\0');
return RETURN(0, depth);
}
case '?':
break;
case '[': {
int mt = match_class(pattern, testchar);
if (mt == 0)
return RETURN(0, depth);
else if (mt == 2 && ch != testchar)
return RETURN(0, depth);
break;
}
default:
if ((ch & ~QUOTE) != testchar)
return RETURN(0, depth);
break;
}
if (testchar == '\0')
string = laststr; // reverse string
pattern = next_patt(pattern);
}
return RETURN(CHARAT(string) == '\0', depth);
}
static int
match_class(register const char *clss, register char testchar)
/*
* pattern is a pointer to the leading [ of
* a shell-type class. testchar is the character to match against
* the class.
*/
{
int match = 1; /* false if first char is '!' */
wchar_t __nlh_char[1];
/* find end of class, ie an un-escaped ']' */
register const char *eop = next_patt(clss, 0);
ADVANCE(clss);
if (CHARAT(eop) != ']')
return 2;
if (CHARAT(clss) == '!')
{
match = 0;
ADVANCE(clss);
}
while (clss < eop)
{
register int ch = next_char(clss, &clss);
char const *clss_end = clss;
int sep = next_char(clss_end, &clss_end);
int ch2 = next_char(clss_end, &clss_end);
/* check if next three chars are a range */
if (sep == '-' && ch2 != ']')
{
/* check range - we have to use strcoll to do it right */
char c1[MB_LEN_MAX+1], c2[MB_LEN_MAX+1], tc[MB_LEN_MAX+1];
memset(c1, 0, sizeof(c1));
memset(c2, 0, sizeof(c2));
memset(tc, 0, sizeof(tc));
ch &= ~QUOTE;
WCHAR(ch, c1);
ch2 &= ~QUOTE;
WCHAR(ch2, c2);
WCHAR(testchar, tc);
/* if (ch <= testchar && testchar <= ch2) // Original code */
/* Second implementation:
* if (nl_strncmp(c1, tc, 1) <= 0 && nl_strncmp(tc, c2, 1) <= 0)
* return match;
*/
/* Third, portable implementation: */
if (strcoll(c1, tc) <= 0 && strcoll(tc, c2) <= 0)
return match;
clss = clss_end;
}
else /* they are not a range, check simple
match */
{
if ((ch & ~QUOTE) == testchar)
return match;
}
}
return !match;
}
static const char *
next_patt(register const char *pattern, int advance)
{
wchar_t __nlh_char[1];
if (CHARAT(pattern) == '[')
{
int ch;
const char *pp = pattern;
ADVANCE(pp);
if (CHARAT(pp) == '^')
ADVANCE(pp);
if (CHARAT(pp) == ']')
ADVANCE(pp);
char const *np;
for (; (ch = next_char(pp, &np)) != '\0'; pp = np)
if (ch == ']')
return (advance ? np : pp);
}
next_char(pattern, &pattern);
return pattern;
}
#ifdef DEBUG
#define MAIN main
MAIN()
{
char pattern[50], string[50];
while (1)
{
putchar('\n');
printf("pattern: ");
if (fgets(pattern, sizeof(pattern)-1, stdin) == NULL)
break;
printf("string: ");
if (fgets(string, sizeof(pattern)-1, stdin) == NULL)
break;
printf("MATCH is %s\n",
((strwcmp(pattern, string) == 0) ? "SUCCEEDED" : "FAILED"));
putchar('\n');
printf("MATCHI is %s\n",
((strwcmpi(pattern, string) == 0) ? "SUCCEEDED" : "FAILED"));
}
return 0;
}
#endif

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
/* $TOG: Action.h /main/4 1998/05/06 15:55:18 rafi $ */
/*
* (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.
*/
#ifndef _Dt_Action_h
#define _Dt_Action_h
#include <X11/Intrinsic.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Argument types
*/
#define DtACTION_FILE 1 /* file argument */
#define DtACTION_BUFFER 2 /* buffer argument */
#define DtACTION_STRING 3 /* string argument */
#define DtACTION_NULLARG 4 /* untyped return-only argument */
typedef struct {
void *bp; /* location of buffer */
int size; /* size of buffer in bytes */
char *type; /* (opt.) type of buffer */
char *name; /* (opt.) name of buffer object */
Boolean writable; /* allow changes to buffer object? */
} DtActionBuffer;
typedef struct {
char *name;
} DtActionFile;
typedef struct {
/*
* Structure containing argument information
*/
int argClass; /* see argument types */
union {
DtActionFile file;
DtActionBuffer buffer;
} u;
} DtActionArg;
/*
* DtActionStatus codes
*/
typedef enum {
DtACTION_OK, /* If not any of the below */
DtACTION_INVALID_ID, /* ID is not valid */
DtACTION_INVOKED, /* the action invocation step is done */
DtACTION_STATUS_UPDATE, /* status update */
DtACTION_DONE, /* normal action termination code */
DtACTION_FAILED, /* error running action */
DtACTION_CANCELED /* normal action termination by cancel*/
} DtActionStatus;
typedef void (*DtDbReloadCallbackProc)(
XtPointer clientData);
/*
* DtActionInvocationID is the fundamental user-space handle to invoked
* actions.
*/
typedef unsigned long DtActionInvocationID;
typedef void (*DtActionCallbackProc) (
DtActionInvocationID id,
XtPointer client_data,
DtActionArg *actionArgPtr,
int actionArgCount,
DtActionStatus status);
/*
* Functions
*/
extern Boolean DtActionExists(
char *actionName);
extern char * DtActionLabel(
char *actionName);
extern char * DtActionDescription(
char *actionName);
extern void DtDbReloadNotify (
DtDbReloadCallbackProc proc,
XtPointer clientData);
extern void DtDbLoad(void);
extern DtActionInvocationID DtActionInvoke (
Widget w,
char *action,
DtActionArg *args,
int argCount,
char *termOpts,
char *execHost,
char *contextDir,
int useIndicator,
DtActionCallbackProc statusUpdateCb,
XtPointer client_data);
extern char * DtActionIcon(
char *actionName);
#ifdef __cplusplus
}
#endif
#endif /* _Dt_Action_h */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,219 @@
/*****************************************************************************
*
* File: ActionDb.h
* RCS: $XConsortium: ActionDb.h /main/3 1995/10/26 14:58:38 rswiston $
* Description: Internal header file for the action database functions.
* Language: C
* Package: N/A
* Status: Experimental (Do Not Distribute)
*
*
** (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.
*****************************************************************************/
#ifndef _Dt_ActionDb_h
#define _Dt_ActionDb_h
/*
* The following constants are used by the database parsing code to
* identify the field names for an action definition.
*
* Recognized Field names for any action definition.
*/
#define _DtACTION_NAME "ACTION"
#define _DtACTION_TYPE "TYPE"
#define _DtACTION_LABEL "LABEL"
#define _DtACTION_ARG_CLASS "ARG_CLASS"
#define _DtACTION_ARG_MODE "ARG_MODE"
#define _DtACTION_ARG_TYPE "ARG_TYPE"
#define _DtACTION_ARG_COUNT "ARG_COUNT"
#define _DtACTION_DESCRIPTION "DESCRIPTION"
#define _DtACTION_ICON "ICON"
#define _DtACTION_INSTANCE_ICON "INSTANCE_ICON"
/*
* Miscellaneous syntax strings
*/
#define _DtACT_ANY "*"
#define _DtACT_LIST_SEPARATOR_CHAR ','
#define _DtACT_GT_CHAR '>'
#define _DtACT_LT_CHAR '<'
/*
* Valid values for ACTION_TYPE
*/
#define _DtACTION_MAP "MAP"
#define _DtACTION_COMMAND "COMMAND"
#define _DtACTION_TT_MSG "TT_MSG"
#ifdef _DT_ALLOW_DT_MSGS
#define _DtACTION_DT_REQUEST "DT_REQUEST"
#define _DtACTION_DT_NOTIFY "DT_NOTIFY"
#endif /* _DT_ALLOW_DT_MSGS */
/*
* Field names for "MAP" type actions
*/
#define _DtACTION_MAP_ACTION "MAP_ACTION"
/*
* Field names for the "COMMAND" type actions.
*/
#define _DtACTION_EXEC_STRING "EXEC_STRING"
#define _DtACTION_EXEC_HOST "EXEC_HOST"
#define _DtACTION_CWD "CWD"
#define _DtACTION_WINDOW_TYPE "WINDOW_TYPE"
#define _DtACTION_TERM_OPTS "TERM_OPTS"
/*
* Field names for "TT_MSG" type actions
*/
#define _DtACTION_TT_CLASS "TT_CLASS"
#define _DtACTION_TT_SCOPE "TT_SCOPE"
#define _DtACTION_TT_OPERATION "TT_OPERATION"
#define _DtACTION_TT_FILE "TT_FILE"
/* definitions to decifer TT_ARGn_* fields */
#define _DtACTION_TTN_ARG "TT_ARG"
#define _DtACTION_TTN_MODE "_MODE"
#define _DtACTION_TTN_VTYPE "_VTYPE"
#define _DtACTION_TTN_REP_TYPE "_REP_TYPE"
#define _DtACTION_TTN_VALUE "_VALUE"
#ifdef _DT_ALLOW_DT_MSGS
/*
* Field names for "DT_REQUEST" type actions
*/
#define _DtACTION_DT_REQUEST_NAME "DT_REQUEST_NAME"
#define _DtACTION_DT_SVC "DT_SVC"
/*
* Field names for "DT_NOTIFY" type actions
*/
#define _DtACTION_DT_NOTIFY_NAME "DT_NOTIFY_NAME"
#define _DtACTION_DT_NGROUP "DT_NGROUP"
/*
* Field names for DT ARGn (either request or notify)
*/
#define _DtACTION_DTN_ARG "DT_ARG"
#define _DtACTION_DTN_VALUE "_VALUE"
#endif /* _DT_ALLOW_DT_MSGS */
/*
* Valid Field value strings
* for Command Actions Window Types
*/
#define _DtACTION_TERMINAL "TERMINAL"
#define _DtACTION_PERM_TERMINAL "PERM_TERMINAL"
#define _DtACTION_NO_STDIO "NO_STDIO"
/*
* Valid Field values for ARG_CLASS records.
*/
#define _DtACTION_BUFFER "BUFFER"
#define _DtACTION_FILE "FILE"
#define _DtACTION_STRING "STRING"
/*
* Valid Field values for ARG_MODE
*/
#define _DtACT_ARG_MODE_WRITE "w"
#define _DtACT_ARG_MODE_NOWRITE "!w"
#define _DtACT_ARG_MODE_ANY _DtACT_ANY
/*
* Valid Field values for TT_CLASS records.
*/
#define _DtACTION_TT_NOTICE "TT_NOTICE"
#define _DtACTION_TT_REQUEST "TT_REQUEST"
/*
* Valid Field values for TT_SCOPE records.
*/
#define _DtACTION_TT_SESSION "TT_SESSION"
#define _DtACTION_TT_BOTH "TT_BOTH"
#define _DtACTION_TT_FILE_IN_SESSION "TT_FILE_IN_SESSION"
/* --- same as TT_MSG's TT_FILE field name --------
#define _DtACTION_TT_FILE "TT_FILE"
*/
/*
* Valid Field values for TT_ARGn_MODE
*/
#define _DtACTION_TT_MODE_IN "TT_IN"
#define _DtACTION_TT_MODE_OUT "TT_OUT"
#define _DtACTION_TT_MODE_INOUT "TT_INOUT"
/*
* Valid Field values for TT_ARGn_REP_TYPE
*/
#define _DtACTION_TT_RTYP_UND "TT_REP_UNDEFINED"
#define _DtACTION_TT_RTYP_INT "TT_REP_INTEGER"
#define _DtACTION_TT_RTYP_BUF "TT_REP_BUFFER"
#define _DtACTION_TT_RTYP_STR "TT_REP_STRING"
/*
* Action Keywords --
* these keywords appear in the action database files
* in the form: %<qualifier><keyword><prompt string>%
* where the optional qualifier in enclosed in: ()
* and the optional prompt string is enclosed in: ""
*/
#define _DtACT_DATABASEHOST_STR "DatabaseHost"
#define _DtACT_DISPLAYHOST_STR "DisplayHost"
#define _DtACT_LOCALHOST_STR "LocalHost"
#define _DtACT_SESSIONHOST_STR "SessionHost"
#define _DtACT_ARGS_STR "Args"
#define _DtACT_ARG_UNDER_STR "Arg_"
#define _DtACT_STRING_QUALIFIER "(String)"
#define _DtACT_FILE_QUALIFIER "(File)"
/*
* Default action field value definitions (these should be strings)
* for recognized fields.
*/
#define _DtACT_LBL_DFLT NULL
#define _DtACT_TYPE_DFLT _DtACTION_COMMAND
#define _DtACT_ARG_CLASS_DFLT _DtACT_ANY
#define _DtACT_ARG_MODE_DFLT _DtACT_ANY
#define _DtACT_ARG_TYPE_DFLT _DtACT_ANY
#define _DtACT_ARG_CNT_DFLT _DtACT_ANY
#define _DtACT_DESC_DFLT NULL
#define _DtACT_ICON_DFLT NULL
#define _DtACT_MAP_ACT_DFLT NULL
#define _DtACT_EXEC_STRG_DFLT NULL
#define _DtACT_EXEC_HOST_DFLT \
"%" _DtACT_DATABASEHOST_STR "%,%" _DtACT_LOCALHOST_STR "%"
#define _DtACT_CWD_DFLT NULL
#define _DtACT_WIN_TYPE_DFLT _DtACTION_PERM_TERMINAL
#define _DtACT_TERM_OPTS_DFLT NULL
#define _DtACT_TT_CLASS_DFLT NULL
#define _DtACT_TT_SCOPE_DFLT NULL
#define _DtACT_TT_OP_DFLT NULL
#define _DtACT_TT_FILE_DFLT NULL
#ifdef _DT_ALLOW_DT_MSGS
#define _DtACT_DT_REQ_DFLT NULL
#define _DtACT_DT_SVC_DFLT NULL
#define _DtACT_DT_NTFY_DFLT NULL
#define _DtACT_DT_NGRP_DFLT NULL
#endif /* _DT_ALLOW_DT_MSGS */
#endif /* _Dt_ActionDb_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,121 @@
/*****************************************************************************
*
* File: ActionDbP.h
* RCS: $XConsortium: ActionDbP.h /main/3 1995/10/26 14:58:53 rswiston $
* Description: Private header file for the action database functions.
* Language: C
* Package: N/A
*
*
** (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.
*****************************************************************************/
#ifndef _Dt_ActionDbP_h
#define _Dt_ActionDbP_h
#include <Dt/DbReader.h>
#include <Dt/ActionDb.h>
#define _DtMAX_NUM_FIELDS 30
#define _ActDb_MAX_NUM_FIELDS _DtMAX_NUM_FIELDS
/*
* Bitmask field definitions for the action converter bit mask.
* These are NOT the bits for the mask in struct ACTION.
*/
#define _ActDb_LABEL_SET (1<<0)
#define _ActDb_TYPE_SET (1<<1)
#define _ActDb_ARG_CLASS_SET (1<<2)
#define _ActDb_ARG_TYPE_SET (1<<3)
#define _ActDb_ARG_COUNT_SET (1<<4)
#define _ActDb_ARG_MODE_SET (1<<5)
#define _ActDb_DESCRIPTION_SET (1<<6)
#define _ActDb_ICON_SET (1<<7)
#define _ActDb_MAP_ACTION_SET (1<<10)
#define _ActDb_EXEC_STRING_SET (1<<12)
#define _ActDb_EXEC_HOST_SET (1<<13)
#define _ActDb_CWD_SET (1<<14)
#define _ActDb_WINDOW_TYPE_SET (1<<15)
#define _ActDb_TERM_OPTS_SET (1<<16)
#define _ActDb_TT_CLASS_SET (1<<18)
#define _ActDb_TT_SCOPE_SET (1<<19)
#define _ActDb_TT_OPERATION_SET (1<<20)
#define _ActDb_TT_FILE_SET (1<<21)
#define _ActDb_TT_ARGN_MODE_SET (1<<22)
#define _ActDb_TT_ARGN_VTYP_SET (1<<23)
#define _ActDb_TT_ARGN_RTYP_SET (1<<24)
#define _ActDb_TT_ARGN_VAL_SET (1<<25)
#ifdef _DT_ALLOW_DT_MSGS
#define _ActDb_DT_REQ_NAME_SET (1<<26)
#define _ActDb_DT_SVC_SET (1<<27)
#define _ActDb_DT_NTFY_NAME_SET (1<<28)
#define _ActDb_DT_NGROUP_SET (1<<29)
#define _ActDb_DT_ARGN_VAL_SET (1<<30)
/* no mask for ARGn strings */
#define _ActDb_DT_REQUEST_BITS ( _ActDb_DT_REQ_NAME_SET \
| _ActDb_DT_SVC_SET )
#define _ActDb_DT_NOTIFY_BITS ( _ActDb_DT_NTFY_NAME_SET \
| _ActDb_DT_NGROUP_SET )
#endif /* _DT_ALLOW_DT_MSGS */
#define _ActDb_TT_BITS ( _ActDb_TT_CLASS_SET \
| _ActDb_TT_SCOPE_SET \
| _ActDb_TT_OPERATION_SET \
| _ActDb_TT_ARGN_MODE_SET \
| _ActDb_TT_ARGN_VTYP_SET \
| _ActDb_TT_ARGN_RTYP_SET \
| _ActDb_TT_ARGN_VAL_SET \
| _ActDb_TT_FILE_SET )
#define _ActDb_CMD_BITS ( _ActDb_EXEC_STRING_SET \
| _ActDb_CWD_SET \
| _ActDb_WINDOW_TYPE_SET \
| _ActDb_TERM_OPTS_SET )
#define _ActDb_MAP_BITS ( _ActDb_MAP_ACTION_SET )
#define _ActDb_TT_ARGN_BITS ( _ActDb_TT_ARGN_MODE_SET \
| _ActDb_TT_ARGN_VTYP_SET \
| _ActDb_TT_ARGN_RTYP_SET \
| _ActDb_TT_ARGN_VAL_SET )
#ifdef _DT_ALLOW_DT_MSGS
#define _ActDb_ARGN_BITS ( _ActDb_TT_ARGN_BITS \
| _ActDb_DT_ARGN_VAL_SET )
#else
#define _ActDb_ARGN_BITS ( _ActDb_TT_ARGN_BITS )
#endif /* _DT_ALLOW_DT_MSGS */
/******************************************************************************
*
* Private (but external) entry points for internal use by Action Database
* Library code only.
*
*****************************************************************************/
# ifdef __cplusplus
extern "C" {
# endif
extern Boolean _DtActionConverter( DtDtsDbField *fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus);
# ifdef __cplusplus
}
# endif
#endif /* _Dt_ActionDbP_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/* $XConsortium: ActionFind.h /main/4 1995/10/26 14:59:41 rswiston $ */
/************************************<+>*************************************
****************************************************************************
**
** File: ActionFind.h
**
** Project: DT
**
** Description: Public include file for the ActionFind functions.
**
** (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.
****************************************************************************
************************************<+>*************************************/
#ifndef _Dt_ActionFind_h
#define _Dt_ActionFind_h
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <Dt/ActionP.h>
#include <Dt/DtsDb.h>
#include <Dt/DtsMM.h>
# ifdef __cplusplus
extern "C" {
# endif
extern void _DtSortActionDb(void);
extern ActionPtr
_DtActionFindDBEntry( ActionRequest *reqp,
DtShmBoson actQuark );
# ifdef __cplusplus
}
# endif
#endif /* _Dt_ActionFind_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,827 @@
/* $XConsortium: ActionP.h /main/3 1995/10/26 14:59:56 rswiston $ */
/************************************<+>*************************************
****************************************************************************
**
** File: ActionP.h
**
** Project: DT
**
** Description: Private include file for the Action Library.
**
**
** (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.
****************************************************************************
************************************<+>*************************************/
#ifndef _ActionP_h
#define _ActionP_h
#include <Dt/DtP.h>
#include <Dt/DbReader.h>
#include <Dt/ActionDb.h>
#include <Dt/Action.h>
#include <Tt/tttk.h>
#include <Dt/DtShmDb.h>
/*
* Environment Variable Names
*/
#define ENV_SESSION_SVR "SESSION_SVR"
/*
* Define maximum static buffer size for action code.
*/
#define _DtAct_MAX_BUF_SIZE 1024
/*
* Data-type field which contains the template for producing filenames
* of a given type.
*/
#define _DtActNAME_TEMPLATE "NAME_TEMPLATE"
#define _DtActIS_EXECUTABLE "IS_EXECUTABLE"
/******************************************************************************
*
* MASK LAYOUT:
*
* The same layout is used for all the masks (defined herein);, independent of
* the data structure in which they are defined. That is, all bit fields for
* all masks are non-overlapping. In general, the mask in any given structure
* should ONLY contain information in the field appropriate for that structure.
*
* The action bit mask is broken into the following fields
*
* --------------------------------------------------------------------------
* |act'n |arg |arg |arg | win |args| request | object |treat| not |
* |type |class|count|typ | type | | status | status | as | |
* |bits |bits |bits |bit | bits |used| bits | bits |file |used |
* --------------------------------------------------------------------------
* 0 - 4,5 - 8,9 - 12, 13 ,14 - 17,18-19,20 ------- 22,23 ---- 28, 29 ,30-31
* | | | | | |
* |<-- action mask -->| |<- request->|<- obj. ->|< - >|
* mask data |
* mask msgCcomp.
* mask
******************************************************************************/
/*
* generic bit manipulation macros
*/
#define SET_ANY_BITS(mask,bits) ( mask |= (bits) )
#define RESET_ANY_BITS(mask,bits) ( mask &= ~(bits) )
#define TST_ANY_BITS(mask,bits) ( mask & (bits) )
/*
* Action type bits
*/
#define _DtAct_CMD_BIT (1<<0)
#define _DtAct_MAP_BIT (1<<1)
#define _DtAct_TT_MSG_BIT (1<<2)
#ifdef _DT_ALLOW_DT_MSGS
#define _DtAct_DT_REQ_MSG_BIT (1<<3)
#define _DtAct_DT_NTFY_MSG_BIT (1<<4)
#endif /* _DT_ALLOW_DT_MSGS */
/*
* Action structure mask bits
*/
#define _DtAct_ARG_CLASS_FILE_BIT (1<<5)
#define _DtAct_ARG_CLASS_STRING_BIT (1<<6)
#define _DtAct_ARG_CLASS_BUFFER_BIT (1<<7)
#define _DtAct_ARG_CLASS_WILD_BIT (1<<8)
#define _DtAct_ARG_COUNT_LT_BIT (1<<9)
#define _DtAct_ARG_COUNT_GT_BIT (1<<10)
#define _DtAct_ARG_COUNT_EQ_BIT (1<<11)
#define _DtAct_ARG_COUNT_WILD_BIT (1<<12)
#define _DtAct_ARG_TYPE_WILD_BIT (1<<13)
#define _DtAct_NO_STDIO_BIT (1<<14)
#define _DtAct_TERMINAL_BIT (1<<15)
#define _DtAct_PERM_TERM_BIT (1<<16)
/*
* Defines which reflect the actual number
* of %ARGn% instances found in the action definition
* NOTE: Is this JUST in the EXEC_STRING? or the total number of %ARGn%'s
* referenced in all parssed definitions?
*
*/
#define _DtAct_SINGLE_ARG_BIT (1<<18)
#define _DtAct_MULTI_ARG_BIT (1<<19)
#ifdef _DT_ALLOW_DT_MSGS
#define _DtAct_ACTION_TYPE_BITS ( _DtAct_CMD_BIT \
| _DtAct_MAP_BIT \
| _DtAct_DT_NTFY_MSG_BIT \
| _DtAct_DT_REQ_MSG_BIT \
| _DtAct_TT_MSG_BIT )
#else
#define _DtAct_ACTION_TYPE_BITS ( _DtAct_CMD_BIT \
| _DtAct_MAP_BIT \
| _DtAct_TT_MSG_BIT )
#endif /* _DT_ALLOW_DT_MSGS */
#define _DtAct_ARG_CLASS_BITS ( _DtAct_ARG_CLASS_FILE_BIT \
| _DtAct_ARG_CLASS_STRING_BIT\
| _DtAct_ARG_CLASS_BUFFER_BIT \
| _DtAct_ARG_CLASS_WILD_BIT )
#define _DtAct_ARG_TYPE_BITS ( _DtAct_ARG_TYPE_WILD_BIT )
#define _DtAct_ARG_COUNT_BITS ( _DtAct_ARG_COUNT_LT_BIT \
| _DtAct_ARG_COUNT_GT_BIT \
| _DtAct_ARG_COUNT_EQ_BIT \
| _DtAct_ARG_COUNT_WILD_BIT )
#define _DtAct_WINTYPE_BITS ( _DtAct_NO_STDIO_BIT \
| _DtAct_TERMINAL_BIT \
| _DtAct_PERM_TERM_BIT )
#define _DtAct_ARGS_USED_BITS ( _DtAct_SINGLE_ARG \
| _DtAct_MULTI_ARG )
#define _DtAct_ACTION_BITS ( _DtAct_ACTION_TYPE_BITS \
| _DtAct_ARG_CLASS_BITS \
| _DtAct_ARG_TYPE_BITS \
| _DtAct_ARG_COUNT_BITS \
| _DtAct_WINTYPE_BITS \
| _DtAct_ARGS_USED_BITS )
#define IS_CMD(mask) ( mask & _DtAct_CMD_BIT )
#define IS_MAP(mask) ( mask & _DtAct_MAP_BIT )
#define IS_TT_MSG(mask) ( mask & _DtAct_TT_MSG_BIT )
#ifdef _DT_ALLOW_DT_MSGS
#define IS_DT_REQ_MSG(mask) ( mask & _DtAct_DT_REQ_MSG_BIT )
#define IS_DT_NOTIFY_MSG(mask) ( mask & _DtAct_DT_NTFY_MSG_BIT )
#endif /* _DT_ALLOW_DT_MSGS */
#define SET_CMD_ACTION(mask) ( mask |= _DtAct_CMD_BIT )
#define SET_MAP_ACTION(mask) ( mask |= _DtAct_MAP_BIT )
#define SET_TT_MSG(mask) ( mask |= _DtAct_TT_MSG_BIT )
#ifdef _DT_ALLOW_DT_MSGS
#define SET_DT_REQUEST_MSG(mask) ( mask |= _DtAct_DT_REQ_MSG_BIT)
#define SET_DT_NOTIFY_MSG(mask) ( mask |= _DtAct_DT_NTFY_MSG_BIT)
#endif /* _DT_ALLOW_DT_MSGS */
#define RESET_CMD_ACTION(mask) ( mask &= ~(_DtAct_CMD_BIT))
#define RESET_MAP_ACTION(mask) ( mask &= ~(_DtAct_MAP_BIT))
#define RESET_TT_MSG(mask) ( mask &= ~(_DtAct_TT_MSG_BIT))
#ifdef _DT_ALLOW_DT_MSGS
#define RESET_DT_REQ_MSG(mask) ( mask &= ~(_DtAct_DT_REQ_MSG_BIT))
#define RESET_DT_NOTIFY_MSG(mask) ( mask &= ~(_DtAct_DT_NTFY_MSG_BIT))
#endif /* _DT_ALLOW_DT_MSGS */
#define IS_NO_STDIO(mask) ( mask & _DtAct_NO_STDIO_BIT )
#define IS_TERMINAL(mask) ( mask & _DtAct_TERMINAL_BIT )
#define IS_PERM_TERM(mask) ( mask & _DtAct_PERM_TERM_BIT)
#define SET_NO_STDIO(mask) ( mask |= _DtAct_NO_STDIO_BIT )
#define SET_TERMINAL(mask) ( mask |= _DtAct_TERMINAL_BIT )
#define SET_PERM_TERM(mask) ( mask |= _DtAct_PERM_TERM_BIT )
#define RESET_NO_STDIO(mask) ( mask &= ~(_DtAct_NO_STDIO_BIT ))
#define RESET_TERMINAL(mask) ( mask &= ~(_DtAct_TERMINAL_BIT ))
#define RESET_PERM_TERM(mask) ( mask &= ~(_DtAct_PERM_TERM_BIT ))
#define IS_ARG_CLASS_FILE(mask) ( mask & _DtAct_ARG_CLASS_FILE_BIT )
#define IS_ARG_CLASS_STRING(mask) ( mask & _DtAct_ARG_CLASS_STRING_BIT )
#define IS_ARG_CLASS_BUFFER(mask) ( mask & _DtAct_ARG_CLASS_BUFFER_BIT )
#define IS_ARG_CLASS_WILD(mask) ( mask & _DtAct_ARG_CLASS_WILD_BIT )
#define SET_ARG_CLASS_FILE(mask) ( mask |= _DtAct_ARG_CLASS_FILE_BIT )
#define SET_ARG_CLASS_STRING(mask) ( mask |= _DtAct_ARG_CLASS_STRING_BIT)
#define SET_ARG_CLASS_BUFFER(mask) ( mask |= _DtAct_ARG_CLASS_BUFFER_BIT)
#define SET_ARG_CLASS_WILD(mask) ( mask |= _DtAct_ARG_CLASS_WILD_BIT )
#define RESET_ARG_CLASS_FILE(mask) (mask &= ~(_DtAct_ARG_CLASS_FILE_BIT))
#define RESET_ARG_CLASS_STRING(mask) (mask &= ~(_DtAct_ARG_CLASS_STRING_BIT))
#define RESET_ARG_CLASS_BUFFER(mask) (mask &= ~(_DtAct_ARG_CLASS_BUFFER_BIT))
#define RESET_ARG_CLASS_WILD(mask) (mask &= ~(_DtAct_ARG_CLASS_WILD_BIT))
#define IS_ARG_TYPE_WILD(mask) ( mask & _DtAct_ARG_TYPE_WILD_BIT )
#define SET_ARG_TYPE_WILD(mask) ( mask |= _DtAct_ARG_TYPE_WILD_BIT )
#define RESET_ARG_TYPE_WILD(mask) ( mask &= ~(_DtAct_ARG_TYPE_WILD_BIT))
#define IS_ARG_COUNT_GT(mask) ( mask & _DtAct_ARG_COUNT_GT_BIT )
#define IS_ARG_COUNT_LT(mask) ( mask & _DtAct_ARG_COUNT_LT_BIT )
#define IS_ARG_COUNT_EQ(mask) ( mask & _DtAct_ARG_COUNT_EQ_BIT )
#define IS_ARG_COUNT_WILD(mask) ( mask & _DtAct_ARG_COUNT_WILD_BIT )
#define SET_ARG_COUNT_GT(mask) ( mask |= _DtAct_ARG_COUNT_GT_BIT )
#define SET_ARG_COUNT_LT(mask) ( mask |= _DtAct_ARG_COUNT_LT_BIT )
#define SET_ARG_COUNT_EQ(mask) ( mask |= _DtAct_ARG_COUNT_EQ_BIT )
#define SET_ARG_COUNT_WILD(mask) ( mask |= _DtAct_ARG_COUNT_WILD_BIT )
#define RESET_ARG_COUNT_GT(mask) ( mask &= ~(_DtAct_ARG_COUNT_GT_BIT ))
#define RESET_ARG_COUNT_LT(mask) ( mask &= ~(_DtAct_ARG_COUNT_LT_BIT ))
#define RESET_ARG_COUNT_EQ(mask) ( mask &= ~(_DtAct_ARG_COUNT_EQ_BIT ))
#define RESET_ARG_COUNT_WILD(mask) ( mask &= ~(_DtAct_ARG_COUNT_WILD_BIT ))
/*
* Use of the logical "NOT" operator(!) instead of the bitwise negation
* operator(~) is intentional in IS_ARG_NONE_FOUND.
*/
#define IS_ARG_NONE_FOUND(mask) !( mask & ( _DtAct_SINGLE_ARG_BIT \
| _DtAct_MULTI_ARG_BIT ))
#define IS_ARG_SINGLE_ARG(mask) ( mask & _DtAct_SINGLE_ARG_BIT )
#define IS_ARG_MULTI_ARG(mask) ( mask & _DtAct_MULTI_ARG_BIT )
#define SET_ARG_NONE_FOUND(mask) ( mask &= ~( _DtAct_SINGLE_ARG_BIT \
| _DtAct_MULTI_ARG_BIT ))
#define SET_ARG_SINGLE_ARG(mask) ((mask |= _DtAct_SINGLE_ARG_BIT), \
( mask &= ~(_DtAct_MULTI_ARG_BIT)))
#define SET_ARG_MULTI_ARG(mask) ((mask |= _DtAct_MULTI_ARG_BIT), \
( mask &= ~(_DtAct_SINGLE_ARG_BIT)))
#define RESET_ARG_SINGLE_ARG(mask) ( mask &= ~(_DtAct_SINGLE_ARG_BIT))
#define RESET_ARG_MULTI_ARG(mask) ( mask &= ~(_DtAct_MULTI_ARG_BIT))
/*
* ActionRequest structure mask bits
*/
#define _DtAct_REPROCESSING_BIT (1<<20)
#define _DtAct_TOO_MANY_MAPS_BIT (1<<21)
#define _DtAct_CLONED_REQUEST_BIT (1<<22)
#define _DtAct_ACTION_REQUEST_BITS ( _DtAct_REPROCESSING_BIT \
| _DtAct_TOO_MANY_MAPS_BIT \
| _DtAct_CLONED_REQUEST_BIT )
#define IS_REPROCESSING(mask) ( mask & _DtAct_REPROCESSING_BIT )
#define IS_TOO_MANY_MAPS(mask) ( mask & _DtAct_TOO_MANY_MAPS_BIT )
#define IS_CLONED_REQUEST(mask) ( mask & _DtAct_CLONED_REQUEST_BIT )
#define SET_REPROCESSING(mask) ( mask |= _DtAct_REPROCESSING_BIT )
#define SET_TOO_MANY_MAPS(mask) ( mask |= _DtAct_TOO_MANY_MAPS_BIT )
#define SET_CLONED_REQUEST(mask) ( mask |= _DtAct_CLONED_REQUEST_BIT )
#define RESET_REPROCESSING(mask) ( mask &= ~(_DtAct_REPROCESSING_BIT))
#define RESET_TOO_MANY_MAPS(mask) ( mask &= ~(_DtAct_TOO_MANY_MAPS_BIT))
#define RESET_CLONED_REQUEST(mask) ( mask &= ~(_DtAct_CLONED_REQUEST_BIT))
/*
* ObjectData structure mask bits
*
*/
#define _DtAct_WRITE_OBJ_BIT (1<<23)
#define _DtAct_FILE_OBJ_BIT (1<<24)
#define _DtAct_BUFFER_OBJ_BIT (1<<25)
#define _DtAct_STRING_OBJ_BIT (1<<26)
#define _DtAct_DIR_OBJ_BIT (1<<27)
#define _DtAct_UNKNOWN_IF_DIR_BIT (1<<28)
#define _DtAct_OBJ_DATA_BITS ( _DtAct_WRITE_OBJ_BIT \
| _DtAct_FILE_OBJ_BIT \
| _DtAct_DIR_OBJ_BIT \
| _DtAct_BUFFER_OBJ_BIT \
| _DtAct_STRING_OBJ_BIT \
| _DtAct_UNKNOWN_IF_DIR_BIT )
#define IS_WRITE_OBJ(mask) ( mask & _DtAct_WRITE_OBJ_BIT )
#define IS_FILE_OBJ(mask) ( mask & _DtAct_FILE_OBJ_BIT )
#define IS_BUFFER_OBJ(mask) ( mask & _DtAct_BUFFER_OBJ_BIT )
#define IS_STRING_OBJ(mask) ( mask & _DtAct_STRING_OBJ_BIT )
#define IS_UNKNOWN_IF_DIR(mask) ( mask & _DtAct_UNKNOWN_IF_DIR_BIT )
#define IS_DIR_OBJ(mask) ( mask & \
( _DtAct_UNKNOWN_IF_DIR_BIT \
| _DtAct_DIR_OBJ_BIT ) \
== _DtAct_DIR_OBJ_BIT)
#define SET_WRITE_OBJ(mask) ( mask |= _DtAct_WRITE_OBJ_BIT )
#define SET_FILE_OBJ(mask) ( mask |= _DtAct_FILE_OBJ_BIT )
#define SET_BUFFER_OBJ(mask) ( mask |= _DtAct_BUFFER_OBJ_BIT )
#define SET_STRING_OBJ(mask) ( mask |= _DtAct_STRING_OBJ_BIT )
#define SET_DIR_OBJ(mask) ( mask |= _DtAct_DIR_OBJ_BIT )
#define SET_UNKNOWN_IF_DIR(mask) ( mask |= _DtAct_UNKNOWN_IF_DIR_BIT)
#define RESET_WRITE_OBJ(mask) ( mask &= ~(_DtAct_WRITE_OBJ_BIT))
#define RESET_FILE_OBJ(mask) ( mask &= ~(_DtAct_FILE_OBJ_BIT))
#define RESET_BUFFER_OBJ(mask) ( mask &= ~(_DtAct_BUFFER_OBJ_BIT))
#define RESET_STRING_OBJ(mask) ( mask &= ~(_DtAct_STRING_OBJ_BIT))
#define RESET_DIR_OBJ(mask) ( mask &= ~(_DtAct_DIR_OBJ_BIT))
#define RESET_UNKNOWN_IF_DIR(mask) ( mask &= ~(_DtAct_UNKNOWN_IF_DIR_BIT))
/*
* MsgComponent structure mask bits (shared with Object Data?)
*/
#define _DtAct_TREAT_AS_FILE_BIT (1<<29)
#define _DtAct_MSG_COMP_BITS ( _DtAct_TREAT_AS_FILE_BIT )
#define IS_TREAT_AS_FILE(mask) ( mask & _DtAct_TREAT_AS_FILE_BIT )
#define SET_TREAT_AS_FILE(mask) ( mask |= _DtAct_TREAT_AS_FILE_BIT)
#define RESET_TREAT_AS_FILE(mask) ( mask &= ~(_DtAct_TREAT_AS_FILE_BIT))
/* Keyword defines */
#define NO_KEYWORD -1
#define LOCAL_HOST 0
#define DATA_HOST 1
#define DATABASE_HOST 2
#define ARG 3
#define DISPLAY_HOST 4
#define LABEL 5
#define SESSION_HOST 6
/* Special argNum values */
#define NO_ARG -1
#define ALL_ARGS 0
/*
* ToolTalk base representation type ( tt_argn_rep_type ) values
*/
#define DtACT_TT_REP_UNDEFINED 0
#define DtACT_TT_REP_INT 1
#define DtACT_TT_REP_BUFFER 2
#define DtACT_TT_REP_STRING 3
/*
* Resource name and class for the EXEC-HOST resource.
*/
#define DtEXEC_HOSTS_NAME "executionHosts"
#define DtEXEC_HOSTS_CLASS "ExecutionHosts"
#define DtEXEC_HOSTS_DEFAULT _DtACT_EXEC_HOST_DFLT
/* Flags to force special processing of filenames */
#define _DTAct_TT_VTYPE 1 << 0
#define _DTAct_TT_ARG 1 << 1
/* Structure used to hold the components of a message */
typedef struct {
char *precedingText;
char *prompt;
int keyword;
int argNum;
unsigned long mask; /* replaces isFile, isBuffer, isString boolean */
} MsgComponent;
typedef struct {
MsgComponent *parsedMessage;
int numMsgParts;
char *compiledMessage;
int msgLen;
} parsedMsg;
/******************************************************************************
*
* Structs used during the invocation of an action. Once DtActionInvoke()
* exits, these structs are generally freed.
*
*****************************************************************************/
typedef struct {
/*int winMask; ---> moved into the action mask*/
parsedMsg execString;
parsedMsg termOpts;
char *contextDir;
char *contextHost;
parsedMsg execHosts;
char **execHostArray;
int execHostCount;
} cmdAttr;
typedef struct {
DtShmBoson map_action;
} mapAttr;
typedef struct {
int tt_class;
int tt_scope;
parsedMsg tt_op;
parsedMsg tt_file; /* must be a single file name */
int *tt_argn_mode;
int mode_count;
parsedMsg *tt_argn_vtype;
int vtype_count;
parsedMsg *tt_argn_value;
int value_count;
int *tt_argn_rep_type; /* INT, STRING, BUFFER or UNDEFINED */
int rep_type_count;
} tt_msgAttr;
#ifdef _DT_ALLOW_DT_MSGS
typedef struct {
parsedMsg service; /* ICCCM service name */
parsedMsg request; /* request name string */
parsedMsg *argn_value;
int value_count;
} dt_reqAttr;
typedef struct {
parsedMsg ngroup; /* ICCCM notification group */
parsedMsg notify; /* notification to be sent */
parsedMsg *argn_value;
int value_count;
} dt_notifyAttr;
#endif /* _DT_ALLOW_DT_MSGS */
typedef struct {
DtShmBoson action; /* Might just use a char * here? */
DtDbPathId file_name_id; /* id of file wherein the action is defined */
char *label; /* localizable action label string */
char *description;
DtShmBoson *arg_types;
int type_count;
int arg_count; /* Number of arguments accepted by the action */
unsigned long mask; /* action mask -- class/type/arg info */
union { /* attributes for the different action kinds */
cmdAttr cmd;
mapAttr map;
tt_msgAttr tt_msg;
#ifdef _DT_ALLOW_DT_MSGS
dt_reqAttr dt_req;
dt_notifyAttr dt_notify;
#endif /* _DT_ALLOW_DT_MSGS */
} u;
} Action, *ActionPtr; /* new action structure and pointer */
/* Structure used to hold each of the object components */
typedef struct {
char * origFilename;
char * baseFilename;
char * origHostname;
int hostIndex;
int dirIndex;
void * bp; /* pointer to original buffer -- tmp files only */
int sizebp; /* size of original buf -- for tmp files only */
} fileAttr;
typedef struct {
char * string;
} stringAttr;
typedef struct {
int size;
void *bp;
} bufferAttr;
typedef struct {
DtShmBoson type;
unsigned long mask;
union {
fileAttr file;
stringAttr string;
bufferAttr buffer;
} u;
} ObjectData;
/*
* Structure attached to the button callbacks in the
* dialog used to collect missing parameters.
*
*/
typedef struct {
char *actionName;
int objOffset;
int objsUsed;
int numObjects;
ObjectData *objects;
int numPromptInputs;
char **promptInputs;
int numHostNames;
char **hostNames;
int numDirNames;
char **dirNames;
char *termOpts;
char *cwdHost;
char *cwdDir;
ActionPtr clonedAction;
unsigned long mask;
char *badHostList;
char *currentHost;
int hostIndex;
char *execHost;
DtActionInvocationID invocId;
unsigned long childId;
} ActionRequest;
/******************************************************************************
*
* Structs used to maintain information on invoked actions until they
* exit. A few select elements of the ActionRequest and Action structs
* will be copied into these strcuts.
*
*****************************************************************************/
/******************************************************************************
******************************************************************************
**
** Major data-structure diagram for the DtAction invocation layer:
**
** _DtActInvRec <=== _DtActInvRecArray[ actInvRecArraySize ]
** ------------------
** | info per |
** | DtActionInvoke |
** |----------------|
** | numChildren |
** |----------------|
** | childRecs[] | ===> _DtActChildRec
** ------------------ ------------------
** | info per |
** | child request |
** |----------------|
** | *request | ===> ActionRequest
** ------------------ ------------------
** | info on users |
** | action request |
** |----------------|
** Action <=== | *clonedAction |
** ------------------ ------------------
** |info on matching|
** | actionDB entry |
** |----------------|
** | cmd/map/tt/dt |
** | attributes of |
** | resulting msg |
** ------------------
**
** "ActionRequest" and "Action" were present in VUE 3.0, and have a
** scratch-pad like function within DtActionInvoke() to get actions
** started. They are not good long-term retainers of information.
** Action and ActionRequest are in fact freed when DtActionInvoke()
** exits.
**
** "_DtActInvRec" and "_DtActChildRec" have been introduced to retain
** information for the entire life of the actions. Some of the
** information from ActionRequest and Action will be copied (mirrored)
** up to these structures.
**
******************************************************************************
*****************************************************************************/
/******************************************************************************
*
* Child Status Macro Definitions -- These values are used in
* the status word of the _DtActChildRec child record.
*
* ****** IMPORTANT NOTE *** IMPORTANT NOTE *** IMPORTANT NOTE ******
*
* The _DtActCHILD_ macros are also used in cde1/dtexec/Main.c
* in the _DtActDtexecDone(Request) message, so in effect they
* are also protocol constants that should *never* be changed.
* If changed, libDtSvc and dtexec may mis-communicate status.
*
*****************************************************************************/
#define _DtActCHILD_UNKNOWN (1<<0) /* 1 - child status unknown */
#define _DtActCHILD_PENDING_START (1<<1) /* 2 - child start pending */
#define _DtActCHILD_ALIVE_UNKNOWN (1<<2) /* 4 - child alive but unknown*/
#define _DtActCHILD_ALIVE (1<<3) /* 8 - child alive and well */
#define _DtActCHILD_DONE (1<<4) /* 16 - child done */
#define _DtActCHILD_FAILED (1<<5) /* 32 - child failed */
#define _DtActCHILD_CANCELED (1<<6) /* 64 - child canceled */
#define _DtActCHILD_DONE_BITS ( (_DtActCHILD_DONE) | \
(_DtActCHILD_FAILED) | \
(_DtActCHILD_CANCELED) )
/*** IMPORTANT NOTE ABOVE *** IMPORTANT NOTE ABOVE *** IMPORTANT NOTE ABOVE ***/
#define ARE_CHILDREN_DONE(mask) ( (mask) & _DtActCHILD_DONE_BITS )
#define IS_CHILD_UNKNOWN(mask) ( (mask) == _DtActCHILD_UNKNOWN )
#define IS_CHILD_PENDING_START(mask) ( (mask) & _DtActCHILD_PENDING_START )
#define IS_CHILD_DONE(mask) ( (mask) & _DtActCHILD_DONE)
#define IS_CHILD_FAILED(mask) ( (mask) & _DtActCHILD_FAILED)
#define IS_CHILD_CANCELED(mask) ( (mask) & _DtActCHILD_CANCELED)
#define IS_CHILD_ALIVE(mask) ( (mask) & _DtActCHILD_ALIVE)
#define IS_CHILD_ALIVE_UNKOWN(mask) ( (mask) & _DtActCHILD_ALIVE_UNKNOWN)
/******************************************************************************
*
* Information per child of DtActionInvoke()
*
*****************************************************************************/
/*
* Structure useed to map returnable arguments to the child argument list.
*/
typedef struct {
int argN; /* Nth returned value (0 based for tooltalk) */
int argIdx; /* Nth child argument */
} _DtActArgMap;
typedef struct {
unsigned long childId; /* serial # with DtActInvId */
unsigned long childState; /* child state */
/*
* Information cloned from "ActionRequest *req"
*/
int numObjects; /* number of child args */
_DtActArgMap *argMap; /* map of returnable args to chd args */
/*
* Information cloned from "ActionPtr clonedAction"
*/
unsigned long mask; /* action type - IS_xxx() */
/* a list of tmp file names 5/11/94 --tomg */
union {
struct { /* COMMAND elements */
char *TTProcId; /* TT procID handle to child */
Tt_message reqMessage; /* Initiator TT Request */
Tt_pattern magic_cookie; /* dtexec to libDtSvc cookie */
} cmd;
struct { /* TT_MSG elements */
char *TTProcId; /* TT procID handle to child */
Tt_message reqMessage; /* Initiator TT Request */
int isTtMedia; /* handled by ttmedia_load ? */
Tttk_op TtMediaOp; /* if ttmedia_load, the op */
Tt_pattern *subConPats; /* for subcontract_manage */
} tt;
} u;
} _DtActChildRecT;
/******************************************************************************
*
* Invocation Status Macro Definitions -- These values are used in
* the state word of the _DtActInvRec invocation record.
*
*****************************************************************************/
#define _DtActINV_UNKNOWN 0 /* unknown invocation status */
#define _DtActINV_ERROR (1<<0) /* invocation error detected */
#define _DtActINV_CANCEL (1<<1) /* trying to cancel invocation*/
#define _DtActINV_PENDING (1<<2) /* invocation pending */
#define _DtActINV_WORKING (1<<3) /* invocation in process */
#define _DtActINV_DONE (1<<4) /* invocation step done */
#define _DtActINV_COMPLETE (1<<5) /* invocation steps all done */
#define _DtActINV_CB_CALLED (1<<6) /* invocation callback called */
#define _DtActINV_ID_RETURNED (1<<7) /* invocation id has returned */
#define _DtActINV_CMD_QUEUED (1<<8) /* command has been queued */
#define _DtActINV_INDICATOR_ON (1<<9) /* busy indicator active bit */
#define SET_INV_UNKNOWN(mask) (mask = 0)
#define SET_INV_ERROR(mask) (mask |= _DtActINV_ERROR)
#define SET_INV_CANCEL(mask) (mask |= _DtActINV_CANCEL)
#define SET_INV_PENDING(mask) (mask |= _DtActINV_PENDING)
#define SET_INV_WORKING(mask) (mask |= _DtActINV_WORKING)
#define SET_INV_DONE(mask) (mask |= _DtActINV_DONE)
#define SET_INV_COMPLETE(mask) (mask |= _DtActINV_COMPLETE)
#define SET_INV_CB_CALLED(mask) (mask |= _DtActINV_CB_CALLED)
#define SET_INV_ID_RETURNED(mask) (mask |= _DtActINV_ID_RETURNED)
#define SET_INV_CMD_QUEUED(mask) (mask |= _DtActINV_CMD_QUEUED)
#define SET_INV_INDICATOR_ON(mask) (mask |= _DtActINV_INDICATOR_ON)
#define RESET_INV_ERROR(mask) (mask &= ~(_DtActINV_ERROR))
#define RESET_INV_CANCEL(mask) (mask &= ~(_DtActINV_CANCEL))
#define RESET_INV_PENDING(mask) (mask &= ~(_DtActINV_PENDING))
#define RESET_INV_WORKING(mask) (mask &= ~(_DtActINV_WORKING))
#define RESET_INV_COMPLETE(mask) (mask &= ~(_DtActINV_COMPLETE))
#define RESET_INV_DONE(mask) (mask &= ~(_DtActINV_DONE))
#define RESET_INV_CB_CALLED(mask) (mask &= ~(_DtActINV_CB_CALLED))
#define RESET_INV_ID_RETURNED(mask) (mask &= ~(_DtActINV_ID_RETURNED))
#define RESET_INV_CMD_QUEUED(mask) (mask &= ~(_DtActINV_CMD_QUEUED))
#define RESET_INV_INDICATOR_ON(mask) (mask &= ~(_DtActINV_INDICATOR_ON))
#define IS_INV_FINISHED(mask) ( !((mask) & _DtActINV_CMD_QUEUED) \
&& ((mask) & (_DtActINV_COMPLETE \
| _DtActINV_CANCEL)) )
#define IS_INV_UNKNOWN(mask) ( (mask) == _DtActINV_UNKNOWN )
#define IS_INV_ERROR(mask) ((mask) & _DtActINV_ERROR )
#define IS_INV_CANCEL(mask) ((mask) & _DtActINV_CANCEL )
#define IS_INV_PENDING(mask) ((mask) & _DtActINV_PENDING )
#define IS_INV_WORKING(mask) ((mask) & _DtActINV_WORKING )
#define IS_INV_DONE(mask) ((mask) & _DtActINV_DONE )
#define IS_INV_COMPLETE(mask) ((mask) & _DtActINV_COMPLETE )
#define IS_INV_CB_CALLED(mask) ((mask) & _DtActINV_CB_CALLED )
#define IS_INV_ID_RETURNED(mask) ((mask) & _DtActINV_ID_RETURNED )
#define IS_INV_CMD_QUEUED(mask) ((mask) & _DtActINV_CMD_QUEUED )
#define IS_INV_INDICATOR_ON(mask) ((mask) & _DtActINV_INDICATOR_ON )
#define CALL_INV_CB(mask) ((IS_INV_FINISHED(mask)) && \
(IS_INV_ID_RETURNED(mask)) && \
!(IS_INV_CB_CALLED(mask)))
/******************************************************************************
*
* Information per DtActionInvoke()
*
* Note: For TT_MSG(NOTICE)'s during CDE 1.0, this struct will disappear
* immediately after the NOTICEs are sent.
*
*****************************************************************************/
typedef struct {
unsigned long mask; /* encodes object class and writable flag */
int size; /* original size (buffers only) */
char *type; /* original type (buffers only) */
char *name; /* encodes (tmp) file name associated with the
object (if any) */
} _DtActArgInfo;
typedef struct {
DtActionStatus userStatus;
DtActionArg *newArgp;
int newArgc;
} _DtActUpdateCache;
typedef struct _DtActInvRec {
unsigned long state; /* invocation state */
DtActionInvocationID id; /* identifying invocation ID */
Widget w; /* users widget id */
DtActionCallbackProc cb; /* users callback */
XtPointer client_data; /* users client data for cb */
_DtActArgInfo *info; /* template w/ .argClass info */
int ac; /* original # of arguments */
int numChildren; /* number of childRec's. */
_DtActChildRecT **childRec; /* array of child Rec's */
int cachedUploadCnt;/* cached callback updates */
_DtActUpdateCache *cachedUploads; /* data for */
} _DtActInvRecT;
/******************************************************************************
*
* Structs for dialogs/prompts
*
*****************************************************************************/
/* Structure used to hold a prompt string destined for a dialog */
typedef struct {
int argIndex;
char *prompt;
} PromptEntry;
/* Structure used to contain prompt dialog information */
typedef struct {
int argIndex;
Widget promptWidget;
} DialogPromptEntry;
typedef struct {
ActionRequest * request;
Widget topLevel;
Widget associatedWidget;
int numPrompts;
DialogPromptEntry * prompts;
} PromptDialog;
/* Structure used to contain abort/continue dialog information */
typedef struct {
ActionRequest * request;
Widget topLevel;
Widget associatedWidget;
int numPrompts;
PromptEntry * prompts;
} ContinueDialog;
/* Structure passed to request passed/failed callbacks */
typedef struct {
Widget associatedWidget;
char *actionLabel;
int offset;
ActionPtr actionPtr; /* Ptr to the action that
was invoked. */
ActionRequest *requestPtr;
DtActionInvocationID actInvId; /* A standard invocation id */
unsigned long childId; /* An id to further identify
children of actInvId */
} CallbackData;
/******************************************************************************
*
* Private External Function Declarations -- not for public consumption
*
******************************************************************************/
extern void _DtFreeActionStruct( ActionPtr action) ;
#endif /* _ActionP_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/* $XConsortium: ActionUtilP.h /main/3 1995/10/26 15:01:19 rswiston $ */
/************************************<+>*************************************
****************************************************************************
**
** File: ActionUtilP.h
**
** Project: DT
**
** Description: Private include file for the Action Library Utilities.
**
**
** (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.
****************************************************************************
************************************<+>*************************************/
#ifndef _ActionUtilP_h
#define _ActionUtilP_h
#include <X11/Intrinsic.h> /* for Display struct definition */
#include "ActionP.h"
/*****************************************************************************
*
* Macro to protect against sending a NULL pointer to certain
* library functions (i.e. sprintf, strlen, ...) with on some
* systems choke on a NULL pointer.
*
****************************************************************************/
#define _DtActNULL_GUARD(s) ((s) ? (s) : "")
/******************************************************************************
External Utility Function Declarations
These functions are for internal use and are not part of the
public Action API. Each of the following functions returns a
newly allocated version of the desired string. It is up to the
caller to free the strings obtained.
******************************************************************************/
extern char *_DtBasename(const char *s);
extern char *_DtDirname(const char *s);
extern char *_DtPathname(const char *s);
extern char *_DtHostString(const char *s);
extern char *_DtGetSessionHostName( void );
extern char *_DtGetDisplayHostName( Display *d);
extern char *_DtGetLocalHostName( void );
extern char *_DtGetExecHostsDefault (void);
extern char *_DtGetActionIconDefault (void);
extern char *_DtGetDtTmpDir(void);
extern char *_DtActGenerateTmpFile(char *dir,
char *format,
mode_t mode,
int *fd );
extern int _DtIsSameHost( const char *host1, const char *host2 );
extern void _DtRemoveTrailingBlanksInPlace(char **s);
extern int _DtExecuteAccess(const char *path);
extern DtActionInvocationID _DtActAllocID();
extern _DtActInvRecT *_DtActAllocInvRec();
extern _DtActChildRecT *_DtActAllocChildRec( _DtActInvRecT *recp );
extern int _DtActDeleteInvRec( DtActionInvocationID id);
extern _DtActInvRecT *_DtActFindInvRec( DtActionInvocationID id);
extern _DtActChildRecT *_DtActFindChildRec(
DtActionInvocationID id,
unsigned long childId);
extern unsigned long _DtActEvalChildren(DtActionInvocationID id);
extern void _DtActExecutionLeafNodeCleanup(
DtActionInvocationID id,
DtActionArg *newArgp,
int newArgc,
int respectQuitBlock);
extern DtActionArg *_DtActMallocEmptyArgArray(int ac);
extern void _DtActFreeArgArray( DtActionArg *argp, int ac );
extern void *_DtActReadTmpFileToBuffer (
char *fname,
int *sizep);
extern int _DtActGetCmdReturnArgs (
DtActionInvocationID invId,
_DtActChildRecT *childp,
DtActionArg **aargv );
/******************************************************************************/
#endif /* _ActionUtilP_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,177 @@
/* $XConsortium: CmdInv.h /main/6 1996/01/23 10:41:03 barstow $ */
/***************************************************************************
*
* File: CmdInv.h
* Description: Public header for the command invocation system.
* Language: C
*
** (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.
***************************************************************************/
#ifndef _CmdInv_h
#define _CmdInv_h
#include <X11/Xlib.h>
#include <Dt/Message.h>
#include <Dt/Spc.h>
/******************************************************************************
*
* DtCmdInvExecuteProc - This type is is used to define the parameters
* needed in the callback functions for success and failure notification
* of a Command Invoker execution call.
*
*****************************************************************************/
typedef void (*DtCmdInvExecuteProc) (
char *message, /* NULL if the request is successful.
* Otherwise an error message. */
void *client_data
);
/******************************************************************************
*
* Function: void _DtInitializeCommandInvoker (
* Display *display,
* char *toolClass,
* char *applicationClass,
* DtSvcReceiveProc reloadDBHandler,
* XtAppContext appContext)
*
* Parameters:
*
* display - The X server display connection.
*
* toolClass - The BMS tool class of the client.
*
* applicationClass - The application class of the client (see
* XtInitialize). This is needed to add the
* Command Invoker's resources to the client's
* resources.
*
* reloadDBHandler - Function to be called if a RELOAD-TYPES-DB
* request is made. If the client does not read
* DT action and/or filetype databases, NULL must
* be used.
*
* appContext - The client's application context. Must be NULL
* if the client does not use an application
* context.
*
* Purpose:
*
* This function allows a client to internalize the functionality
* of the DT "Command Invoker". By using this library and the
* Action Library, requests for the Command Invoker will be done
* internally instead of sending a request to a separate Command
* Invoker process.
*
* For local execution, the "fork" and "execvp" system calls are
* used. For remote execution, the "SPCD" is used.
*
*****************************************************************************/
extern void
_DtInitializeCommandInvoker(
Display *display,
char *toolClass,
char *applicationClass,
DtSvcReceiveProc reloadDBHandler,
XtAppContext appContext);
/******************************************************************************
*
* Function: void _DtCommandInvokerExecute (
* char *request_name,
* char *context_host,
* char *context_dir,
* char *context_file,
* char *exec_parameters,
* char *exec_host,
* char *exec_string,
* DtCmdInvExecProc success_proc,
* void *success_data,
* DtCmdInvExecProc failure_proc,
* void *failure_data)
*
* Parameters:
*
* request_name - The request name (defined in "CommandM.h").
*
* context_host - Name of the host where request is executed from. If
* NULL, the "exec_host" parameter is used. Note: this
* should not be confused with execution host, described
* below.
*
* context_dir - Directory where the request should be executed. If
* NULL, the HOME directory is used.
*
* context_file - Not currently used by the Command Invoker.
*
* exec_parameters - Command Invoker execution parameters. See External
* Specification for more information.
* If set to NULL, "-" is used.
*
* exec_host - Name of the host where the request is executed.
*
* exec_string - The command line to execute.
*
* success_proc - The function to be invoked if the request is
* successfully executed.
*
* success_data - Client data for successful execution.
*
* failure_proc - The function to be invoked if an attempt to exeucte
* the request fails.
*
* failure_data - Client data for unsuccessful execution.
*
* Purpose:
*
* This function allows a client to use the DT "Command Invoker"
* Library for its' process execution. This function is intended
* for processes which do not use the Action Library.
*
* For local execution, the "fork" and "execvp" system calls are
* used. For remote execution, the "SPCD" is used.
*
* Notes:
*
* This function must be preceeded by a call to
* "_DtInitializeCommandInvoker".
*
*****************************************************************************/
extern void
_DtCommandInvokerExecute(
char *request_name,
char *context_host,
char *context_dir,
char *context_file,
char *exec_parameters,
char *exec_host,
char *exec_string,
DtCmdInvExecuteProc success_proc,
void *success_data,
DtCmdInvExecuteProc failure_proc,
void *failure_data);
extern SPC_Channel_Ptr _DtSPCOpen( char *hostname,
int iomode,
char *errorMessage); /* MODIFIED */
extern int _DtSPCSpawn(
char *path,
char *context,
char **args,
char **env,
SPC_Channel_Ptr chan,
char *execHost,
char *contextHost,
char *contextDir,
char *errorMessage); /* MODIFIED */
#endif /* _CmdInv_h */

View File

@@ -0,0 +1,184 @@
/* $TOG: CmdInvP.h /main/5 1998/07/30 12:10:30 mgreess $ */
/***************************************************************************
*
* File: CmdInvP.h
* Description: Command execution system private externs and includes
* Language: C
*
** (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.
***************************************************************************/
#ifndef _CmdInvP_h
#define _CmdInvP_h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h> /* MAXPATHNAMELEN */
#include <X11/Intrinsic.h>
#include <Dt/DtP.h>
#include <Dt/DtNlUtils.h>
#include <Dt/Message.h>
#include <bms/SbEvent.h>
#include <bms/XeUserMsg.h>
#include <Dt/Spc.h>
#include <Dt/CmdInv.h>
#include <Dt/ActionP.h>
#include <Dt/Connect.h>
#ifndef CDE_INSTALLATION_TOP
#define CDE_INSTALLATION_TOP "/opt/dt"
#endif
/*
* Resource names and classes for the Command Invoker.
*/
#define DtLOCAL_TERMINAL_NAME "localTerminal"
#define DtLOCAL_TERMINAL_CLASS "LocalTerminal"
#define DtREMOTE_TERMINALS_NAME "remoteTerminals"
#define DtREMOTE_TERMINALS_CLASS "RemoteTerminals"
#define DtWAIT_TIME_NAME "waitTime"
#define DtWAIT_TIME_CLASS "WaitTime"
#define DtDTEXEC_PATH_NAME "dtexecPath"
#define DtDTEXEC_PATH_CLASS "DtexecPath"
#define DtEXECUTION_HOST_LOGGING_NAME "executionHostLogging"
#define DtEXECUTION_HOST_LOGGING_CLASS "ExecutionHostLogging"
/*
* Structure for saving the "state" of a remote request that is
* queued while waiting for a remote subprocess to terminate.
*/
typedef struct _Cmd_RequestQueue {
SPC_Channel_Ptr channel;
char *context;
char *exec_host;
char *exec_string;
char **argv;
int winType;
unsigned long request_num;
DtSvcMsgContext replyContext;
DtCmdInvExecuteProc success_proc;
void *success_data;
DtCmdInvExecuteProc failure_proc;
void *failure_data;
struct _Cmd_RequestQueue *next;
} Cmd_RequestQueue;
/*
* Command invocation resources.
*/
typedef struct {
char *localTerminal;
char **remoteHosts;
char **remoteTerminals;
int waitTime;
char *dtexecPath;
Boolean executionHostLogging;
} Cmd_Resources;
/*
* Command invocation global variables.
*/
typedef struct {
Boolean terminal_ok;
Boolean subprocess_ok;
XtAppContext app_context;
char **path_list;
char *error_directory_name_map;
char *error_subprocess;
char *error_terminal;
} Cmd_Globals;
/*
* Defaults for the Resources.
*/
#define DtWAIT_TIME_DEFAULT 3 /* In seconds. */
#define DtTERMINAL_DEFAULT "dtterm"
#define DtCMD_INV_SUB_PROCESS CDE_INSTALLATION_TOP "/bin/dtexec"
/*
* Temporary buffer size.
*/
#define MAX_BUF_SIZE 1024
/*
* Window types:
*/
#define NO_STDIO 0
#define TERMINAL 1
#define PERM_TERMINAL 2
/*
* Command execution return status:
*/
#define _CMD_EXECUTE_SUCCESS 1
#define _CMD_EXECUTE_FAILURE 2
#define _CMD_EXECUTE_QUEUED 3
#define _CMD_EXECUTE_FATAL 4
/*
* External declarations for the global Command Invoker variables.
*/
extern Cmd_Resources cmd_Resources;
extern Cmd_Globals cmd_Globals;
/*
******* Public Function Declarations for CmdSpc.c *******
*/
extern SbInputId _DtCmdSPCAddInputHandler (
int fd,
SbInputCallbackProc proc,
void *data);
extern SbInputId _DtCmdSPCAddExceptionHandler (
int fd,
SbInputCallbackProc proc,
void *data);
extern void _DtCmdLogErrorMessage(
char *message) ;
/*
******* Public Function Declarations for CmdProcess.c *******
*/
extern void _DtCmdCreateTerminalCommand(
char **theCommand,
int windowType,
char *execString,
char *execParms,
char *execHost,
char *procId,
char *tmpFiles) ;
extern Boolean _DtCmdCheckForExecutable(
char *fileName) ;
extern Boolean _DtCmdValidDir(
char *clientHost,
char *contextDir,
char *contextHost) ;
extern void _DtCmdGetResources(
Display *display);
/*
******* Public Function Declarations for CmdUtilityP.c *******
*/
extern void _DtCmdBuildPathList( void ) ;
/******** End Public Function Declarations ********/
#endif /* _CmdInvP_h */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,792 @@
/* $TOG: CmdProcess.c /main/8 1998/04/09 17:47:13 mgreess $ */
/***************************************************************************
*
* File: CmdProcess.c
* Description: Miscellaneous functions for the command execution system
* Language: C
*
** (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 "CmdInvP.h"
#include <X11/Xproto.h>
#include <Dt/CommandM.h>
#include <Dt/DtNlUtils.h>
#include <Dt/ActionUtilP.h>
#include "myassertP.h"
#if defined(sun) || defined(USL) || defined(__uxp__)
#include <limits.h>
#endif
#if defined(__hp_osf) || defined (__osf__)
#include <sys/access.h>
#else
#if defined(__hpux)
#include <sys/getaccess.h>
#endif
#endif
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <Tt/tt_c.h>
/*
* Global variables:
*/
Cmd_Resources cmd_Resources = { 0 };
Cmd_Globals cmd_Globals = { 0 };
/******** Static Function Declarations ********/
static char *_GetRemoteTerminalsResource (
Display *display,
char *appClass,
char *appName);
static void GetRemoteTerminalsResource (
Display *display,
char *appClass,
char *appName);
static void GetLocalTerminalResource (
Display *display,
char *appClass,
char *appName);
static void GetWaitTimeResource (
Display *display,
char *appClass,
char *appName);
static void GetDtexecPath (
Display *display,
char *appClass,
char *appName);
static void GetExecutionHostLoggingResource (
Display *display,
char *appClass,
char *appName);
static char *GetRemoteTerminal(
char *host);
/******** End Static Function Declarations ********/
/******************************************************************************
*
* _GetRemoteTerminalsResource - gets the value of the "remoteTerminals"
* resource.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* RETURNS: a pointer to the "remoteTerminals" resource or NULL if the
* resource is not defined.
*
* NOTES: The space for the returned string is "malloc'ed". The calling
* function should free the string.
*
*****************************************************************************/
static char
*_GetRemoteTerminalsResource (
Display *display,
char *appClass,
char *appName)
{
XrmValue resource_value;
XrmDatabase db;
char *rep_type;
char *name;
char *class;
char *terminals = NULL;
name = XtMalloc (strlen (DtREMOTE_TERMINALS_NAME) + strlen (appName) + 4);
sprintf (name, "%s*%s", appName, DtREMOTE_TERMINALS_NAME);
class = XtMalloc (strlen (DtREMOTE_TERMINALS_CLASS) + strlen (appClass) + 4);
sprintf (class, "%s*%s", appClass, DtREMOTE_TERMINALS_CLASS);
db = XtDatabase (display);
if (XrmGetResource (db, name, class, &rep_type, &resource_value))
terminals = (char *) XtNewString (resource_value.addr);
XtFree (name);
XtFree (class);
return (terminals);
}
/******************************************************************************
*
* GetRemoteTerminalsResource - initializes the "remoteTerminals" resource.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* MODIFIED:
*
* char *cmd_Resources.remoteTerminals; - Set to the list of remote
* terminals.
*
* char *cmd_Resources.remoteHosts; - Set to the list of remote hosts..
*
*****************************************************************************/
static void
GetRemoteTerminalsResource (
Display *display,
char *appClass,
char *appName)
{
int num, j;
char *terminals;
char *pch, *host;
if ((terminals = _GetRemoteTerminalsResource (display, appClass, appName))
== NULL) {
/*
* The resource was not specified, and no defaults are set.
*/
cmd_Resources.remoteHosts = (char **) NULL;
cmd_Resources.remoteTerminals = (char **) NULL;
return;
}
/*
* Find out how many terminals are specified by counting the number of
* colons.
*/
for (pch=terminals, num=0; pch != NULL ; ) {
if ((pch = DtStrchr (pch, ':')) != NULL) {
/*
* Move past the ':'.
*/
pch++;
num++;
}
}
if (num == 0) {
/*
* No "host:/terminal" pairs were found.
*/
cmd_Resources.remoteHosts = (char **) NULL;
cmd_Resources.remoteTerminals = (char **) NULL;
return;
}
/*
* Create space for the pointers to the hosts and terminals and
* make room for a NULL terminator.
*
* Note that the host names and terminal names are "vectorized" in
* place by replacing the ':' and ',' characters with '\0'.
*/
cmd_Resources.remoteHosts = (char **) XtMalloc (num * sizeof(char *));
cmd_Resources.remoteTerminals = (char **) XtMalloc (num * sizeof(char *));
for (pch=terminals, j=0; j < num && pch != NULL && *pch != '\0'; j++)
{
host = pch;
if ((pch = DtStrchr (pch, ':')) == NULL)
break;
/*
* Null terminate the host and then move past the ':'.
*/
*pch = '\0';
pch++;
if (*pch == '\0')
/*
* Found a host but nothing followed it.
*/
break;
cmd_Resources.remoteHosts[j] = host;
cmd_Resources.remoteTerminals[j] = pch;
/*
* Find the end of this entry and skip past it.
*/
if ((pch = DtStrchr (pch, ',')) == NULL) {
/*
* This is the last pair, advance "j" and break the loop.
*/
j++;
break;
}
/*
* End the terminal name.
*/
*pch = '\0';
pch++;
}
/*
* NULL terminate the arrays.
*/
cmd_Resources.remoteHosts[j] = (char *) NULL;
cmd_Resources.remoteTerminals[j] = (char *) NULL;
}
/******************************************************************************
*
* GetLocalTerminalResource - initializes the "localTerminal resource.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* MODIFIED:
*
* char *cmd_Resources.localTerminal; - Set to the "localTerminal"
* or to DtDEFUALT_TERMINAL.
*
* Boolean cmd_Globals.terminal_ok; - Set to True if "localTerminal"
* is executable and has the correct
* permissions; False otherwise.
*
*****************************************************************************/
static void
GetLocalTerminalResource (
Display *display,
char *appClass,
char *appName)
{
XrmValue resource_value;
char *rep_type;
char *name;
char *class;
XrmDatabase db = XtDatabase (display);
name = XtMalloc (strlen (DtLOCAL_TERMINAL_NAME) + strlen (appName) + 4);
sprintf (name, "%s*%s", appName, DtLOCAL_TERMINAL_NAME);
class = XtMalloc (strlen (DtLOCAL_TERMINAL_CLASS) + strlen (appClass) + 4);
sprintf (class, "%s*%s", appClass, DtLOCAL_TERMINAL_CLASS);
if (XrmGetResource (db, name, class, &rep_type, &resource_value))
cmd_Resources.localTerminal = (char *) XtNewString (resource_value.addr);
else
cmd_Resources.localTerminal = XtNewString (DtTERMINAL_DEFAULT);
/*
* Check to see if the execvp will potentially fail because the
* localTerminal is not accessable or it it is not executable. If not,
* log an error message.
*/
cmd_Globals.terminal_ok = True;
if (!(_DtCmdCheckForExecutable (cmd_Resources.localTerminal))) {
char *errorMessage = XtMalloc(MAX_BUF_SIZE);
cmd_Globals.terminal_ok = False;
if (errorMessage)
{
(void) sprintf (errorMessage,
cmd_Globals.error_terminal,
cmd_Resources.localTerminal);
_DtCmdLogErrorMessage (errorMessage);
XtFree(errorMessage);
}
}
XtFree (name);
XtFree (class);
}
/******************************************************************************
*
* GetWaitTimeResource - initializes the "waitTime" resource.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* MODIFIED:
*
* char *cmd_Resources.waitTime; - Set to the "waitTime" resource
* or "True" by default.
*
*****************************************************************************/
static void
GetWaitTimeResource (
Display *display,
char *appClass,
char *appName)
{
XrmValue resource_value;
char *rep_type;
char *name;
char *class;
XrmDatabase db= XtDatabase (display);
cmd_Resources.waitTime = DtWAIT_TIME_DEFAULT;
name = XtMalloc (strlen (DtWAIT_TIME_NAME) + strlen (appName) + 4);
sprintf (name, "%s*%s", appName, DtWAIT_TIME_NAME);
class = XtMalloc (strlen (DtWAIT_TIME_CLASS) + strlen (appClass) + 4);
sprintf (class, "%s*%s", appClass, DtWAIT_TIME_CLASS);
if (XrmGetResource (db, name, class, &rep_type, &resource_value)) {
cmd_Resources.waitTime = atoi (resource_value.addr);
if (cmd_Resources.waitTime < 0)
cmd_Resources.waitTime = DtWAIT_TIME_DEFAULT;
}
XtFree (name);
XtFree (class);
}
/******************************************************************************
*
* GetDtexecPath - initializes the "dtexecPath" resource.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* MODIFIED:
*
* char *cmd_Resources.dtexecPath; - Set to the "dtexecPath" resource
* or to DtCMD_INV_SUB_PROCESS.
*
*****************************************************************************/
static void
GetDtexecPath (
Display *display,
char *appClass,
char *appName)
{
XrmValue resource_value;
char *rep_type;
char errorMessage [MAX_BUF_SIZE];
char *name;
char *class;
XrmDatabase db = XtDatabase (display);
name = XtMalloc (strlen (DtDTEXEC_PATH_NAME) + strlen (appName) + 4);
sprintf (name, "%s*%s", appName, DtDTEXEC_PATH_NAME);
class = XtMalloc (strlen (DtDTEXEC_PATH_CLASS) + strlen (appClass) + 4);
sprintf (class, "%s*%s", appClass, DtDTEXEC_PATH_CLASS);
if (XrmGetResource (db, name, class, &rep_type, &resource_value))
cmd_Resources.dtexecPath = (char *) XtNewString (resource_value.addr);
else
cmd_Resources.dtexecPath = XtNewString (DtCMD_INV_SUB_PROCESS);
/*
* Check to see if the execvp will potentially fail because the
* subprocess is not accessable or it it is not executable. If not,
* log an error message.
*/
cmd_Globals.subprocess_ok = True;
if (!(_DtCmdCheckForExecutable (cmd_Resources.dtexecPath))) {
char *errorMessage = XtMalloc(MAX_BUF_SIZE);
cmd_Globals.subprocess_ok = False;
if (errorMessage)
{
(void) sprintf (errorMessage,
cmd_Globals.error_subprocess,
cmd_Resources.dtexecPath);
_DtCmdLogErrorMessage (errorMessage);
XtFree(errorMessage);
}
}
XtFree (name);
XtFree (class);
}
/******************************************************************************
*
* GetExecutionHostLoggingResources - initializes the "executionHostLogging"
*
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
* char *appName; The client's application name.
*
* MODIFIED:
*
* char *cmd_Resources.executionHostLogging;
*
* - Set to the "executionHostLogging" resource or "False" by default.
*
*****************************************************************************/
static void
GetExecutionHostLoggingResource (
Display *display,
char *appClass,
char *appName)
{
XrmValue resource_value;
char *rep_type;
char *name;
char *class;
XrmDatabase db= XtDatabase (display);
cmd_Resources.executionHostLogging = False;
name = XtMalloc (strlen (DtEXECUTION_HOST_LOGGING_NAME) +
strlen (appName) + 4);
sprintf (name, "%s*%s", appName, DtEXECUTION_HOST_LOGGING_NAME);
class = XtMalloc (strlen (DtEXECUTION_HOST_LOGGING_CLASS) +
strlen (appClass) + 4);
sprintf (class, "%s*%s", appClass, DtEXECUTION_HOST_LOGGING_CLASS);
if (XrmGetResource (db, name, class, &rep_type, &resource_value)) {
if (((strcmp (resource_value.addr, "True")) == 0) ||
((strcmp (resource_value.addr, "true")) == 0) ||
((strcmp (resource_value.addr, "TRUE")) == 0))
cmd_Resources.executionHostLogging = True;
else if (((strcmp (resource_value.addr, "False")) == 0) ||
((strcmp (resource_value.addr, "false")) == 0) ||
((strcmp (resource_value.addr, "FALSE")) == 0))
cmd_Resources.executionHostLogging = False;
}
XtFree (name);
XtFree (class);
}
/******************************************************************************
*
* GetRemoteTerminal - takes a host name "host" and searches the list of remote
* host:terminal pairs for "host" and if found, returns the corresponding
* terminal emulator.
*
* PARAMETERS:
*
* char *host; - Name of the host to use as the key to find
* the terminal emulator name.
*
* RETURNS: If "host" is found, the corresponding terminal emulator is
* returned, otherwise "NULL" is returned.
*
*****************************************************************************/
static char *
GetRemoteTerminal(
char *host )
{
int i;
if (cmd_Resources.remoteHosts == NULL)
return (NULL);
for (i=0; cmd_Resources.remoteHosts[i] != NULL; i++) {
if ((strcmp (host, cmd_Resources.remoteHosts[i])) == 0)
return (cmd_Resources.remoteTerminals[i]);
}
return (NULL);
}
/******************************************************************************
*
* _DtCmdCreateTerminalCommand - takes a windowType, execString
* and execParms and creates an appropriate command to execute.
*
* Note that if valid execParms are found, they are simply added
* to the execution string, before the "-e" option.
*
* PARAMETERS:
*
* char **theCommand; - The command line to be expanded and returned.
* int windowType; - The request number (window number).
* char *execString; - The execution string to be expanded.
* char *execParms; - The execution parameters.
* char *procId - tooltalk procId for dtexec
* char *tmpFiles - string containing tmp file args for dtexec
*
* MODIFIED:
*
* char ** theCommand; - Contains the completed execution string.
*
*****************************************************************************/
void
_DtCmdCreateTerminalCommand(
char **theCommand,
int windowType,
char *execString,
char *execParms,
char *execHost,
char *procId,
char *tmpFiles)
{
char *pGeom = NULL;
char *pName = NULL;
char *pTitle = NULL;
char options[MAX_BUF_SIZE];
char *defaultTerminal;
strcpy(options,execParms);
/*
* Get the name of the terminal emulator to use.
*/
if ((defaultTerminal = GetRemoteTerminal (execHost)) == NULL)
defaultTerminal = cmd_Resources.localTerminal;
/*
* Create space for the expanded command line.
*/
*theCommand = (char *) XtMalloc ( strlen (defaultTerminal)
+ strlen(options)
+ strlen(cmd_Resources.dtexecPath)
+ strlen(" -open ") + 4 /* max waitTime len */
+ strlen(" -ttprocid ") + strlen(_DtActNULL_GUARD(procId))
+ strlen(_DtActNULL_GUARD(tmpFiles))
+ strlen(execString) + 9 /* 2 quotes, "-e", 7 blanks, null */ );
if (windowType == TERMINAL) {
(void) sprintf (*theCommand, "%s %s -e %s -open %d -ttprocid '%s' %s %s",
defaultTerminal, options, cmd_Resources.dtexecPath,
cmd_Resources.waitTime,
_DtActNULL_GUARD(procId),
_DtActNULL_GUARD(tmpFiles),
execString);
}
else {
(void) sprintf (*theCommand, "%s %s -e %s -open -1 -ttprocid '%s' %s %s",
defaultTerminal, options, cmd_Resources.dtexecPath,
_DtActNULL_GUARD(procId),
_DtActNULL_GUARD(tmpFiles),
execString);
}
}
/******************************************************************************
*
* _DtCmdCheckForExecutable - checks "fileName" to see if it is executable
* by the user.
*
* PARAMETERES:
*
* char *fileName; - The name of the file to check.
*
* RETURNS: "True" if the file is access'able && executable, "False" otherwise.
*
*****************************************************************************/
Boolean
_DtCmdCheckForExecutable(
char *fileName )
{
char **ppch;
int access;
/* First check to see if the fileName contains the complete path
* and is access'able.
*/
switch (access = _DtExecuteAccess(fileName))
{
/* execution access allowed for this process */
case 1: return True;
break;
/* file found -- not executable by this process */
case 0: return False;
break;
/* file not found -- yet */
case -1: /* fall through */
default:
break;
}
/* Append fileName to each entry in "cmd_Globals.path_list" and then see
* if that is accessable.
*/
for (ppch = cmd_Globals.path_list; *ppch != NULL; ppch++)
{
char *longName = XtMalloc(MAXPATHLEN);
if (longName)
{
(void) sprintf (longName, "%s/%s", *ppch, fileName);
switch (access = _DtExecuteAccess(longName))
{
/* execution access allowed for this process */
case 1: return True;
break;
/* file found -- not executable by this process */
case 0: return False;
break;
/* file not found -- yet */
case -1: /* fall through */
default:
break;
}
XtFree(longName);
}
}
return (False);
}
/******************************************************************************
*
* _DtCmdValidDir - takes the client host, context directory and a context host
* and checks to see if the directory is valid.
*
* PARAMETERS:
*
* char *clientHost; - Host where the client is running.
*
* char *contextDir; - Directory to "chdir" to.
*
* char *contextHost; - Host where 'contextDir' resides.
*
* NOTES:
*
* If the context directory is NULL, "chdir" is not run and "True" is
* returned.
*
* RETURNS: "True" if "chdir" succeeds and "False" otherwise.
*
*****************************************************************************/
Boolean
_DtCmdValidDir(
char *clientHost,
char *contextDir,
char *contextHost )
{
int retValue = 0;
if (contextDir == NULL)
/*
* Stay in the same directory.
*/
return (True);
if (contextHost == NULL)
/*
* Change to 'contextDir'.
*/
retValue = chdir (contextDir);
else if (_DtIsSameHost (clientHost, contextHost))
/*
* Just change to 'contextDir'.
*/
retValue = chdir (contextDir);
else {
/*
* Need to create a pathname for the directory.
*/
char *netfile;
char *path;
char *errorMessage = XtMalloc(MAX_BUF_SIZE);
/* Old syntax should no longer appear in contextHost/Dir */
myassert( *contextHost != '*' && *contextDir != '*' );
netfile = (char *) tt_host_file_netfile (contextHost, contextDir);
if (tt_pointer_error (netfile) != TT_OK) {
(void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
contextDir, contextHost,
tt_status_message (tt_pointer_error(netfile)));
_DtCmdLogErrorMessage (errorMessage);
return (False);
}
path = (char *) tt_netfile_file (netfile);
tt_free (netfile);
if (tt_pointer_error (path) != TT_OK) {
(void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
contextDir, contextHost,
tt_status_message (tt_pointer_error(path)));
_DtCmdLogErrorMessage (errorMessage);
return (False);
}
retValue = chdir (path);
tt_free (path);
if (errorMessage) XtFree(errorMessage);
}
if (retValue == -1)
return (False);
else
return (True);
}
/******************************************************************************
*
* _DtCmdGetResources - initializes the Command Invoker's resources.
*
* PARAMETERS:
*
* Display *display; The connection to the X server.
*
* char *appClass; The client's application class.
*
*****************************************************************************/
void
_DtCmdGetResources (
Display *display)
{
char *appClass = NULL;
char *appName = NULL;
/*
* Determine the name and class for this client.
*/
XtGetApplicationNameAndClass (display, &appName, &appClass);
GetLocalTerminalResource (display, appClass, appName);
GetRemoteTerminalsResource (display, appClass, appName);
GetWaitTimeResource (display, appClass, appName);
GetDtexecPath (display, appClass, appName);
GetExecutionHostLoggingResource (display, appClass, appName);
}

View File

@@ -0,0 +1,99 @@
/* $XConsortium: CmdSpc.c /main/4 1995/10/26 15:02:34 rswiston $ */
/***************************************************************************
*
* File: CmdSpc.c
* Description: Messaging support for the command execution system.
* Language: C
*
** (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 "CmdInvP.h"
#include <Dt/UserMsg.h>
#include <Dt/CommandM.h>
/******************************************************************************
*
* _DtCmdSPCAddInputHandler - Register the Command Invoker AddInputHandler
*
* PARAMETERS: Those need by a SPC Add Input Handler.
*
* NOTES:
*
* This function is needed by SPC to get a process termination
* callback to get invoked.
*
*****************************************************************************/
SbInputId
_DtCmdSPCAddInputHandler (
int fd,
SbInputCallbackProc proc,
void *data)
{
if (cmd_Globals.app_context == NULL)
return(XtAddInput(fd,
(XtPointer) XtInputReadMask,
proc,
data));
else
return(XtAppAddInput(cmd_Globals.app_context,
fd,
(XtPointer) XtInputReadMask,
proc,
data));
}
/******************************************************************************
*
* _DtCmdSPCAddExceptionHandler - Register the Command Invoker AddExceptionHandler
*
* PARAMETERS: Those need by a SPC Add Exception Input Handler.
*
* NOTES:
*
* This function is needed by SPC to get a process termination
* callback to get invoked.
*
*****************************************************************************/
SbInputId
_DtCmdSPCAddExceptionHandler (
int fd,
SbInputCallbackProc proc,
void *data)
{
if (cmd_Globals.app_context == NULL)
return(XtAddInput(fd,
(XtPointer) XtInputExceptMask,
proc,
data));
else
return(XtAppAddInput(cmd_Globals.app_context,
fd,
(XtPointer) XtInputExceptMask,
proc,
data));
}
/******************************************************************************
*
* _DtCmdLogErrorMessage - write an error message to the default log file.
*
* PARAMETERS:
*
* char *message; - The error message to log.
*
*****************************************************************************/
void
_DtCmdLogErrorMessage(
char *message )
{
_DtSimpleError (DtProgName, DtError, NULL, "%.2000s", message);
}

View File

@@ -0,0 +1,96 @@
/* $XConsortium: CmdUtilityP.c /main/4 1995/10/26 15:02:50 rswiston $ */
/***************************************************************************
*
* File: CmdUtilityP.c
* Description: Private Utility routines for the command invocation system.
* Language: C
*
** (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 "CmdInvP.h"
#include <stdio.h>
#include <sys/param.h>
#ifdef __apollo
#include "/sys5/usr/include/unistd.h"
#else
#include <unistd.h>
#endif
#include <limits.h>
#include <sys/stat.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <Dt/CommandM.h>
/*****************************************************************************
*
* _DtCmdBuildPathList - this functions builds a list of the path names
* that are part of the $PATH environment variable. This is done once
* during initialization and the list is then searched whenever
* a command is going to be executed.
*
* MODIFIED:
*
* char **cmd_Globals.path_list; - Initialized or set to NULL if
* $PATH is undefined
*
*****************************************************************************/
void
_DtCmdBuildPathList( void )
{
int i=0;
char *path;
int indx;
int n=0, pathLen;
char *pend, /* Points to the beginning of a directory */
*pbeg; /* Points to the end of a directory */
/* Get the PATH */
if ((path = (char *) (getenv ("PATH"))) == NULL) {
cmd_Globals.path_list = (char **) NULL;
return;
}
pathLen = strlen(path);
pbeg = path;
while (i < pathLen) {
n++;
cmd_Globals.path_list = (char **) XtRealloc ((char *)cmd_Globals.path_list, n * sizeof (char *));
if ((indx = DtStrcspn (pbeg, ":")) >= pathLen) {
/* At the end of the path */
i = pathLen;
pend = (char *) pbeg + indx;
}
else {
/* Found a ":" */
pend = (char *) pbeg + indx;
i += (pend - pbeg) +1;
}
cmd_Globals.path_list[n-1] = (char *) XtMalloc (((pend - pbeg) + 1) *
sizeof(char));
(void) strncpy (cmd_Globals.path_list[n-1], pbeg, (pend - pbeg));
/* Strncpy does not put a '\0' at the EOS if s2 >= s1 */
cmd_Globals.path_list[n-1][pend-pbeg] = '\0';
/* Move past the ":" */
if (i < pathLen)
pbeg = pend +1;
}
/* May need to NULL terminate cmd_Globals.path_list */
if (n > 0) {
n++;
cmd_Globals.path_list = (char **) XtRealloc ((char *) cmd_Globals.path_list, n * sizeof (char *));
cmd_Globals.path_list [n-1] = (char *) NULL;
}
}

View File

@@ -0,0 +1,304 @@
/*
* +SNOTICE
*
* $XConsortium: DbLoad.c /main/7 1996/08/28 14:38:07 rswiston $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special restrictions in a
* confidential disclosure agreement bertween HP, IBM, Sun, USL, SCO and
* Univel. Do not distribute this document outside HP, IBM, Sun, USL, SCO,
* or Univel wihtout Sun's specific written approval. This documment and all
* copies and derivative works thereof must be returned or destroyed at Sun's
* request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
* +ENOTICE
*/
/* *
* (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 <stdio.h>
#include <sys/types.h>
#ifdef __hpux
#include <ndir.h>
#else
#if defined(sun) || defined(USL) || defined(sco) || defined(__uxp__)
#include <dirent.h>
#else
#include <sys/dir.h>
#endif /* sun || USL */
#endif /* __hpux */
#include <ctype.h>
#include <string.h>
#ifdef NLS16
#include <limits.h>
#endif
#include <sys/stat.h>
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <Dt/DtP.h>
#include <Dt/Connect.h>
#include <Dt/FileUtil.h>
#include <Dt/DtNlUtils.h>
#include <Dt/Action.h>
#include <Dt/ActionDbP.h>
#include <Dt/ActionP.h>
#include <Dt/ActionFind.h>
#include <Dt/DbUtil.h>
#include <Dt/DtPStrings.h>
#include <Dt/Utility.h>
#include <Dt/DtsDb.h>
#include <Dt/Dts.h>
#include "myassertP.h"
#include "DtSvcLock.h"
extern void _DtDtsDCConverter(DtDtsDbField * fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus);
extern void _DtDtsDAConverter(DtDtsDbField * fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus);
extern void _DtDtsSeqReset(void);
extern int _DtDtsNextDCSeq(void);
extern int _DtDtsNextDASeq(void);
int use_in_memory_db = False;
static void
_DtOAConverter(DtDtsDbField * fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus)
{
DtDtsDbDatabase *dc_db;
DtDtsDbDatabase *da_db;
DtDtsDbRecord *dc_rec;
DtDtsDbRecord *da_rec;
DtDtsDbField *fld;
_DtSvcProcessLock();
dc_db = _DtDtsDbGet(DtDTS_DC_NAME);
da_db = _DtDtsDbGet(DtDTS_DA_NAME);
if ( _DtDtsDbGetRecordByName(dc_db,
fields[0].fieldValue) ||
_DtDtsDbGetRecordByName(da_db,
fields[0].fieldValue))
{
_DtSvcProcessUnlock();
return;
}
/*
* Synthesize criteria record -- for this action
*/
dc_rec = _DtDtsDbAddRecord(_DtDtsDbGet(DtDTS_DC_NAME));
dc_rec->recordName = XrmStringToQuark(fields[0].fieldValue);
dc_rec->seq = _DtDtsNextDCSeq();
dc_rec->pathId = (int)pathId;
fld = _DtDtsDbAddField(dc_rec);
fld->fieldName = XrmStringToQuark(DtDTS_NAME_PATTERN);
fld->fieldValue = strdup(fields[0].fieldValue);
fld = _DtDtsDbAddField(dc_rec);
fld->fieldName = XrmStringToQuark(DtDTS_MODE);
fld->fieldValue = strdup("fx");
fld = _DtDtsDbAddField(dc_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DATA_ATTRIBUTES_NAME);
fld->fieldValue = strdup(fields[0].fieldValue);
/*
* Mark the criteria record as synthetic.
*/
fld = _DtDtsDbAddField(dc_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_IS_SYNTHETIC);
fld->fieldValue = strdup("True");
/*
* Synthesize attribute record -- for this action
*/
da_rec = _DtDtsDbAddRecord(_DtDtsDbGet(DtDTS_DA_NAME));
da_rec->recordName = XrmStringToQuark(fields[0].fieldValue);
da_rec->seq = _DtDtsNextDASeq();
da_rec->pathId = (int)pathId;
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_ACTION_LIST);
fld->fieldValue = strdup(fields[0].fieldValue);
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_DATA_HOST);
fld->fieldValue = strdup(hostPrefix);
/*
* Mark the attribute record as synthetic.
*/
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_IS_SYNTHETIC);
fld->fieldValue = strdup("True");
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_IS_ACTION);
fld->fieldValue = strdup("True");
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_IS_TEXT);
fld->fieldValue = strdup("False");
/*
* Use the action name as the default copy_to action
*/
fld = _DtDtsDbAddField(da_rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_COPY_TO_ACTION);
fld->fieldValue = strdup(fields[0].fieldValue);
_DtSvcProcessUnlock();
}
/******************************************************************************
*
* DtDbLoad -
*
* Reads in the file types and action databases.
* From the Default DtDatabaseDirPaths.
*
*****************************************************************************/
void _DtDbLoad(DtDirPaths *dirs)
{
_DtDtsMMUnLoad();
}
void
DtDbLoad(void)
{
DtDirPaths *dirs;
/* Load the requested database files */
dirs = _DtGetDatabaseDirPaths();
_DtDbLoad(dirs);
_DtFreeDatabaseDirPaths(dirs);
}
/******************************************************************************
*
* _DtDbLoad(dirs) -
*
* Reads in the file types and action databases.
* From the the given directory path. This function is not part of the
* public API but may be used internally to avoid repeated generation of
* the default databasedir path.
*
*****************************************************************************/
int
_DtDtsMMCreateDb(DtDirPaths *dirs, const char *CacheFile, int override)
{
DtDbRecordDesc recordDescriptions[3];
DtDbConverter criteriaConverters[2];
DtDbConverter attributesConverters[2];
DtDbConverter actionConverters[3];
static int beenCalled = 0;
char **list;
int i;
_DtSvcProcessLock();
use_in_memory_db = TRUE;
if ( beenCalled ) {
/*
* Free up existing database.
*/
_DtDtsSeqReset();
DtDtsRelease();
_DtFreeActionDB();
}
beenCalled = 1;
/*
* Initialize the databases
* -- this call will initializae the Object databases then
* add the action database.
*/
(void) _DtDtsDbAddDatabase(_DtACTION_NAME);
if ( !dirs )
{
myassert(dirs); /* register an assertion failure */
_DtSvcProcessUnlock();
return(0);
}
/* Build up the record descriptions */
criteriaConverters[0] = (DtDbConverter) _DtDtsDCConverter;
criteriaConverters[1] = NULL;
recordDescriptions[0].recordKeyword = DtDTS_DC_NAME;
recordDescriptions[0].maxFields = _DtMAX_NUM_FIELDS;
recordDescriptions[0].converters = criteriaConverters;
/* Build up the ot record descriptions */
attributesConverters[0] = (DtDbConverter) _DtDtsDAConverter;
attributesConverters[1] = NULL;
recordDescriptions[1].recordKeyword = DtDTS_DA_NAME;
recordDescriptions[1].maxFields = _DtMAX_NUM_FIELDS;
recordDescriptions[1].converters = attributesConverters;
actionConverters[0] = (DtDbConverter) _DtActionConverter;
actionConverters[1] = (DtDbConverter) _DtOAConverter;
actionConverters[2] = NULL;
recordDescriptions[2].recordKeyword = _DtACTION_NAME;
recordDescriptions[2].maxFields = _ActDb_MAX_NUM_FIELDS;
recordDescriptions[2].converters = actionConverters;
_DtDbRead(dirs, ".dt", recordDescriptions, 3);
_DtSortActionDb();
/*
* we may eventually want to return a count of the new records.
* for now we return a non-zero value to register success.
*/
if ((!_DtDtsMMCreateFile(dirs, CacheFile)) ||
(!_DtDtsMMapDB(CacheFile)))
{
_DtSvcProcessUnlock();
return(0);
}
if(!override)
{
unlink(CacheFile);
}
/* now that we have built the databases delete the tmp Db memory
used for it (Too, bad we can't delete the memory associcated
with the Quarks) */
list = (char **)_DtsDbListDb();
for(i = 0; list[i]; i++)
{
_DtDtsDbDeleteDb(_DtDtsDbGet(list[i]));
free(list[i]);
}
free(list);
use_in_memory_db = FALSE;
_DtSvcProcessUnlock();
return(1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
/*
* File: DbReader.h $XConsortium: DbReader.h /main/4 1995/10/26 15:03:35 rswiston $
*
* Description: Public include file for the database reader.
*
* (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
*
* (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. *
*/
#ifndef _Dt_DbReader_h
#define _Dt_DbReader_h
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <Dt/DbUtil.h>
#define DTRECORDIDENTIFIER NULL
#define DTUNLIMITEDFIELDS 0
/* one set of attribute/pair */
typedef struct
{
XrmQuark fieldName;
char *fieldValue;
} DtDtsDbField;
/*
* Opaque identifier used for identifying a database file name. The opaque
* identifier can be converted to an ascii string, using the function
* _DtDbPathIdToString().
*/
#define DtDbPathId long
/*
* All record converters should expect to be called with the parameters
* indicated below:
*
* fields: This is an array of keyword/value pair strings, each
* representing one field value for this database record. NOTE:
* the keywords have not been validated; this is the
* responsibility of the converter, and is usually accomplished
* by calling _DtValidateFieldNames(). The array is NULL
* terminated, with the last entry having both the 'fieldName'
* and 'fieldValue' pointers set to NULL. The first entry always
* represents the record identifier, with the 'fieldName' set
* to the record type string, and the 'fieldValue' set to any
* remaining data specified on the record identifier line.
*
* pathId: Is an opaque identifier, which can be used to retrieve the name
* of the database file from which this record was obtained. By
* calling _DtDbPathIdToString(), the database file, in
* "host:/path" format, can be obtained.
*
* hostPrefix: If the database file was loaded from a machine other than the
* local machine, then this string indicates the host prefix, in
* "/nfs/<host>" format. If the host was the local host, then
* this value is set to NULL.
*
* rejectionStatus: This flag indicates whether any of the earlier record
* converters had rejected this entry. Certain classes
* of converters may choose to ignore entries if they
* had already been rejected.
*
* It is the responsibility of the converter to perform any necessary
* verification of the passed in set of keywords; the function
* _DtValidateFieldNames() is provided as a convenience function for performing
* this type of validation. Typically, the converter will write an error to
* the user's errorlog file, if an invalid record is encountered.
*
* It is also the responsibility of the converter to allocate any memory needed
* to store the new record. The strings contained within the 'fields' array
* will all be freed when the converter returns to _DtDbRead(), so the
* converter should make copies of any information it wishes to use in the
* future. The converter is also responsible for adding the new record to
* whatever storage array it is using to save record information.
*
* If the converter decides to reject the record, then it should return a
* 'True' value. If the record was acceptable, then 'False' should be
* returned.
*/
typedef Boolean (*DtDbConverter) (DtDtsDbField * fields,
DtDbPathId pathId,
char * hostPrefix,
Boolean rejectionStatus);
/*
* This structure defines each record type which should be loaded by
* _DtDbRead(). Since _DtDbRead() is capable of loading multiple record types
* (i.e ACTION, DATA_CRITERIA, etc) in a single pass, the invoking function will
* pass in an array of these structures, for which each element will define a
* record type which should be loaded. Each record definition requires the
* following information:
*
* recordKeyword: This is the keyword which uniquely identifies the record
* which matches this definition. Examples are "ACTION" and
* "DATA_CRITERIA".
*
* maxFields: Indicates the maximum number of fields which is expected
* by this record type; typically, this corresponds to the
* number of distinct field keywords supported by this type
* of record. This feature is used to prevent runaway database
* records from getting out of hand; a runaway database record
* typically occurs when the user forgets to include line
* continuation characters, and a long 'description' field
* is entered. If this parameter is set to
* DTUNLIMITEDFIELDS, then the check for runaway records
* will be disabled for records of this type.
*
* converters: This is a NULL-terminated array of function pointers,
* corresponding to the set of record converters which will
* be called, whenever a record of this type is encountered.
* The converters are called in order, and all converters will
* be called, even if an earlier one rejects the record. The
* last entry in the array must be set to NULL.
*/
typedef struct {
char * recordKeyword;
int maxFields;
DtDbConverter * converters;
} DtDbRecordDesc;
/*
* _DtDbRead() is the function which causes the specified set of directories to
* be searched for files ending with the specified suffix. Although not
* required, the set of directories to search is typically obtained by calling
* _DtGetDatabaseDirPaths(). This function supports the loading of multiple
* field types, all in a single pass of the database files. This function does
* not attempt to manage the memory used to store the information extracted from
* the database files; it is the responsibility of the function calling this
* procedure to initialize any storage, and it is the responsibility of the
* record converters to allocate any memory needed to store and record, along
* with adding the record to the appropriate storage array.
*
* dirs: The set of directories to be searched for database files.
*
* suffix: The file suffix (i.e. ".vf") used to qualify which files within
* the database directories should be loaded.
*
* recordDescriptions: An array, where each entry describes a database record
* which should be loaded during this pass of _DtDbRead().
* See the definition for this structure, for more details.
*
* int numRecordDescriptions: The number of entries in the above array.
*/
extern void _DtDbRead (DtDirPaths * dirs,
char * suffix,
DtDbRecordDesc * recordDescriptions,
int numRecordDescriptions);
/*
* _DtDbPathIdToString() is used to map a filename identifier, represented
* by an opaque DtDbPathId value, into its corresponding ascii string
* representation. The returned string is owned by the calling application,
* which should free it up when no longer needed.
*/
extern char * _DtDbPathIdToString ( DtDbPathId pathId );
#endif /* _Dt_DbReader_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,890 @@
/*
* $TOG: DbUtil.c /main/13 1998/04/09 17:47:56 mgreess $
*
* (c) Copyright 1988, 1989, 1990, 1991, 1992, 1993
* by 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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <string.h>
#ifdef NLS16
#include <limits.h>
#endif
#include <sys/stat.h>
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#define X_INCLUDE_DIRENT_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <Dt/DtP.h>
#include <Dt/Connect.h>
#include <Dt/FileUtil.h>
#include <Dt/DtNlUtils.h>
#include <Dt/Action.h>
#include <Dt/ActionP.h>
#include <Dt/ActionDbP.h>
#include <Dt/ActionUtilP.h>
#include <Dt/DbUtil.h>
#include <Dt/Utility.h>
#include <Dt/ActionDb.h>
#ifndef S_ISLNK
/* This macro is normally defined in stat.h, but not on USL systems. */
# define S_ISLNK(_M) ((_M & S_IFMT)==S_IFLNK) /* test for symbolic link */
#endif
#ifndef CDE_INSTALLATION_TOP
#define CDE_INSTALLATION_TOP "/opt/dt"
#endif
#ifndef CDE_CONFIGURATION_TOP
#define CDE_CONFIGURATION_TOP "/etc/opt/dt"
#endif
#define TRUE 1
#define FALSE 0
#define FILE_INCREMENT 20
/* The following string holds the default value of the Dt database
* search path. This default search path has the following major
* components:
*
* $HOME/.dt/types[/%L] A location for the user's personal
* actions and filetypes.
*
* <config-location>/appconfig/types[/%L]
* The DT location for system-wide
* customizations.
*
* <top-of-dt>/types/[%L] The DT location for default
* system-wide actions and filetypes.
*/
static char DTDATABASESEARCHPATH_DEFAULT[] =
"%s/.dt/types/%%L,"
"%s/.dt/types,"
CDE_CONFIGURATION_TOP "/appconfig/types/%%L,"
CDE_CONFIGURATION_TOP "/appconfig/types,"
CDE_INSTALLATION_TOP "/appconfig/types/%%L,"
CDE_INSTALLATION_TOP "/appconfig/types";
/**** Substitution records used by XtFindFile() in _DtExpandLang() ****/
static SubstitutionRec langSubstitutions[] =
{
{'L', (char *)NULL},
{'l', (char *)NULL},
{'t', (char *)NULL},
{'c', (char *)NULL}
};
static int nLangSubstitutions = XtNumber(langSubstitutions);
/******** Static Function Declarations ********/
static Boolean __testPath(
String str );
static void __setupLangSubstitutions(
void );
static void __freeLangSubstitutions(
void );
static char *_DtExpandLang(
char *string ) ;
static char _DtIsDir(
char *path,
char *name) ;
static void _DtFreeDirVector(
char **dir_vector) ;
static void __swap(
int i ,
DtDirPaths *data );
static void _DtSortFiles(
int low,
int n,
DtDirPaths *data) ;
/******** End Static Function Declarations ********/
/******************
*
* Function Name: __testPath
*
* Description:
*
* This function is needed by XtFindFile(). Always returns True.
*
* Synopsis:
*
* path = XtFindFile(..., __testPath);
*
******************/
static Boolean
__testPath(String str)
{
return True;
}
/******************
*
* Function Name: __setupLangSubstitutions
*
* Description:
*
* This function initializes langSubstitutions[] for use by
* XtFindFile().
*
* Synopsis:
*
* __setupLangSubstitutions();
*
******************/
static void
__setupLangSubstitutions(void)
{
char *lang;
char *languagePart;
char *territoryPart;
char *codesetPart;
char *tlPtr, *ttPtr, *tcPtr, *endPtr;
/*
* We should really be calling setlocale to determine the "default"
* locale but setlocale's return value is not standardized across
* the various vendor platforms nor is it consistent within differnt
* revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
* HP-UX 10.0). The "right" call would be the following line:
*
* if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
*
* Here we hard code the default to "C" instead of leaving it NULL.
*/
languagePart = territoryPart = codesetPart = (char *)NULL;
if ((lang = getenv ("LANG")) == (char *)NULL)
lang = "C";
lang = XtNewString(lang); /* free'd in __freeLangSubstitutions() */
tlPtr = lang;
endPtr = (char *)NULL;
if ((ttPtr = DtStrchr(tlPtr, '_')) != (char *)NULL)
ttPtr++;
if ((tcPtr = DtStrchr(ttPtr ? ttPtr : tlPtr, '.')) != (char *)NULL)
{
endPtr = tcPtr++;
if (*tcPtr != '\0')
codesetPart =
XtNewString(tcPtr); /* free'd in __freeLangSubstitutions() */
}
if (ttPtr)
{
if (endPtr)
{
int ttLen = endPtr - ttPtr;
if (ttLen > 0)
{
/* free'd in __freeLangSubstitutions() */
territoryPart = (char *)XtMalloc((ttLen + 1) * sizeof(char));
strncpy(territoryPart, ttPtr, ttLen);
territoryPart[ttLen] = '\0';
}
}
else territoryPart =
XtNewString(ttPtr); /* free'd in __freeLangSubstitutions() */
endPtr = ttPtr - 1;
}
if (endPtr)
{
int tlLen = endPtr - tlPtr;
if (tlLen > 0)
{
/* free'd in __freeLangSubstitutions() */
languagePart = (char *)XtMalloc((tlLen + 1) * sizeof(char));
strncpy(languagePart, tlPtr, tlLen);
languagePart[tlLen] = '\0';
}
}
else languagePart =
XtNewString(tlPtr); /* free'd in __freeLangSubstitutions() */
langSubstitutions[0].substitution = lang;
langSubstitutions[1].substitution = languagePart;
langSubstitutions[2].substitution = territoryPart;
langSubstitutions[3].substitution = codesetPart;
}
/******************
*
* Function Name: __freeLangSubstitutions
*
* Description:
*
* This function free's the strings allocated by
* __setupLangSubstitutions and placed into langSubstitutions[]
*
* Synopsis:
*
* __freeLangSubstitutions();
*
******************/
static void
__freeLangSubstitutions(void)
{
int i;
for (i = 0; i < nLangSubstitutions; i++)
XtFree(langSubstitutions[i].substitution);
}
/******************
*
* Function Name: _DtExpandLang
*
* Description:
*
* This function takes the string "string", and performs the following
* replacements:
* %L : contents of LANG environment variable.
* %l : language part of the LANG environment variable.
* %t : territory part of the LANG environment variable.
* %c : codeset part of the LANG environment variable.
* %% : % (e.g. %%L would be replaced by %L, and
* no substitution would be performed on %L)
*
* If $LANG is not defined, the $LANG is assumed to be "C".
*
* Synopsis:
*
* ret_string = _DtExpandLang (string);
*
* char *ret_string; Returns NULL if "string" is NULL, or it points
* to the expanded string.
*
* char *string; The comma-separated pathnames to expand.
*
* Note: The caller is responsible for free'ing the returned string.
*
******************/
static char *
_DtExpandLang(
char *string )
{
char *thisPath;
char *newPath;
char *modPath;
int pathLen, maxPathLen;
int nColons;
char *tmpPtr, *tmpPtr1;
char *newString;
char *tokPtr;
if (string == NULL)
return (NULL);
/*
* We're going to use XtFindFile() to perform the replacements;
* the colon character ':' is used as a delimiter in XtFindFile,
* so we escape all colon characters in our string before
* passing it along.
*/
for (nColons = 0, tmpPtr = string;
(tmpPtr = DtStrchr(tmpPtr, ':')) != (char *)NULL;
nColons++, tmpPtr++)
/* EMPTY */
;
newString =
(char *)XtCalloc(1, (strlen(string) + nColons + 1) * sizeof(char));
for (tmpPtr = string;
(tmpPtr1 = DtStrchr(tmpPtr, ':')) != (char *)NULL;
tmpPtr = tmpPtr1 + 1)
{
strncat(newString, tmpPtr, tmpPtr1 - tmpPtr);
strcat(newString, "%:");
}
strcat(newString, tmpPtr);
__setupLangSubstitutions();
/*
* XtFindFile() assumes that the string into which it's making
* substitutions is a path, and therefore it assumes that the
* length of the string does not exceed MAXPATHLEN. Since
* our string is a series of paths, it CAN exceed MAXPATHLEN.
* So, we split our string into individual paths which we then
* pass off to XtFindFile().
*/
pathLen = maxPathLen = 0;
newPath = (char *)NULL;
for (thisPath = DtStrtok_r(newString, ",", &tokPtr);
thisPath != (char *)NULL;
thisPath = DtStrtok_r((char *)NULL, ",", &tokPtr))
{
modPath = XtFindFile(thisPath, langSubstitutions,
nLangSubstitutions, __testPath);
if (modPath)
{
char *origPath = modPath;
int modLen;
/*
* For some reason, XtFindFile() collapses all '/'
* characters EXCEPT at the beginning of the path!
* For backwards compatibility, we collapse those here.
*/
if (*modPath == '/')
{
while (*(modPath + 1) == '/')
modPath++;
}
modLen = strlen(modPath);
if (pathLen + modLen + 2 > maxPathLen)
{
maxPathLen =
((pathLen + modLen + 2 + MAXPATHLEN) / MAXPATHLEN) *
MAXPATHLEN;
newPath =
(char *)XtRealloc(newPath, maxPathLen * sizeof(char));
}
if (pathLen > 0)
newPath[pathLen++] = ',';
strcpy(&(newPath[pathLen]), modPath);
pathLen += modLen;
XtFree(origPath);
}
}
__freeLangSubstitutions();
XtFree(newString);
return newPath;
}
/******************
*
* Function Name: _DtIsDir
*
* Description:
*
* This function tests a pathname to see if it is a directory.
* The path name is received in two pieces, which makes it easy
* for the calling function to test a bunch of files in a directory
* to see if any are subdirectories.
*
* This function does NOT handle Softbench-style pathnames with
* embedded hostnames.
*
* Synopsis:
*
* dir = _DtIsDir (path, name);
*
* char dir; Returns 0 if the item is not a directory,
* 1 if it is.
* char *path; The first part of the pathname. Typically
* the directory containing the item of interest.
* char *name; The second half of the pathname. Typically
* the name of the item of interest.
*
******************/
static char
_DtIsDir(
char *path,
char *name )
{
struct stat stat_buf;
char *stat_name;
stat_name = XtMalloc ((Cardinal)(strlen(path) + strlen(name) + 2));
(void)strcpy (stat_name, path);
(void)strcat (stat_name, "/");
(void)strcat (stat_name, name);
if(stat (stat_name, &stat_buf))
{
stat_buf.st_mode = 0;
}
XtFree (stat_name);
if (stat_buf.st_mode & S_IFDIR)
return (TRUE);
else
return (FALSE);
}
/******************************
*
* Function Name: _DtFreeDirVector
*
* Description:
*
* This function frees a database-directory string vector.
*
* Synoposis:
*
* FreeDatabaseDirs (dirs);
*
* char **dirs; The string vector to free.
*
********************************/
static void
_DtFreeDirVector(
char **dir_vector )
{
char **v;
if (dir_vector)
{
for (v = dir_vector; *v != NULL; v++)
XtFree ((char *)*v);
XtFree ((char *)dir_vector);
}
}
/******************************
*
* Function Name: __swap
*
* Description:
*
* This function exchanges two elements in an array of DtDirPaths.
*
* Synoposis:
*
* __swap (i, data);
*
* int i; The base index to change.
* DtDirPaths *data; The data to change.
*
********************************/
static void
__swap(
int i ,
DtDirPaths *data )
{
char *tmp;
/* The "names" field of the structure is not touched because
* this field is "NULL" for all of the entries.
*/
tmp = data->dirs[i];
data->dirs[i] = data->dirs[i+1]; data->dirs[i+1] = tmp;
tmp = data->paths[i];
data->paths[i] = data->paths[i+1]; data->paths[i+1] = tmp;
}
/******************************
*
* Function Name: _DtSortFiles
*
* Description:
*
* Given an index, an array of "char" data and the number of elements to
* sort, this function sorts the data. The sorting algorithm is based
* on a bubble sort because the number of elements is usually less than
* ten.
*
* Synoposis:
*
* _DtSortFiles (index, n, data);
*
* int low; The base of the array to begin the sorting.
* int n; The number of elements to sort.
* DtDirPaths *data; The data to sort.
*
********************************/
static void
_DtSortFiles(
int low,
int n,
DtDirPaths *data )
{
int i, j;
int high = low + n;
/*
* This sorting routine needs to be able to sort any portion of
* an array - it does not always start at element '0'.
*/
for (i = low; i < (high - 1); i++)
for (j = low; j < (high - 1); j++)
#ifndef NO_MESSAGE_CATALOG
if ((strcoll (data->paths[j], data->paths[j+1])) > 0)
#else
if ((strcmp (data->paths[j], data->paths[j+1])) > 0)
#endif
__swap (j, data);
}
/******************
*
* Function Name: _DtFindMatchingFiles
*
* Description:
*
* This function takes a string vector of directory names (which
* are in "host:/path/file" format) and a filename suffix and
* finds all of the files in those directories with the specified
* suffix. It returns a string vector of the filenames.
*
* You will typically first call _DtGetDatabaseDirPaths() to get the
* 'dirs' info.
*
* Use _DtFreeDatabaseDirPaths() to free up the return structure.
*
* Synopsis:
*
* filev = _DtFindMatchingFiles (dirs, suffix, sort_files);
*
* DtDirPaths *filev; A structure containing the names
* of all the files that were found.
* DtDirPaths *dirs; A structure of directories to be
* searched.
* char *suffix; The suffix string which is compared
* to the end of the filenames. This
* string must contain a "." if it is
* part of the suffix you want to match
* on (e.g. ".c").
* Boolean sort_files; Should the files within a directory be sorted.
*
*
******************/
DtDirPaths *
_DtFindMatchingFiles(
DtDirPaths *dirs,
char *suffix,
Boolean sort_files )
{
/* LOCAL VARIABLES */
register DtDirPaths *files; /* An array of pointers to the filenames which
have been found. */
int max_files; /* The total number of filenames that can be
stored in the "files" array before it must
be reallocd. */
int num_found; /* The number of files which have been found. */
register DIR *dirp; /* Variables for walking through the directory
entries. */
char * next_file;
struct dirent *dp = NULL;
char *file_suffix;
int suffixLen, nameLen;
int nextIndex;
register char * next_path;
int files_in_this_directory;
int base;
_Xreaddirparams dirEntryBuf;
struct dirent *result;
/* CODE */
if (dirs == NULL)
return(NULL);
files = (DtDirPaths *) XtMalloc((Cardinal)(sizeof(DtDirPaths)));
files->dirs = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
files->paths = (char **) XtMalloc(sizeof(char *) * FILE_INCREMENT);
max_files = FILE_INCREMENT;
num_found = 0;
nextIndex = 0;
/* Process each one of the directories in priority order. */
while (dirs->paths[nextIndex] != NULL) {
next_path = dirs->paths[nextIndex];
dirp = opendir (next_path);
base = num_found;
files_in_this_directory = 0;
while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL) {
/* Check the name to see if it matches the suffix and is
a file. */
if (strlen (result->d_name) >= strlen(suffix))
{
/* Find the end of the name and compare it to the suffix. */
/* Get the number of chars (not bytes) in each string */
suffixLen = DtCharCount(suffix);
nameLen = DtCharCount(result->d_name);
file_suffix = _DtGetNthChar(result->d_name, nameLen - suffixLen);
if (file_suffix && (strcmp(file_suffix, suffix) == 0) &&
!_DtIsDir((char *)next_path, (char *)result->d_name))
{
/* The file is a match. See if there is room in the array
or whether we need to realloc. The "-1" is to save room
for the terminating NULL pointer. */
if (num_found == max_files - 1) {
files->dirs = (char **) XtRealloc ((char *)files->dirs,
(Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
files->paths = (char **) XtRealloc ((char *)files->paths,
(Cardinal)(sizeof(char *) * (max_files + FILE_INCREMENT)));
max_files += FILE_INCREMENT;
}
/* Get some memory and copy the filename to the array. */
files->dirs[num_found] = next_file = (char *)
XtMalloc((Cardinal)(strlen(dirs->dirs[nextIndex]) +
strlen (result->d_name) + 2));
(void)strcpy(next_file, dirs->dirs[nextIndex]);
(void)strcat(next_file, "/");
(void)strcat(next_file, result->d_name);
files->paths[num_found] = next_file = (char *)
XtMalloc((Cardinal)(strlen(next_path) +
strlen (result->d_name) + 2));
(void)strcpy(next_file, next_path);
(void)strcat(next_file, "/");
(void)strcat(next_file, result->d_name);
num_found++;
files_in_this_directory++;
}
}
}
closedir (dirp);
if (sort_files && (files_in_this_directory > 1))
_DtSortFiles (base, files_in_this_directory, files);
nextIndex++;
}
files->dirs[num_found] = NULL;
files->paths[num_found] = NULL;
return (files);
}
/******************************************************************************
*
* _DtDbGetDataBaseEnv( )
* ------------------------
* This function provides a PRIVATE API for internal manipulation of the
* DTDATABASEDIRPATH environment variable before loading the databases.
* -- used by the front panel code in dtwm.
*
* If the environment variable it returns a default path.
*
* NOTE: This function returns a freshly malloc'ed string. It is up to
* the caller to free it.
*
******************************************************************************/
char *
_DtDbGetDataBaseEnv( void )
{
char *nwh_dir;
char *temp_buf;
char *temp_s;
nwh_dir = getenv ("HOME");
/*
* Get the DTDATABASESEARCHPATH environment variable. If it is not set,
* create the default value.
*/
if ( temp_s = getenv ("DTDATABASESEARCHPATH"))
if ( *temp_s != 0 ) return XtNewString(temp_s);
temp_buf =
XtMalloc((2*strlen(nwh_dir)) + strlen(DTDATABASESEARCHPATH_DEFAULT) + 1);
sprintf (temp_buf, DTDATABASESEARCHPATH_DEFAULT, nwh_dir, nwh_dir);
return temp_buf;
}
/******************************
*
* Function Name: _DtGetDatabaseDirPaths
*
* Description:
*
* This function returns a structure containing the external
* and internal forms for all of the database directories that must be
* searched for Dt database files.
* The structure is freed using _DtFreeDatabaseDirPaths().
*
* The directories are all guaranteed to be fully-specified names;
* i.e. host:/path/dir.
*
* THIS IS TYPICALLY CALLED BEFORE USING ANY OF THE FOLLOWING:
*
* DtReadDatabases()
* DtPrepareToolboxDirs()
* _DtDbRead()
* _DtFindMatchingFiles()
*
* Synoposis:
*
* DtDirPaths * _DtGetDatabaseDirPaths ();
*
********************************/
DtDirPaths *
_DtGetDatabaseDirPaths( void )
{
XrmValue resource_value;
char *rep_type;
char *dir_string, *remote_hosts;
char *nwh_host; /* Holds the host portion of the user's
network-home. */
char **dir_vector; /* The list of directories are turned into
a vector of strings. This points to the
start of the vector. */
char **hosts_vector;
char **next_dir; /* A pointer used to walk through dir_vector. */
char **next_host;
char *dir; /* Points to next dir being processed */
int valid_dirs; /* A count of the number of valid directories
found. */
char *home;
char *nextc;
DtDirPaths * ret_paths;
char * internal;
int i;
char *tmp_dir_string;
/* Get our host name, and the user's home directory */
nwh_host = _DtGetLocalHostName ();
tmp_dir_string = _DtDbGetDataBaseEnv();
dir_string = _DtExpandLang (tmp_dir_string);
XtFree (tmp_dir_string);
/* Prepare the input vector and the two output vectors. */
dir_vector = _DtVectorizeInPlace (dir_string, ',');
ret_paths = (DtDirPaths *)XtMalloc(sizeof(DtDirPaths));
ret_paths->dirs = NULL;
ret_paths->paths = NULL;
valid_dirs = 0;
for (next_dir = dir_vector; *next_dir != NULL; next_dir++) {
if (DtStrchr (*next_dir, '/') == NULL){
/* It must be a relative path. */
/* Ignore relative paths */
continue;
}
/* If the name is not a valid directory, get rid of it. */
if (!_DtIsOpenableDirContext (*next_dir, &internal)) {
continue;
}
else {
/* If not already in the list, add it to the structure. */
for (i = 0; i < valid_dirs; i++)
{
if (strcmp(ret_paths->paths[i], internal) == 0)
{
break;
}
}
if (i == valid_dirs)
{
valid_dirs++;
ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
(Cardinal) (sizeof (char *) * valid_dirs));
/* Make sure the directory name is fully-qualified with a host
component. */
if (DtStrchr (*next_dir, ':') != NULL)
dir = XtNewString(*next_dir);
/* If there is no host component, see if there is
an absolute path. */
else if (
#ifdef NLS16
(!is_multibyte || (mblen(*next_dir, MB_LEN_MAX) == 1)) &&
#endif
(**next_dir == '/')) {
dir = XtMalloc ((Cardinal) (strlen (nwh_host) + 2 +
strlen (*next_dir)));
(void) sprintf (dir, "%s:%s", nwh_host, *next_dir);
}
else
dir = XtNewString(*next_dir);
ret_paths->dirs[valid_dirs - 1] = dir;
ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
(Cardinal) (sizeof (char *) * valid_dirs));
ret_paths->paths[valid_dirs - 1] = internal;
}
else {
XtFree(internal);
}
}
}
/* The three vectors must be NULL terminated. */
ret_paths->dirs = (char **) XtRealloc ((char *)ret_paths->dirs,
(Cardinal) (sizeof (char *) *
(valid_dirs + 1)));
ret_paths->dirs[valid_dirs] = NULL;
ret_paths->paths = (char **) XtRealloc ((char *)ret_paths->paths,
(Cardinal) (sizeof (char *) *
(valid_dirs + 1)));
ret_paths->paths[valid_dirs] = NULL;
XtFree ((char *) dir_string);
XtFree ((char *) nwh_host);
XtFree ((char *) dir_vector);
return(ret_paths);
}
/***************************
* void _DtFreeDatabaseDirPaths (paths)
*
* DtDirPaths * paths;
*
* This function will free up each of the arrays within the directory
* information structure, and will then free the structure itself.
*
**************************/
void
_DtFreeDatabaseDirPaths(
DtDirPaths *paths )
{
_DtFreeDirVector(paths->dirs);
_DtFreeDirVector(paths->paths);
XtFree((char *)paths);
}

View File

@@ -0,0 +1,81 @@
/*
* File: DbUtil.h $XConsortium: DbUtil.h /main/4 1995/10/26 15:04:04 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. *
*/
#ifndef _Dt_DbUtil_h
#define _Dt_DbUtil_h
#include <X11/Intrinsic.h> /* Boolean */
/*
* This structure is used by many of the database functions. It is used to
* specify a collection of filenames or directory names. Each file/directory
* name is returned in two forms:
*
* dirs[n] The fully host-qualified pathname for the file or directory,
* in "host:/path" format.
*
* paths[n] The internal format of the file or directory anme, which
* can be passed to any of the standard tools which expect a
* valid filename; i.e. /nfs/host/path.
*
* Both of the arrays are NULL-terminated.
*/
typedef struct {
char ** dirs;
char ** paths;
} DtDirPaths;
/*****************************************************************************
*
*
*
****************************************************************************/
extern DtDirPaths * _DtFindMatchingFiles( DtDirPaths * dirs,
char * suffix,
Boolean sortFiles );
/*****************************************************************************
*
* _DtGetDatabaseDirPaths() returns a NULL-terminated array of directories,
* which are to be searched for database files. The paths are obtained by
* querying the DTDATABASESEARCHPATH environment variable, which specifies
* a set of comma separated pathnames, int "host:/path" format. The
* return structure should be freed up, when no longer needed, by invoking
* _DtFreeDatabaseDirPaths().
*
* The returned directory names are represented in two formats:
*
* 1) Fully host qualified; i.e. "host:/path"
* 2) Internal format; i.e. "/nfs/host/path"
*
****************************************************************************/
extern DtDirPaths * _DtGetDatabaseDirPaths( void );
/*****************************************************************************
*
* _DtFreeDatabaseDirPaths() is used to free the memory occupied by the
* passed-in instance of the DtDirPaths structure. Typically, this
* information was originally obtained by a call to DtGetDatabasePaths()
* or _DtFindMatchingFiles().
*
* Parameters:
*
* dirs The structure which is to be freed up.
*
****************************************************************************/
extern void _DtFreeDatabaseDirPaths( DtDirPaths * dirs );
#endif /* _Dt_DbUtil_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

467
cde/lib/DtSvc/DtUtil1/Dnd.c Normal file
View File

@@ -0,0 +1,467 @@
/* $TOG: Dnd.c /main/7 1998/10/23 13:47:10 mgreess $ */
/*********************************************************************
*
* File: Dnd.c
*
* Description: Implemenation of DND Convenience API.
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/DragDrop.h>
#include <Xm/DropTrans.h>
#include <Dt/UserMsg.h>
#include "Dnd.h"
#include "DndP.h"
#include "DtSvcLock.h"
/*********************************************************************
*
* Data Transfer Selection Targets
*
*********************************************************************/
Atom XA_TARGETS;
Atom XA_TIMESTAMP;
Atom XA_MULTIPLE;
Atom XA_DELETE;
Atom XA_NULL;
Atom XA_TEXT;
Atom XA_HOST_NAME;
Atom XA_SUN_FILE_HOST_NAME;
Atom XA_SUN_ENUM_COUNT;
Atom XA_SUN_DATA_LABEL;
Atom XA_SUN_SELN_READONLY;
Atom XA_SUN_ATM_FILE_NAME;
Atom XA_SUN_ATM_METHODS;
static void
dndInitTargets(
Display *dpy)
{
_DtSvcProcessLock();
if (XA_TARGETS != 0) {
_DtSvcProcessUnlock();
return;
}
XA_TARGETS = DtGetAtom(dpy,"TARGETS");
XA_TIMESTAMP = DtGetAtom(dpy,"TIMESTAMP");
XA_MULTIPLE = DtGetAtom(dpy,"MULTIPLE");
XA_DELETE = DtGetAtom(dpy,"DELETE");
XA_NULL = DtGetAtom(dpy,"NULL");
XA_TEXT = DtGetAtom(dpy,"TEXT");
XA_HOST_NAME = DtGetAtom(dpy,"HOST_NAME");
XA_SUN_FILE_HOST_NAME = DtGetAtom(dpy,"_SUN_FILE_HOST_NAME");
XA_SUN_ENUM_COUNT = DtGetAtom(dpy,"_SUN_ENUMERATION_COUNT");
XA_SUN_DATA_LABEL = DtGetAtom(dpy,"_SUN_DATA_LABEL");
XA_SUN_SELN_READONLY = DtGetAtom(dpy,"_SUN_SELN_IS_READONLY");
XA_SUN_ATM_FILE_NAME = DtGetAtom(dpy,"_SUN_ATM_FILE_NAME");
XA_SUN_ATM_METHODS = DtGetAtom(dpy,
"_SUN_ALTERNATE_TRANSPORT_METHODS");
_DtSvcProcessUnlock();
}
/*********************************************************************
*
* Data Transfer Protocol Method Functions
*
*********************************************************************/
static DtDndProtocol dndProtocolList[] = {
DtDND_FILENAME_TRANSFER,
DtDND_BUFFER_TRANSFER,
DtDND_TEXT_TRANSFER,
DtDND_NOOP_TRANSFER
};
extern DtDndMethods *_DtDndBuffTransferProtocolInitialize(Display*);
extern DtDndMethods *_DtDndFileTransferProtocolInitialize(Display*);
extern DtDndMethods *_DtDndTextTransferProtocolInitialize(Display*);
/*
* dndGetTransferMethods
*
* Return the transfer methods for a particular protocol
*/
static DtDndMethods *
dndGetTransferMethods(
Display * display,
DtDndProtocol protocol)
{
DtDndMethods * methods = NULL;
switch (protocol) {
case DtDND_BUFFER_TRANSFER:
methods = _DtDndBuffTransferProtocolInitialize(display);
break;
case DtDND_FILENAME_TRANSFER:
methods = _DtDndFileTransferProtocolInitialize(display);
break;
case DtDND_TEXT_TRANSFER:
methods = _DtDndTextTransferProtocolInitialize(display);
break;
}
return methods;
}
/*
* _DtDndCreateExportTransfer
*
* Returns a transfer suitable for use by a drag initiator
*/
DtDndTransfer *
_DtDndCreateExportTransfer(
DtDragInfo * dtDragInfo)
{
Display * dpy = XtDisplayOfObject(dtDragInfo->dragInitiator);
DtDndTransfer * transfer;
dndInitTargets(dpy);
transfer = (DtDndTransfer *)XtMalloc(sizeof(DtDndTransfer));
transfer->methods = dndGetTransferMethods(dpy,dtDragInfo->protocol);
(*transfer->methods->getExportTargets)(dtDragInfo,
&(transfer->targets), &(transfer->numTargets));
return transfer;
}
/*
* _DtDndCreateImportTransfers
*
* Create the list of transfers specified by the protocols.
*/
DtDndTransfer *
_DtDndCreateImportTransfers(
DtDropInfo * dtDropInfo,
Cardinal * numTransfers)
{
Display * dpy = XtDisplayOfObject(dtDropInfo->dropReceiver);
DtDndTransfer * transfers;
DtDndTransfer * transfer;
Cardinal ii, jj;
dndInitTargets(dpy);
*numTransfers = 0;
for (ii = 0; dndProtocolList[ii] != DtDND_NOOP_TRANSFER; ii++) {
if (dtDropInfo->protocols & dndProtocolList[ii]) {
(*numTransfers)++;
}
}
if (*numTransfers == 0)
return (DtDndTransfer *)NULL;
transfers = (DtDndTransfer *)XtMalloc(
*numTransfers * sizeof(DtDndTransfer));
for (ii = 0, jj = 0; dndProtocolList[ii] != DtDND_NOOP_TRANSFER; ii++) {
if (dtDropInfo->protocols & dndProtocolList[ii]) {
transfer = &transfers[jj++];
transfer->methods =
dndGetTransferMethods(dpy,dndProtocolList[ii]);
(*transfer->methods->getImportTargets)(dtDropInfo,
&(transfer->targets), &(transfer->numTargets));
}
}
return transfers;
}
/*
* _DtDndDestroyTransfers
*
* Destroy the transfer list created by
* _DtDndCreateExportTransfer() or _DtDndCreateImportTransfers()
*/
void
_DtDndDestroyTransfers(
DtDndTransfer * transfers,
Cardinal numTransfers)
{
Cardinal ii;
for (ii = 0; ii < numTransfers; ii++) {
XtFree((char *)transfers[ii].targets);
}
XtFree((char *)transfers);
}
/*
* _DtDndTransferFromTargets
*
* Returns the transfer method that matches the target list
*/
DtDndTransfer *
_DtDndTransferFromTargets(
DtDndTransfer * transfers,
Cardinal numTransfers,
Atom * targets,
Cardinal numTargets)
{
Cardinal ii, jj, kk;
for (ii = 0; ii < numTransfers; ii++) {
for (jj = 0; jj < transfers[ii].numTargets; jj++) {
for (kk = 0; kk < numTargets; kk++) {
if (transfers[ii].targets[jj] == targets[kk]) {
return &transfers[ii];
}
}
}
}
return (DtDndTransfer *)NULL;
}
/*
* _DtDndTransferAdd
*
* Add the targets to the requested transfer targets list
* and call XmDropTransferAdd() to request them
*/
void
_DtDndTransferAdd(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * transferTargets,
Cardinal numTransferTargets)
{
DtTransferInfo *transferInfo = dtDropInfo->transferInfo;
XmDropTransferEntryRec * transferEntries;
Cardinal numTransfers;
int ii, jj;
transferEntries = (XmDropTransferEntryRec *)
XtMalloc(numTransferTargets * sizeof(XmDropTransferEntryRec));
numTransfers = transferInfo->numTransferTargets + numTransferTargets;
transferInfo->transferTargets = (Atom *)XtRealloc(
(char *)transferInfo->transferTargets,
numTransfers * sizeof(Atom));
jj = transferInfo->numTransferTargets;
for (ii = 0; ii < numTransferTargets; ii++) {
transferEntries[ii].target = transferTargets[ii];
transferEntries[ii].client_data = (XtPointer)dtDropInfo;
transferInfo->transferTargets[ii+jj] = transferTargets[ii];
}
transferInfo->numTransferTargets = numTransfers;
XmDropTransferAdd(dropTransfer, transferEntries, numTransferTargets);
XtFree((char *)transferEntries);
}
/*********************************************************************
*
* Misc Debugging Functions
*
*********************************************************************/
#ifdef DEBUG
void
_DtDndPrintTargets(
Display *display,
Atom *targets,
Cardinal numTargets)
{
Cardinal ii;
char *name;
for (ii = 0; ii < numTargets; ii++) {
name = XGetAtomName(display, targets[ii]);
if (name) {
printf("%s ", name);
XFree(name);
} else {
printf("(null) ");
}
}
printf("\n");
}
void
_DtDndPrintTransfers(
Display *display,
DtDndTransfer *transfers,
Cardinal numTransfers)
{
Cardinal ii;
for (ii = 0; ii < numTransfers; ii++) {
printf("%s\tTargets: ",transfers[ii].methods->name);
_DtDndPrintTargets(display,
transfers[ii].targets,transfers[ii].numTargets);
}
}
#endif
/*********************************************************************
*
* Misc Utility Functions
*
*********************************************************************/
/*
* Copy CallbackList
*/
XtCallbackList
_DtDndCopyCallbackList(
XtCallbackList callbacks)
{
XtCallbackList cl;
int ii, count;
if (callbacks == NULL)
return NULL;
count = 1;
for (cl = callbacks; cl->callback != NULL; cl++) {
count++;
}
cl = (XtCallbackList)XtMalloc(count * sizeof(XtCallbackRec));
for (ii = 0; ii < count; ii++) {
cl[ii].callback = callbacks[ii].callback;
cl[ii].closure = callbacks[ii].closure;
}
return cl;
}
/*
* Call CallbackList
*/
void
_DtDndCallCallbackList(
Widget widget,
XtCallbackList callbacks,
XtPointer calldata)
{
XtCallbackList cl;
if (callbacks == NULL)
return;
for (cl = callbacks; cl->callback != NULL; cl++) {
(*cl->callback)(widget, cl->closure, calldata);
}
}
/*
* Misc Varargs Utility Functions
*/
int
_DtDndCountVarArgs(
va_list vaList)
{
XtPointer argPtr;
Cardinal argCount;
argCount = 0;
for (argPtr = va_arg(vaList,String);
argPtr != NULL;
argPtr = va_arg(vaList,String)) {
va_arg(vaList, XtArgVal);
argCount++;
}
return argCount;
}
void
_DtDndArgListFromVarArgs(
va_list vaList,
Cardinal maxArgs,
ArgList *argListReturn,
Cardinal *argCountReturn)
{
ArgList argList;
Cardinal argCount;
XtPointer argPtr;
if (0 == maxArgs)
{
*argListReturn = NULL;
*argCountReturn = 0;
return;
}
argList = (ArgList)XtMalloc((unsigned)(maxArgs * sizeof(Arg)));
argCount = 0;
for (argPtr = va_arg(vaList,String);
argPtr != NULL;
argPtr = va_arg(vaList,String)) {
XtSetArg(argList[argCount], argPtr, va_arg(vaList,XtArgVal));
argCount++;
}
*argListReturn = argList;
*argCountReturn = argCount;
}
/*
* Returns the network node/host name.
*/
String
_DtDndGetHostName()
{
static char *nodename;
_DtSvcProcessLock();
if (nodename == NULL) {
struct utsname un;
if (uname(&un) == -1) {
_DtSimpleError(DtProgName,DtError, NULL, "uname", NULL);
nodename = XtNewString("nodename");
} else {
nodename = XtNewString(un.nodename);
}
}
_DtSvcProcessUnlock();
return nodename;
}

188
cde/lib/DtSvc/DtUtil1/Dnd.h Normal file
View File

@@ -0,0 +1,188 @@
/* $XConsortium: Dnd.h /main/3 1995/10/26 15:04:35 rswiston $ */
/*
* (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.
*/
#ifndef _Dt_Dnd_h
#define _Dt_Dnd_h
#include <Xm/DragIcon.h>
#include <Xm/DragC.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Constants
*/
/* Dnd Callback Reasons */
enum {
DtCR_DND_CONVERT_DATA,
DtCR_DND_CONVERT_DELETE,
DtCR_DND_DRAG_FINISH,
DtCR_DND_TRANSFER_DATA,
DtCR_DND_DROP_ANIMATE,
DtCR_DND_ROOT_TRANSFER
};
#define DtCR_DND_TRANSFER DtCR_DND_TRANSFER_DATA
/*
* Dnd Drag Start Resources
* dropOnRootCallback is private and should not be used
*/
#define DtNdropOnRootCallback "dropOnRootCallback"
#define DtCDropOnRootCallback "DropOnRootCallback"
#define DtNsourceIcon "sourceIcon"
#define DtCSourceIcon "SourceIcon"
#define DtNbufferIsText "bufferIsText"
#define DtCBufferIsText "BufferIsText"
/*
*Dnd Drop Register Resources
*/
#define DtNdropAnimateCallback "dropAnimateCallback"
#define DtCDropAnimateCallback "DropAnimateCallback"
#define DtNpreserveRegistration "preserveRegistration"
#define DtCPreserveRegistration "PreserveRegistration"
#define DtNregisterChildren "registerChildren"
#define DtCRegisterChildren "RegisterChildren"
#define DtNtextIsBuffer "textIsBuffer"
#define DtCTextIsBuffer "TextIsBuffer"
/*
* Types
*/
typedef enum {
DtDND_SUCCESS,
DtDND_FAILURE
} DtDndStatus;
typedef unsigned long DtDndProtocol;
enum {
DtDND_NOOP_TRANSFER = 0L,
DtDND_TEXT_TRANSFER = (1L << 0),
DtDND_FILENAME_TRANSFER = (1L << 1),
DtDND_BUFFER_TRANSFER = (1L << 2)
};
typedef struct _DtDndBuffer {
void * bp;
int size;
String name;
} DtDndBuffer;
typedef struct _DtDndContext {
DtDndProtocol protocol;
Cardinal numItems;
union {
XmString * strings;
String * files;
DtDndBuffer * buffers;
} data;
} DtDndContext;
/*
* Dnd Callback Structures
*/
typedef struct _DtDndConvertCallbackStruct {
int reason;
XEvent * event;
DtDndContext * dragData;
DtDndStatus status;
} DtDndConvertCallbackStruct, *DtDndConvertCallback;
typedef struct _DtDndDragFinishCallbackStruct {
int reason;
XEvent * event;
DtDndContext * dragData;
Widget sourceIcon;
} DtDndDragFinishCallbackStruct, *DtDndDragFinishCallback;
typedef struct _DtDndTransferCallbackStruct {
int reason;
XEvent * event;
Position x, y;
unsigned char operation;
DtDndContext * dropData;
Widget dragContext;
Boolean completeMove;
DtDndStatus status;
} DtDndTransferCallbackStruct, *DtDndTransferCallback;
typedef DtDndTransferCallbackStruct DtDndDropCallbackStruct, *DtDndDropCallback;
typedef struct _DtDndDropAnimateCallbackStruct {
int reason;
XEvent * event;
Position x, y;
unsigned char operation;
DtDndContext * dropData;
} DtDndDropAnimateCallbackStruct, *DtDndDropAnimateCallback;
/*
* Functions
*/
extern Widget DtDndCreateSourceIcon(
Widget widget,
Pixmap source,
Pixmap mask);
extern Widget DtDndDragStart(
Widget dragInitiator,
XEvent* event,
DtDndProtocol protocol,
Cardinal numItems,
unsigned char operations,
XtCallbackList convertCallback,
XtCallbackList dragFinishCallback,
ArgList argList,
Cardinal argCount);
extern Widget DtDndVaDragStart(
Widget dragInitiator,
XEvent* event,
DtDndProtocol protocol,
Cardinal numItems,
unsigned char operations,
XtCallbackList convertCallback,
XtCallbackList dragFinishCallback,
...);
extern void DtDndDropRegister(
Widget dropSite,
DtDndProtocol protocols,
unsigned char operations,
XtCallbackList transferCallback,
ArgList argList,
Cardinal argCount);
extern void DtDndVaDropRegister(
Widget dropSite,
DtDndProtocol protocols,
unsigned char operations,
XtCallbackList transferCallback,
...);
extern void DtDndDropUnregister(
Widget widget);
#ifdef __cplusplus
}
#endif
#endif /* _Dt_Dnd_h */

View File

@@ -0,0 +1,723 @@
/* $XConsortium: DndBuff.c /main/5 1996/06/21 17:30:55 ageorge $ */
/*********************************************************************
*
* File: DndBuff.c
*
* Description: Implementation of the Buffer Transfer routines
* FOR the DND Convenience API.
*
*********************************************************************
*
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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 <X11/Intrinsic.h>
#include <Xm/AtomMgr.h>
#include <Xm/DragC.h>
#include <Xm/DropSMgr.h>
#include <Xm/DropTrans.h>
#include "Dnd.h"
#include "DndP.h"
#include "DtSvcLock.h"
/*
* Buffer Transfer Protocol Function Prototypes
*/
static void dndBuffGetTargets(Boolean, Boolean, Atom**, Cardinal*);
static void dndBuffGetAvailTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndBuffGetExportTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndBuffGetImportTargets(DtDropInfo*, Atom**, Cardinal*);
static void dndBuffConvertInit(DtDragInfo*);
static Boolean dndBuffConvert(Widget, DtDragInfo*, Atom*, Atom*,
Atom*, XtPointer*, unsigned long*, int*,
XSelectionRequestEvent*);
static void dndBuffConvertFinish(DtDragInfo*);
static void dndBuffTransferTargets(DtDropInfo*,
Atom*, Cardinal, Atom**, Cardinal*);
static void dndBuffTransfer(Widget, DtDropInfo*, Atom*, Atom*, Atom*,
XtPointer, unsigned long*, int*);
static void dndBuffTransferFinish(DtDropInfo*);
/*
* Buffer Transfer Support Functions
*/
static void dndBufferDataToSelectionValue(DtDndBuffer *, Cardinal,
XtPointer *, unsigned long *, Boolean);
static void dndBufferLengthsToSelectionValue(DtDndBuffer *, Cardinal,
XtPointer *, unsigned long *);
static void dndBufferNamesToSelectionValue(DtDndBuffer *, Cardinal,
XtPointer *, unsigned long *);
static void dndTextSelectionValueToBuffer(Display *,
Atom *, XtPointer, unsigned long *, int *, String,
XtPointer *, unsigned long *,
DtDndBuffer **, Cardinal *);
static void dndSelectionValueToBuffer(XtPointer, unsigned long,
XtPointer, unsigned long, XtPointer, unsigned long,
DtDndBuffer **, Cardinal *);
/*
* Buffer Transfer Selection Targets
*/
static Atom XA_DT_BUFFER_DATA;
static Atom XA_DT_BUFFER_LENGTHS;
static Atom XA_DT_BUFFER_NAMES;
/*
* Buffer Transfer Protocol Methods
*/
static DtDndMethods dndBuffTransferProtocol = {
"DtDndBufferTransfer", /* name */
(DtDndProtocol)DtDND_BUFFER_TRANSFER, /* protocol */
DtDND_DRAG_SOURCE_DATA, /* sourceType */
dndBuffGetAvailTargets, /* getAvailTargets */
dndBuffGetExportTargets, /* getExportTargets */
dndBuffGetImportTargets, /* getImportTargets */
dndBuffConvertInit, /* convertInit */
dndBuffConvert, /* convert */
dndBuffConvertFinish, /* convertFinish */
dndBuffTransferTargets, /* transferTargets */
dndBuffTransfer, /* transfer */
dndBuffTransferFinish, /* transferFinish */
};
typedef struct _TransferState {
XtPointer dataValue;
unsigned long dataLength;
XtPointer lengthsValue;
unsigned long lengthsLength;
XtPointer namesValue;
unsigned long namesLength;
String dataLabel;
Atom textTarget;
} TransferState;
/*
* Buffer transfer protocol initialization
*/
DtDndMethods *
_DtDndBuffTransferProtocolInitialize(
Display * dpy)
{
_DtSvcProcessLock();
if (XA_DT_BUFFER_DATA == 0) {
XA_DT_BUFFER_DATA = DtGetAtom(dpy,"_DT_BUFFER_DATA");
XA_DT_BUFFER_LENGTHS = DtGetAtom(dpy,"_DT_BUFFER_LENGTHS");
XA_DT_BUFFER_NAMES = DtGetAtom(dpy,"_DT_BUFFER_NAMES");
}
_DtSvcProcessUnlock();
return &dndBuffTransferProtocol;
}
/*
* Returns export/import targets for buffer transfers
*/
static void
dndBuffGetTargets(
Boolean includeText,
Boolean owCompat,
Atom ** targets,
Cardinal * numTargets)
{
int ii = 0;
*numTargets = 3 + (includeText ? 2 : 0) + (owCompat ? 1 : 0);
*targets = (Atom *)XtMalloc(*numTargets * sizeof(Atom));
(*targets)[ii++] = XA_DT_BUFFER_DATA;
(*targets)[ii++] = XA_DT_BUFFER_LENGTHS;
(*targets)[ii++] = XA_DT_BUFFER_NAMES;
if (includeText) {
(*targets)[ii++] = XA_TEXT;
(*targets)[ii++] = XA_STRING;
}
if (owCompat) {
(*targets)[ii++] = XA_SUN_DATA_LABEL;
}
}
/*
* Returns available targets for buffer transfers
*/
static void
dndBuffGetAvailTargets(
DtDragInfo * dtDragInfo,
Atom ** availTargets,
Cardinal * numAvailTargets)
{
dndBuffGetTargets(True, True, availTargets, numAvailTargets);
}
/*
* Returns export targets for buffer transfers
*/
static void
dndBuffGetExportTargets(
DtDragInfo * dtDragInfo,
Atom ** exportTargets,
Cardinal * numExportTargets)
{
dndBuffGetTargets(dtDragInfo->bufferIsText, True,
exportTargets, numExportTargets);
}
/*
* Returns import targets for buffer transfers
*/
static void
dndBuffGetImportTargets(
DtDropInfo * dtDropInfo,
Atom ** importTargets,
Cardinal * numImportTargets)
{
dndBuffGetTargets(dtDropInfo->textIsBuffer, True,
importTargets, numImportTargets);
}
/*
* Initialize protocol specific part of drag data
*/
static void
dndBuffConvertInit(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
dragData->data.buffers = (DtDndBuffer *)
XtCalloc(dragData->numItems, sizeof(DtDndBuffer));
}
/*
* Convert the buffers into selection data
*/
static Boolean
dndBuffConvert(
Widget dragContext,
DtDragInfo * dtDragInfo,
Atom * selection,
Atom * target,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat,
XSelectionRequestEvent * selectionRequestEvent)
{
DtDndContext * dragData = dtDragInfo->dragData;
/*
* TEXT or STRING
* Convert the buffer data to a text selection
*/
if (*target == XA_TEXT || *target == XA_STRING) {
*returnType = XA_STRING;
*returnFormat = 8;
dndBufferDataToSelectionValue(
dragData->data.buffers, dragData->numItems,
returnValue, returnLength, True);
/*
* _SUN_DATA_LABEL
* Convert the first buffer name to a selection
*/
} else if (*target == XA_SUN_DATA_LABEL) {
*returnType = XA_STRING;
*returnFormat = 8;
*returnValue = XtNewString(dragData->data.buffers[0].name);
*returnLength = strlen(*returnValue)+1;
/*
* _DT_BUFFER_DATA
* Convert the buffer data to a selection
*/
} else if (*target == XA_DT_BUFFER_DATA) {
*returnType = XA_DT_BUFFER_DATA;
*returnFormat = 8;
dndBufferDataToSelectionValue(
dragData->data.buffers, dragData->numItems,
returnValue, returnLength, False);
/*
* _DT_BUFFER_LENGTHS
* Convert the buffer lengths to a selection
*/
} else if (*target == XA_DT_BUFFER_LENGTHS) {
*returnType = XA_INTEGER;
*returnFormat = 32;
dndBufferLengthsToSelectionValue(
dragData->data.buffers, dragData->numItems,
returnValue, returnLength);
/*
* _DT_BUFFER_NAMES
* Convert the buffer names to a selection
*/
} else if (*target == XA_DT_BUFFER_NAMES) {
*returnType = XA_STRING;
*returnFormat = 8;
dndBufferNamesToSelectionValue(
dragData->data.buffers, dragData->numItems,
returnValue, returnLength);
} else {
return False;
}
return True;
}
/*
* Clean up from the convert init proc
*/
static void
dndBuffConvertFinish(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
if (dragData->data.buffers) {
XtFree((char *)dragData->data.buffers);
dragData->data.buffers = NULL;
}
}
/*
* Returns the transfer targets selected from the export targets
* Prefer buffers over TEXT/STRING
*/
static void
dndBuffTransferTargets(
DtDropInfo * dtDropInfo,
Atom * exportTargets,
Cardinal numExportTargets,
Atom ** transferTargets,
Cardinal * numTransferTargets)
{
Boolean foundData, foundLengths, foundNames,
foundDataLabel, foundText, foundString;
int ii;
TransferState * xferState;
xferState = (TransferState *)XtCalloc(1,sizeof(TransferState));
dtDropInfo->transferInfo->clientData = (XtPointer)xferState;
foundData = foundLengths = foundNames = False;
foundDataLabel = foundText = foundString = False;
for (ii = 0; ii < numExportTargets; ii++) {
if (exportTargets[ii] == XA_DT_BUFFER_DATA) {
foundData = True;
} else if (exportTargets[ii] == XA_DT_BUFFER_LENGTHS) {
foundLengths = True;
} else if (exportTargets[ii] == XA_DT_BUFFER_NAMES) {
foundNames = True;
} else if (exportTargets[ii] == XA_SUN_DATA_LABEL) {
foundDataLabel = True;
} else if (exportTargets[ii] == XA_TEXT) {
foundText = True;
} else if (exportTargets[ii] == XA_STRING) {
foundString = True;
}
}
*numTransferTargets = 2; /* max number of transfer targets */
*transferTargets = (Atom *)XtMalloc(*numTransferTargets * sizeof(Atom));
ii = 0;
if (foundData && foundLengths && foundNames) {
*numTransferTargets = 2;
(*transferTargets)[ii++] = XA_DT_BUFFER_NAMES;
(*transferTargets)[ii++] = XA_DT_BUFFER_LENGTHS;
} else if (foundDataLabel && (foundText || foundString)) {
*numTransferTargets = 2;
(*transferTargets)[ii++] = XA_SUN_DATA_LABEL;
(*transferTargets)[ii++] = foundText ? XA_TEXT : XA_STRING;
xferState->textTarget = foundText ? XA_TEXT : XA_STRING;
} else if (foundText || foundString) {
*numTransferTargets = 1;
(*transferTargets)[ii++] = foundText ? XA_TEXT : XA_STRING;
} else {
*numTransferTargets = 0;
*transferTargets = NULL;
return;
}
}
/*
* Transfer the selection data into buffers
*/
static void
dndBuffTransfer(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * selection,
Atom * target,
Atom * type,
XtPointer value,
unsigned long * length,
int * format)
{
Display * display = XtDisplayOfObject(dropTransfer);
DtDndContext * dropData = dtDropInfo->dropData;
TransferState * xferState =
(TransferState *)dtDropInfo->transferInfo->clientData;
/*
* Ignore if we've already transferred
*/
if (dropData->data.buffers) {
XtFree(value);
return;
}
/*
* TEXT or STRING
*
* Convert the text selection into buffers
*/
if (*target == XA_TEXT || *target == XA_STRING) {
dndTextSelectionValueToBuffer(display,
type, value, length, format, xferState->dataLabel,
&(xferState->dataValue), &(xferState->dataLength),
&(dropData->data.buffers), &(dropData->numItems));
/*
* _SUN_DATA_LABEL
*
* Save the buffer name selection for later conversion
* Request the text data transfer
*/
} else if (*target == XA_SUN_DATA_LABEL &&
*type == XA_STRING &&
*format == 8) {
xferState->dataLabel = (String)value;
_DtDndTransferAdd(dropTransfer, dtDropInfo,
&(xferState->textTarget), 1);
/*
* _DT_BUFFER_DATA
*
* Save the buffer data selection for later conversion
*/
} else if (*target == XA_DT_BUFFER_DATA &&
*type == XA_DT_BUFFER_DATA &&
*format == 8) {
xferState->dataValue = value;
xferState->dataLength = *length;
dndSelectionValueToBuffer(
xferState->dataValue, xferState->dataLength,
xferState->lengthsValue, xferState->lengthsLength,
xferState->namesValue, xferState->namesLength,
&(dropData->data.buffers), &(dropData->numItems));
/*
* _DT_BUFFER_LENGTHS
*
* Save the buffer lengths selection for later conversion
* Request the buffer data transfer
*/
} else if (*target == XA_DT_BUFFER_LENGTHS &&
*type == XA_INTEGER &&
*format == 32) {
xferState->lengthsValue = value;
xferState->lengthsLength = *length;
_DtDndTransferAdd(dropTransfer, dtDropInfo,
&XA_DT_BUFFER_DATA, 1);
/*
* _DT_BUFFER_NAMES
*
* Save the buffer names selection for later conversion
*/
} else if (*target == XA_DT_BUFFER_NAMES &&
*type == XA_STRING &&
*format == 8) {
xferState->namesValue = value;
xferState->namesLength = *length;
/*
* Ignore transfers we don't understand
*/
} else {
XtFree(value);
return;
}
}
/*
* Clean up from the transfer proc
*/
static void
dndBuffTransferFinish(
DtDropInfo * dtDropInfo)
{
DtDndContext * dropData = dtDropInfo->dropData;
TransferState * xferState =
(TransferState *)dtDropInfo->transferInfo->clientData;
dtDropInfo->transferInfo->clientData = NULL;
if (xferState->dataValue)
XtFree(xferState->dataValue);
if (xferState->lengthsValue)
XtFree(xferState->lengthsValue);
if (xferState->namesValue)
XtFree(xferState->namesValue);
if (xferState->dataLabel)
XtFree(xferState->dataLabel);
XtFree((char *)xferState);
XtFree((char *)dropData->data.buffers);
}
/*
* Convert buffer data into a single chunk of memory
*/
static void
dndBufferDataToSelectionValue(
DtDndBuffer * buffers,
Cardinal numBuffers,
XtPointer * returnValue,
unsigned long * returnLength,
Boolean isText)
{
int ii;
char *bufferPtr;
*returnLength = 0;
for (ii = 0; ii < numBuffers; ii++) {
*returnLength += buffers[ii].size;
if (isText) {
*returnLength += 1;
}
}
*returnValue = (XtPointer) XtMalloc(*returnLength);
bufferPtr = (XtPointer)*returnValue;
for (ii = 0; ii < numBuffers; ii++) {
memcpy(bufferPtr, buffers[ii].bp, buffers[ii].size);
bufferPtr += buffers[ii].size;
if (isText) {
*bufferPtr = '\0';
bufferPtr++;
}
}
if (isText) {
*returnLength -= 1;
}
}
/*
* Convert buffer lengths into a list of integers
*/
static void
dndBufferLengthsToSelectionValue(
DtDndBuffer * buffers,
Cardinal numBuffers,
XtPointer * returnValue,
unsigned long * returnLength)
{
int ii;
unsigned long * lengths;
*returnLength = numBuffers;
*returnValue = (XtPointer) XtMalloc(*returnLength * sizeof(long));
lengths = (unsigned long *)*returnValue;
for (ii = 0; ii < numBuffers; ii++) {
lengths[ii] = buffers[ii].size;
}
}
/*
* Convert buffer names into a single chunk of memory
*/
static void
dndBufferNamesToSelectionValue(
DtDndBuffer * buffers,
Cardinal numBuffers,
XtPointer * returnValue,
unsigned long * returnLength)
{
int ii, len;
char * namePtr;
*returnLength = 0;
for (ii = 0; ii < numBuffers; ii++) {
if (buffers[ii].name != NULL) {
*returnLength += strlen(buffers[ii].name) + 1;
} else {
*returnLength += 1;
}
}
*returnValue = (XtPointer) XtMalloc(*returnLength);
namePtr = (char *)*returnValue;
for (ii = 0; ii < numBuffers; ii++) {
if (buffers[ii].name == NULL) {
*namePtr = '\0';
namePtr++;
} else {
len = strlen(buffers[ii].name) + 1;
memcpy(namePtr, buffers[ii].name, len);
namePtr += len;
}
}
}
/*
* Split text selection data into multiple buffers
*/
static void
dndTextSelectionValueToBuffer(
Display * display,
Atom * type,
XtPointer value,
unsigned long * length,
int * format,
String dataLabel,
XtPointer * returnValue,
unsigned long * returnLength,
DtDndBuffer ** buffers,
Cardinal * numBuffers)
{
XTextProperty textProp;
char ** text;
char * bufPtr;
int ii, status, textCount, textLen;
textProp.value = (unsigned char *)value;
textProp.encoding = *type;
textProp.format = *format;
textProp.nitems = *length;
status = XmbTextPropertyToTextList(display, &textProp,
&text, &textCount);
if (status != Success) {
*numBuffers = 1;
(*buffers) = (DtDndBuffer *)XtMalloc(sizeof(DtDndBuffer));
(*buffers)[0].bp = value;
(*buffers)[0].size = *length;
(*buffers)[0].name = dataLabel ? dataLabel : (String)NULL;
*returnValue = value;
*returnLength = *length;
return;
}
*numBuffers = textCount;
(*buffers) = (DtDndBuffer *)XtMalloc(*numBuffers * sizeof(DtDndBuffer));
textLen = 0;
for (ii = 0; ii < *numBuffers; ii++) {
(*buffers)[ii].size = strlen(text[ii]);
(*buffers)[ii].name = (String)NULL;
textLen += (*buffers)[ii].size+1;
}
(*returnValue) = XtMalloc(textLen * sizeof(char));
(*returnLength) = textLen;
bufPtr = (*returnValue);
for (ii = 0; ii < *numBuffers; ii++) {
(*buffers)[ii].bp = bufPtr;
memcpy(bufPtr,text[ii],(*buffers)[ii].size+1);
bufPtr += (*buffers)[ii].size+1;
}
if (dataLabel)
(*buffers)[0].name = dataLabel;
XtFree(value);
XFreeStringList(text);
}
/*
* Split data/lengths/names selection data into multiple buffers
*/
static void
dndSelectionValueToBuffer(
XtPointer dataValue,
unsigned long dataLength,
XtPointer lengthsValue,
unsigned long lengthsLength,
XtPointer namesValue,
unsigned long namesLength,
DtDndBuffer ** buffers,
Cardinal * numBuffers)
{
int ii;
char * bufPtr;
char * namePtr;
unsigned long * lenList;
if (lengthsLength == 0 || lengthsValue == NULL) {
*numBuffers = 1;
(*buffers) = (DtDndBuffer *)XtMalloc(sizeof(DtDndBuffer));
(*buffers)[0].bp = dataValue;
(*buffers)[0].size = dataLength;
(*buffers)[0].name = (String)NULL;
return;
}
*numBuffers = lengthsLength;
(*buffers) = (DtDndBuffer *)XtMalloc(*numBuffers * sizeof(DtDndBuffer));
lenList = (unsigned long *)lengthsValue;
bufPtr = dataValue;
namePtr = namesValue;
for (ii = 0; ii < *numBuffers; ii++) {
(*buffers)[ii].bp = bufPtr;
(*buffers)[ii].size = lenList[ii];
(*buffers)[ii].name = namePtr;
bufPtr += lenList[ii];
namePtr = strchr(namePtr, '\0');
namePtr++;
}
}

View File

@@ -0,0 +1,819 @@
/* $XConsortium: DndDrag.c /main/5 1996/09/27 19:00:40 drk $ */
/*********************************************************************
*
* File: DndDrag.c
*
* Description: Implemenation of DND Drag Initator
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <X11/Intrinsic.h>
#include <Xm/AtomMgr.h>
#include <Xm/DragDrop.h>
#include <Xm/DragC.h>
#include <Xm/DragCP.h>
#include <Xm/DragOverSP.h>
#include "Dnd.h"
#include "DndP.h"
#include "DtSvcLock.h"
/*
* Drag Initiator Callbacks
*/
static Boolean dndConvertProc(Widget, Atom*, Atom*, Atom*, XtPointer *,
unsigned long*, int*);
static void dndAppConvert(Widget, int, XEvent*, DtDragInfo*);
static void dndDropStartCallback(Widget, XtPointer, XtPointer);
static void dndDropFinishCallback(Widget, XtPointer, XtPointer);
static void dndDragDropFinishCallback(Widget, XtPointer, XtPointer);
static void dndTopLevelEnterCallback(Widget, XtPointer, XtPointer);
static void dndTopLevelLeaveCallback(Widget, XtPointer, XtPointer);
/*
* Drag Initiator Resources
*/
typedef struct {
XtCallbackList dropOnRootCallback;
Widget sourceIcon;
Boolean bufferIsText;
} DragSettings;
#define Offset(field) XtOffsetOf(DragSettings, field)
static XtResource dragResources[] = {
{ DtNdropOnRootCallback, DtCDropOnRootCallback,
XtRCallback, sizeof(XtCallbackList), Offset(dropOnRootCallback),
XtRImmediate, (XtPointer)NULL},
{ DtNsourceIcon, DtCSourceIcon,
XtRWidget, sizeof(Widget), Offset(sourceIcon),
XtRImmediate, (XtPointer)NULL },
{ DtNbufferIsText, DtCBufferIsText,
XtRBoolean, sizeof(Boolean), Offset(bufferIsText),
XtRImmediate, (XtPointer)False },
};
#undef Offset
/*
* DtDndVaDragStart
*
* Drag Start - varargs version
*/
Widget
DtDndVaDragStart(
Widget dragInitiator,
XEvent* event,
DtDndProtocol protocol,
Cardinal numItems,
unsigned char operations,
XtCallbackList dragConvertCallback,
XtCallbackList dragFinishCallback,
...)
{
Widget dragContext;
va_list vaList;
ArgList argList;
Cardinal argCount;
_DtSvcWidgetToAppContext(dragInitiator);
_DtSvcAppLock(app);
va_start(vaList, dragFinishCallback);
argCount = _DtDndCountVarArgs(vaList);
va_end(vaList);
va_start(vaList, dragFinishCallback);
_DtDndArgListFromVarArgs(vaList, argCount, &argList, &argCount);
va_end(vaList);
dragContext = DtDndDragStart(dragInitiator, event, protocol,
numItems, operations,
dragConvertCallback, dragFinishCallback,
argList, argCount);
XtFree((char *)argList);
_DtSvcAppUnlock(app);
return dragContext;
}
/*
* DtDndVaDragStart
*
* Drag Start - arglist version
*/
Widget
DtDndDragStart(
Widget dragInitiator,
XEvent* event,
DtDndProtocol protocol,
Cardinal numItems,
unsigned char operations,
XtCallbackList dragConvertCallback,
XtCallbackList dragFinishCallback,
ArgList argList,
Cardinal argCount)
{
XtCallbackRec dragDropFinishCbRec[] = { {dndDragDropFinishCallback,
NULL}, {NULL, NULL} };
XtCallbackRec topLevelEnterCbRec[] = { {dndTopLevelEnterCallback,
NULL}, {NULL, NULL} };
XtCallbackRec topLevelLeaveCbRec[] = { {dndTopLevelLeaveCallback,
NULL}, {NULL, NULL} };
XtCallbackRec dropStartCbRec[] = { {dndDropStartCallback,
NULL}, {NULL, NULL} };
XtCallbackRec dropFinishCbRec[] = { {dndDropFinishCallback,
NULL}, {NULL, NULL} };
Display * display = XtDisplayOfObject(dragInitiator);
Screen * screen = XtScreenOfObject(dragInitiator);
Window rootWindow = RootWindowOfScreen(screen);
DtDragInfo * dtDragInfo;
DragSettings settings;
DtDndDragSource sourceType;
DtDndTransfer * transfer;
Arg * args;
int ii, nn, savedEventType;
Atom * exportTargets;
Cardinal numExportTargets;
_DtSvcWidgetToAppContext(dragInitiator);
_DtSvcAppLock(app);
/*
* Reject the drag if noop or multiple protocols specified
*/
switch (protocol) {
case DtDND_BUFFER_TRANSFER:
case DtDND_FILENAME_TRANSFER:
case DtDND_TEXT_TRANSFER:
break;
case DtDND_NOOP_TRANSFER:
default:
_DtSvcAppUnlock(app);
return (Widget)NULL;
}
/*
* Parse resources into dragResources
*/
XtGetSubresources(dragInitiator, &settings,
(String)NULL, (String)NULL,
dragResources, XtNumber(dragResources),
argList, argCount);
/*
* Initialize DragInfo
*/
dtDragInfo = (DtDragInfo *) XtMalloc(sizeof(DtDragInfo));
dtDragInfo->dragInitiator = dragInitiator;
dtDragInfo->dragContext = NULL;
dtDragInfo->protocol = protocol;
dtDragInfo->numItems = numItems;
dtDragInfo->operations = operations;
dtDragInfo->sourceIcon = settings.sourceIcon;
dtDragInfo->bufferIsText = settings.bufferIsText;
dtDragInfo->dragData = NULL;
dtDragInfo->inRoot = False;
dtDragInfo->status = DtDND_SUCCESS;
dtDragInfo->clientData = NULL;
dtDragInfo->backdropWindow
= DtWsmGetCurrentBackdropWindow(display, rootWindow);
dtDragInfo->dragConvertCallback
= _DtDndCopyCallbackList(dragConvertCallback);
dtDragInfo->dragFinishCallback
= _DtDndCopyCallbackList(dragFinishCallback);
dtDragInfo->dropOnRootCallback
= _DtDndCopyCallbackList(settings.dropOnRootCallback);
dtDragInfo->dragData = (DtDndContext *)XtCalloc(1,sizeof(DtDndContext));
dtDragInfo->dragData->protocol = dtDragInfo->protocol;
dtDragInfo->dragData->numItems = 0;
/*
* Get data transfer method
* Use the transfer targets as export targets
*/
dtDragInfo->transfer = _DtDndCreateExportTransfer(dtDragInfo);
exportTargets = dtDragInfo->transfer->targets;
numExportTargets = dtDragInfo->transfer->numTargets;
#ifdef DEBUG
printf("DtDndDragStart: drag from widget 0x%p\n", dragInitiator);
_DtDndPrintTransfers(display,dtDragInfo->transfer,1);
#endif
/*
* Set up drag icon
*/
if (numItems > 1) {
sourceType = DtDND_DRAG_SOURCE_MULTIPLE;
} else {
sourceType = dtDragInfo->transfer->methods->sourceType;
}
_DtDndSelectDragSource(dragInitiator, sourceType,
dtDragInfo->sourceIcon);
/*
* Construct argument list
*/
#define NUM_DRAG_ARGS 30
args = (Arg *) XtMalloc(sizeof(Arg) * (NUM_DRAG_ARGS + argCount));
#undef NUM_DRAG_ARGS
/*
* Copy in passed arguments
*/
nn = 0;
for (ii = 0; ii < argCount; ii++) {
XtSetArg(args[nn], argList[ii].name, argList[ii].value); nn++;
}
/*
* Set basic drag start arguments
*/
XtSetArg(args[nn], XmNexportTargets, exportTargets);
nn++;
XtSetArg(args[nn], XmNnumExportTargets, numExportTargets);
nn++;
XtSetArg(args[nn], XmNdragOperations, operations);
nn++;
XtSetArg(args[nn], XmNblendModel, XmBLEND_ALL);
nn++;
XtSetArg(args[nn], XmNcursorBackground, WhitePixelOfScreen(screen));
nn++;
XtSetArg(args[nn], XmNcursorForeground, BlackPixelOfScreen(screen));
nn++;
XtSetArg(args[nn], XmNclientData, dtDragInfo);
nn++;
if (dtDragInfo->sourceIcon != NULL) {
XtSetArg(args[nn],XmNsourcePixmapIcon, dtDragInfo->sourceIcon);
nn++;
XtSetArg(args[nn],XmNsourceCursorIcon, dtDragInfo->sourceIcon);
nn++;
}
/*
* Set up DnD callbacks for Motif
*/
XtSetArg(args[nn], XmNconvertProc, dndConvertProc);
nn++;
dragDropFinishCbRec[0].closure = (XtPointer) dtDragInfo;
dropFinishCbRec[0].closure = (XtPointer) dtDragInfo;
dtDragInfo->dragDropFinishCallback
= _DtDndCopyCallbackList(dragDropFinishCbRec);
dtDragInfo->dropFinishCallback
= _DtDndCopyCallbackList(dropFinishCbRec);
XtSetArg(args[nn], XmNdragDropFinishCallback, dtDragInfo->dragDropFinishCallback);
nn++;
XtSetArg(args[nn], XmNdropFinishCallback, dtDragInfo->dropFinishCallback);
nn++;
/*
* Only use top-level-enter/leave callbacks if also doing drop-on-root
*/
if (dtDragInfo->dropOnRootCallback != NULL) {
topLevelEnterCbRec[0].closure = (XtPointer) dtDragInfo;
topLevelLeaveCbRec[0].closure = (XtPointer) dtDragInfo;
dropStartCbRec[0].closure = (XtPointer) dtDragInfo;
dtDragInfo->topLevelEnterCallback
= _DtDndCopyCallbackList(topLevelEnterCbRec);
dtDragInfo->topLevelLeaveCallback
= _DtDndCopyCallbackList(topLevelLeaveCbRec);
dtDragInfo->dropStartCallback
= _DtDndCopyCallbackList(dropStartCbRec);
XtSetArg(args[nn], XmNtopLevelEnterCallback, dtDragInfo->topLevelEnterCallback);
nn++;
XtSetArg(args[nn], XmNtopLevelLeaveCallback, dtDragInfo->topLevelLeaveCallback);
nn++;
XtSetArg(args[nn], XmNdropStartCallback, dtDragInfo->dropStartCallback);
nn++;
}
/*
* Fake a button press. This is necessary because Motif requires
* a drag to start on a button press. We need to be able to start
* a drag on a mouse motion event when Bselect is held down. Since
* the motion event has the fields necessary for Motif this works.
*/
savedEventType = event->type;
if (event->type == MotionNotify) {
event->type = ButtonPress;
}
/*
* Start the drag
*/
dtDragInfo->dragContext = XmDragStart(dragInitiator, event, args, nn);
XtFree((char *)args);
event->type = savedEventType;
_DtSvcAppUnlock(app);
return (dtDragInfo->dragContext);
}
/*********************************************************************
*
* Drag Initiator Callbacks
*
*********************************************************************/
/*
* dndDropStartCallback
*
*
*/
static void
dndDropStartCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
DtDndContext *dragData;
XmDragContext xmDragContext = (XmDragContext)dtDragInfo->dragContext;
XmDropStartCallbackStruct *xmDropInfo = (XmDropStartCallback) callData;
DtDndTransferCallbackStruct dropCallData;
int posOffsetX, posOffsetY;
/*
* If the user has cancelled the drop, or the drop isn't on the
* root, or there are no dropOnRoot or convert callbacks
* then reject the drop.
*/
if (xmDragContext->drag.dragCompletionStatus == XmDROP_CANCEL ||
dtDragInfo->inRoot == False ||
dtDragInfo->dropOnRootCallback == NULL ||
dtDragInfo->dragConvertCallback == NULL ) {
xmDropInfo->dropSiteStatus = XmINVALID_DROP_SITE;
xmDropInfo->dropAction = XmDROP_CANCEL;
return;
}
/*
* The following is to handle the dropOnRoot situation.
* We handle both the convert and transfer sides of the
* transaction here. First we get the application drag data
* and then we call the application dropOnRoot callback.
*/
/*
* Initialize protocol specific dragData
*/
dtDragInfo->dragData->numItems = dtDragInfo->numItems;
(*dtDragInfo->transfer->methods->convertInit)(dtDragInfo);
/*
* Invoke the application convert callback
*/
dndAppConvert(dragContext, DtCR_DND_CONVERT_DATA,
xmDropInfo->event, dtDragInfo);
if (dtDragInfo->status == DtDND_FAILURE) {
return;
}
/*
* Setup dropOnRootcall data and invoke the dropOnroot callback
*/
_DtDndGetIconOffset(dtDragInfo->dragContext,
dtDragInfo->transfer->methods->sourceType,
&posOffsetX, &posOffsetY);
dropCallData.reason = DtCR_DND_ROOT_TRANSFER;
dropCallData.event = xmDropInfo->event;
dropCallData.x = xmDropInfo->x + posOffsetX;
dropCallData.y = xmDropInfo->y + posOffsetY;
dropCallData.operation = xmDropInfo->operation;
dropCallData.dropData = dtDragInfo->dragData;
dropCallData.completeMove = False;
dropCallData.status = DtDND_SUCCESS;
_DtDndCallCallbackList(dragContext, dtDragInfo->dropOnRootCallback,
(XtPointer)&dropCallData);
/*
* Tell Motif that the root is a valid drop site
*/
xmDropInfo->dropSiteStatus = XmVALID_DROP_SITE;
xmDropInfo->dropAction = XmDROP;
}
/*
* dndConvertProc
*
*
*/
static Boolean
dndConvertProc(
Widget dragContext,
Atom *selection,
Atom *target,
Atom *returnType,
XtPointer *returnValue,
unsigned long *returnLength,
int *returnFormat)
{
Atom realSelectionAtom; /* Motif hides the selection atom */
DtDragInfo *dtDragInfo = NULL;
XSelectionRequestEvent *selectionRequestEvent;
Boolean status;
#ifdef DEBUG
{
Display *display = XtDisplayOfObject(dragContext);
char *atomname = XGetAtomName(display,*target);
printf("dndConvertProc: target = %s\n",(atomname ? atomname : "Null"));
if (atomname) XFree(atomname);
}
#endif
/*
* Get the DtDragInfo
*/
XtVaGetValues(dragContext, XmNclientData, &dtDragInfo, NULL);
if (dtDragInfo == NULL || dtDragInfo->status == DtDND_FAILURE) {
return False;
}
/*
* Get selection request event
*/
XtVaGetValues(dragContext, XmNiccHandle, &realSelectionAtom, NULL);
selectionRequestEvent = XtGetSelectionRequest(dragContext,
realSelectionAtom, NULL); /* REMIND: NULL for atomic transfer */
/*
* Get the application drag data if necessary
*/
if (dtDragInfo->dragData->numItems == 0) {
dtDragInfo->dragData->numItems = dtDragInfo->numItems;
(*dtDragInfo->transfer->methods->convertInit)(dtDragInfo);
dndAppConvert(dragContext, DtCR_DND_CONVERT_DATA,
(XEvent *)selectionRequestEvent, dtDragInfo);
if (dtDragInfo->status == DtDND_FAILURE) {
return False;
}
}
/*
* Handle transfer protocol independent target conversions
*/
if (*target == XA_TARGETS) {
/*
* TARGETS Construct a list of targets consisting of those
* the dnd library supports plus those supported by
* the drag initiator.
*/
int ii, LIBRARY_TARGETS = 6;
Atom * availTargets;
Atom * allTargets;
Cardinal numAvailTargets;
Cardinal numAllTargets;
(*dtDragInfo->transfer->methods->getAvailTargets)(dtDragInfo,
&availTargets, &numAvailTargets);
numAllTargets = numAvailTargets + LIBRARY_TARGETS;
allTargets = (Atom *)XtMalloc(sizeof(Atom) * numAllTargets);
for (ii = 0; ii < numAvailTargets; ii++) {
allTargets[ii] = availTargets[ii];
}
XtFree((char *)availTargets);
ii = numAvailTargets;
allTargets[ii++] = XA_TARGETS;
allTargets[ii++] = XA_TIMESTAMP;
allTargets[ii++] = XA_MULTIPLE;
allTargets[ii++] = XA_HOST_NAME;
allTargets[ii++] = XA_SUN_FILE_HOST_NAME;
allTargets[ii++] = XA_DELETE;
*returnType = XA_ATOM;
*returnFormat = 32;
*returnValue = (XtPointer)allTargets;
*returnLength = numAllTargets * sizeof(Atom)/4;
status = True;
} else if (*target == XA_TIMESTAMP || *target == XA_MULTIPLE) {
/*
* TIMESTAMP and MULTIPLE are handled by the Intrinsics
*/
status = True;
} else if (*target == XA_HOST_NAME ||
*target == XA_SUN_FILE_HOST_NAME) {
/*
* HOST_NAME, _SUN_FILE_HOST_NAME The name of this host
*/
*returnType = XA_STRING;
*returnValue = (XtPointer)XtNewString(_DtDndGetHostName());
*returnLength = strlen((char *)*returnValue) + 1;
*returnFormat = 8;
status = True;
} else if (*target == XA_DELETE) {
/*
* DELETE Set up convert callback data to specify
* deletion and invoke the application-defined
* convertCallback() to perform the delete.
*/
*returnType = XA_NULL;
*returnFormat = 32;
*returnValue = (XtPointer) NULL;
*returnLength = 0;
dndAppConvert(dragContext, DtCR_DND_CONVERT_DELETE,
(XEvent *)selectionRequestEvent, dtDragInfo);
status = True;
} else if (*target == XA_SUN_ENUM_COUNT) {
/*
* _SUN_ENUMERATION_COUNT The number of items available
*/
int *count = XtNew(int);
if (dtDragInfo->dragData->numItems == 1) {
count[0] = 1;
} else {
count[0] = 0;
dtDragInfo->status = DtDND_FAILURE;
}
*returnType = XA_INTEGER;
*returnValue = (XtPointer)count;
*returnLength = 1;
*returnFormat = 32;
status = True;
} else {
/*
* Invoke protocol specific convert method
*/
status = (*dtDragInfo->transfer->methods->convert)(
dragContext, dtDragInfo,
selection, target,
returnType, returnValue,
returnLength, returnFormat,
selectionRequestEvent);
}
return status;
}
/*
* dndAppConvert
*
* Call the application convert callback
*/
static void
dndAppConvert(
Widget dragContext,
int reason,
XEvent * event,
DtDragInfo * dtDragInfo)
{
DtDndConvertCallbackStruct convertCallData;
convertCallData.reason = reason;
convertCallData.event = event;
convertCallData.dragData = dtDragInfo->dragData;
convertCallData.status = DtDND_SUCCESS;
_DtDndCallCallbackList(dragContext, dtDragInfo->dragConvertCallback,
(XtPointer)&convertCallData);
dtDragInfo->status = convertCallData.status;
if (reason == DtCR_DND_CONVERT_DATA &&
dtDragInfo->dragData->numItems <= 0) {
dtDragInfo->status = DtDND_FAILURE;
}
}
/*
* dndDropFinishCallback
*
* Handle drop-on-root case
*/
static void
dndDropFinishCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
XmDropFinishCallbackStruct *xmDropFinishCallData =
(XmDropFinishCallbackStruct *) callData;
if (dtDragInfo->dropOnRootCallback != NULL &&
dtDragInfo->inRoot &&
xmDropFinishCallData->dropSiteStatus == XmVALID_DROP_SITE) {
xmDropFinishCallData->completionStatus = XmDROP_SUCCESS;
XtVaSetValues(dtDragInfo->dragContext,
XmNblendModel, XmBLEND_NONE, NULL);
}
}
/*
* dndDragDropFinishCallback
*
* Call the application dragFinishCallback
*/
static void
dndDragDropFinishCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
XmDragDropFinishCallbackStruct *xmDndFinishInfo =
(XmDragDropFinishCallbackStruct *)callData;
DtDragInfo *dtDragInfo = (DtDragInfo *)clientData;
DtDndDragFinishCallbackStruct dragFinishCallData;
/*
* Invoke application dragFinishCallback
*/
dragFinishCallData.reason = DtCR_DND_DRAG_FINISH;
dragFinishCallData.event = xmDndFinishInfo->event;
dragFinishCallData.sourceIcon = dtDragInfo->sourceIcon;
dragFinishCallData.dragData = dtDragInfo->dragData;
_DtDndCallCallbackList(dragContext, dtDragInfo->dragFinishCallback,
(XtPointer)&dragFinishCallData);
/*
* Restore motif default drag cursors
*/
_DtDndSelectDragSource(dragContext, DtDND_DRAG_SOURCE_DEFAULT, NULL);
/*
* Invoke protocol specific convertFinish
*/
(*dtDragInfo->transfer->methods->convertFinish)(dtDragInfo);
/*
* Free data structures allocated during the drag
*/
XtFree((char *)dtDragInfo->transfer->targets);
XtFree((char *)dtDragInfo->transfer);
XtFree((char *)dtDragInfo->dragConvertCallback);
XtFree((char *)dtDragInfo->dragFinishCallback);
XtFree((char *)dtDragInfo->dragDropFinishCallback);
XtFree((char *)dtDragInfo->dropFinishCallback);
if (dtDragInfo->dropOnRootCallback != NULL) {
XtFree((char *)dtDragInfo->topLevelEnterCallback);
XtFree((char *)dtDragInfo->topLevelLeaveCallback);
XtFree((char *)dtDragInfo->dropStartCallback);
}
XtFree((char *)dtDragInfo->dropOnRootCallback);
XtFree((char *)dtDragInfo->dragData);
XtFree((char *)dtDragInfo);
}
/*
* dndTopLevelEnterCallback -- Support for drop-on-root callback.
* When a drop-on-root callback has been set, determines if
* the drag has entered the root window (or equivalents)
* and sneakily changes Motif's idea that the root is an
* invalid drop site to think that it's really a valid one.
* Also updates dtDragInfo.inRoot as needed.
*/
static void
dndTopLevelEnterCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
XmTopLevelEnterCallbackStruct *xmEnterInfo =
(XmTopLevelEnterCallbackStruct *) callData;
DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
XmDragContext xmDragContext = (XmDragContext) dragContext;
XmDragOverShellWidget dragOverShell = xmDragContext->drag.curDragOver;
if (xmEnterInfo->window == RootWindowOfScreen(xmEnterInfo->screen) ||
dtDragInfo->backdropWindow == xmEnterInfo->window ) {
dragOverShell->drag.cursorState = XmVALID_DROP_SITE;
_XmDragOverChange((Widget)dragOverShell,
dragOverShell->drag.cursorState);
dtDragInfo->inRoot = True;
} else {
dtDragInfo->inRoot = False;
}
}
/*
* dndTopLevelLeaveCallback -- Support for drop-on-root callback.
* When a drop-on-root callback has been set, determines if
* the drag is exiting the root window and restores Motif's
* internal state back to thinking that the root window is
* an invalid drop site. We don't update dtDragInfo->inRoot
* here since the top-level-leave callback is called before
* the drop callback which needs to know if we're in the root
* or not.
*/
static void
dndTopLevelLeaveCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
XmTopLevelLeaveCallbackStruct *xmLeaveInfo =
(XmTopLevelLeaveCallbackStruct *) callData;
DtDragInfo *dtDragInfo = (DtDragInfo *) clientData;
XmDragContext xmDragContext = (XmDragContext) dragContext;
XmDragOverShellWidget dragOverShell = xmDragContext->drag.curDragOver;
if (xmLeaveInfo->window == RootWindowOfScreen(xmLeaveInfo->screen) ||
dtDragInfo->backdropWindow == xmLeaveInfo->window ) {
dragOverShell->drag.cursorState = XmINVALID_DROP_SITE;
_XmDragOverChange((Widget)dragOverShell,
dragOverShell->drag.cursorState);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,644 @@
/* $TOG: DndFile.c /main/5 1998/04/09 17:48:19 mgreess $ */
/*********************************************************************
*
* File: DndFile.c
*
* Description: Implementation of the File Transfer routines
* for the DND Convenience API.
*
*********************************************************************
*
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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 <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <X11/Intrinsic.h>
#include <Xm/AtomMgr.h>
#include <Xm/DragC.h>
#include <Xm/DropSMgr.h>
#include <Xm/DropTrans.h>
#include <Tt/tt_c.h>
#include "Dnd.h"
#include "DndP.h"
#include "DtSvcLock.h"
/*
* File Transfer Protocol Function Prototypes
*/
static void dndFileGetTargets(Boolean, Boolean, Atom**, Cardinal*);
static void dndFileGetAvailTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndFileGetExportTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndFileGetImportTargets(DtDropInfo*, Atom**, Cardinal*);
static void dndFileConvertInit(DtDragInfo*);
static Boolean dndFileConvert(Widget, DtDragInfo*, Atom*, Atom*,
Atom*, XtPointer*, unsigned long*, int*,
XSelectionRequestEvent*);
static void dndFileConvertFinish(DtDragInfo*);
static void dndFileTransferTargets(DtDropInfo*,
Atom*, Cardinal, Atom**, Cardinal*);
static void dndFileTransfer(Widget, DtDropInfo*, Atom*, Atom*, Atom*,
XtPointer, unsigned long*, int*);
static void dndFileTransferFinish(DtDropInfo*);
/*
* File Transfer Support Functions
*/
static Boolean dndFileContentsToSelectionValue(String,
Atom*, XtPointer*, unsigned long*, int*);
static Boolean dndFileListToSelectionValue(String*, Cardinal, Boolean,
Atom*, XtPointer*, unsigned long*, int*);
static Boolean dndSelectionValueToFileList(Atom, XtPointer, unsigned long, int,
Boolean, String**, Cardinal*);
static String dndFileEncode(String, Boolean);
static String dndFileDecode(String, Boolean);
/*
* File Transfer Selection Targets
*/
static Atom XA_FILE_NAME;
static Atom XA_DT_NETFILE;
/*
* File Transfer Protocol Methods
*/
static DtDndMethods dndFileTransferProtocol = {
"DtDndFileNameTransfer", /* name */
(DtDndProtocol)DtDND_FILENAME_TRANSFER, /* protocol */
DtDND_DRAG_SOURCE_DATA, /* sourceType */
dndFileGetAvailTargets, /* getAvailTargets */
dndFileGetExportTargets, /* getExportTargets */
dndFileGetImportTargets, /* getImportTargets */
dndFileConvertInit, /* convertInit */
dndFileConvert, /* convert */
dndFileConvertFinish, /* convertFinish */
dndFileTransferTargets, /* transferTargets */
dndFileTransfer, /* transfer */
dndFileTransferFinish, /* transferFinish */
};
typedef struct _ConvertState {
Boolean owCompat;
} ConvertState;
/*
* File transfer protocol initialization
*/
DtDndMethods *
_DtDndFileTransferProtocolInitialize(
Display * dpy)
{
_DtSvcProcessLock();
if (XA_FILE_NAME == 0) {
XA_FILE_NAME = DtGetAtom(dpy,"FILE_NAME");
XA_DT_NETFILE = DtGetAtom(dpy,"_DT_NETFILE");
}
_DtSvcProcessUnlock();
return &dndFileTransferProtocol;
}
/*
* Returns generic export/import targets for filename transfers
*/
static void
dndFileGetTargets(
Boolean doHost,
Boolean owCompat,
Atom ** targets,
Cardinal * numTargets)
{
int ii = 0;
*numTargets = 2 + (doHost ? 1 : 0) + (owCompat ? 4 : 0);
*targets = (Atom *)XtMalloc(*numTargets * sizeof(Atom));
(*targets)[ii++] = XA_DT_NETFILE;
(*targets)[ii++] = XA_FILE_NAME;
if (doHost) {
(*targets)[ii++] = XA_HOST_NAME;
}
if (owCompat) {
(*targets)[ii++] = XA_TEXT;
(*targets)[ii++] = XA_STRING;
(*targets)[ii++] = XA_SUN_DATA_LABEL;
(*targets)[ii++] = XA_SUN_ATM_METHODS;
}
}
/*
* Returns available targets for filename transfers
*/
static void
dndFileGetAvailTargets(
DtDragInfo * dtDragInfo,
Atom ** availTargets,
Cardinal * numAvailTargets)
{
dndFileGetTargets(True, True, availTargets, numAvailTargets);
}
/*
* Returns export targets for filename transfers
*/
static void
dndFileGetExportTargets(
DtDragInfo * dtDragInfo,
Atom ** exportTargets,
Cardinal * numExportTargets)
{
dndFileGetTargets(True, False, exportTargets, numExportTargets);
}
/*
* Returns import targets for filename transfers
*/
static void
dndFileGetImportTargets(
DtDropInfo * dtDropInfo,
Atom ** importTargets,
Cardinal * numImportTargets)
{
dndFileGetTargets(False, False, importTargets, numImportTargets);
}
/*
* Initialize protocol specific part of drag data
*/
static void
dndFileConvertInit(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
ConvertState * cvtState;
dragData->data.files = (String *)
XtMalloc(dragData->numItems * sizeof(String));
cvtState = (ConvertState *)XtCalloc(1,sizeof(ConvertState));
dtDragInfo->clientData = (XtPointer)cvtState;
}
/*
* Convert the file names into selection data
*/
static Boolean
dndFileConvert(
Widget dragContext,
DtDragInfo * dtDragInfo,
Atom * selection,
Atom * target,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat,
XSelectionRequestEvent * selectionRequestEvent)
{
DtDndContext * dragData = dtDragInfo->dragData;
ConvertState * cvtState = (ConvertState *)dtDragInfo->clientData;
*returnType = XA_NULL;
*returnValue = (XtPointer)NULL;
*returnLength = 0;
*returnFormat = 8;
/*
* Determine file encoding style.
* Handle Sun ATM file name.
* Reject unknown targets.
*/
if (*target == XA_FILE_NAME || *target == XA_DT_NETFILE) {
if (!dndFileListToSelectionValue(
dragData->data.files, dragData->numItems,
(*target == XA_DT_NETFILE),
returnType, returnValue,
returnLength, returnFormat)) {
return False;
}
} else if (*target == XA_TEXT || *target == XA_STRING) {
if (dragData->numItems > 1 || !cvtState->owCompat)
return False;
if (!dndFileContentsToSelectionValue(dragData->data.files[0],
returnType, returnValue,
returnLength, returnFormat)) {
return False;
}
} else if (*target == XA_SUN_SELN_READONLY) {
cvtState->owCompat = True;
} else if (*target == XA_SUN_DATA_LABEL) {
String name;
if (dragData->numItems > 1)
return False;
if ((name = strrchr(dragData->data.files[0],'/')) != NULL)
name++;
else
name = dragData->data.files[0];
*returnType = XA_STRING;
*returnValue = (XtPointer)XtNewString(name);
*returnLength = strlen(*returnValue);
*returnFormat = 8;
cvtState->owCompat = True;
} else if (*target == XA_SUN_ATM_METHODS) {
Atom *atmAtom = XtNew(Atom);
atmAtom[0] = XA_SUN_ATM_FILE_NAME;
*returnType = XA_ATOM;
*returnValue = (XtPointer)atmAtom;
*returnLength = 1;
*returnFormat = 32;
cvtState->owCompat = True;
} else {
return False;
}
return True;
}
/*
* Clean up from the convert init proc
*/
static void
dndFileConvertFinish(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
if (dragData->data.files) {
XtFree((char *)dragData->data.files);
dragData->data.files = NULL;
}
if (dtDragInfo->clientData)
XtFree((char *)dtDragInfo->clientData);
}
/*
* Returns the transfer targets selected from the export targets
* Prefer _DT_NETFILE over FILE_NAME; prefer local host file names
*/
static void
dndFileTransferTargets(
DtDropInfo * dtDropInfo,
Atom * exportTargets,
Cardinal numExportTargets,
Atom ** transferTargets,
Cardinal * numTransferTargets)
{
Boolean foundNetFile, foundFileName, foundHostName;
Atom target;
int ii;
foundNetFile = foundFileName = foundHostName = False;
for (ii = 0; ii < numExportTargets; ii++) {
if (exportTargets[ii] == XA_DT_NETFILE) {
foundNetFile = True;
} else if (exportTargets[ii] == XA_FILE_NAME) {
foundFileName = True;
} else if (exportTargets[ii] == XA_HOST_NAME) {
foundHostName = True;
}
}
if (foundNetFile && foundFileName && foundHostName) {
target = XA_HOST_NAME;
} else if (foundNetFile) {
target = XA_DT_NETFILE;
} else if (foundFileName) {
target = XA_FILE_NAME;
} else {
*numTransferTargets = 0;
*transferTargets = NULL;
return;
}
*numTransferTargets = 1;
*transferTargets = (Atom *)XtMalloc(*numTransferTargets * sizeof(Atom));
(*transferTargets)[0] = target;
}
/*
* Transfer the selection data into file names
*/
static void
dndFileTransfer(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * selection,
Atom * target,
Atom * type,
XtPointer value,
unsigned long * length,
int * format)
{
DtDndContext * dropData = dtDropInfo->dropData;
/*
* Ignore if we've already transferred
*/
if (dropData->data.files) {
XtFree(value);
return;
}
/*
* If hosts are the same then request FILE_NAME else request NETFILE
*/
if (*target == XA_HOST_NAME) {
Atom target;
if (strcmp(_DtDndGetHostName(),(char *)value) == 0)
target = XA_FILE_NAME;
else
target = XA_DT_NETFILE;
_DtDndTransferAdd(dropTransfer, dtDropInfo, &target, 1);
/*
* Convert NETFILE or FILE_NAME selection to file list
*/
} else if (*target == XA_DT_NETFILE || *target == XA_FILE_NAME) {
if (!dndSelectionValueToFileList(*type, value,
*length, *format, (*target == XA_DT_NETFILE),
&(dropData->data.files), &(dropData->numItems))) {
dtDropInfo->status = DtDND_FAILURE;
}
}
if (value != NULL)
XtFree(value);
}
/*
* Clean up from the transfer proc
*/
static void
dndFileTransferFinish(
DtDropInfo * dtDropInfo)
{
DtDndContext * dropData = dtDropInfo->dropData;
int ii;
for (ii = 0; ii < dropData->numItems; ii++) {
XtFree((char *)dropData->data.files[ii]);
}
XtFree((char *)dropData->data.files);
}
/*
* Convert the file contents into a STRING selection
*/
static Boolean
dndFileContentsToSelectionValue(
String fileName,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat)
{
String fullPath;
struct stat stBuf;
int fd;
unsigned long bufLen, bytesRead;
char * buf;
fullPath = dndFileEncode(fileName, False);
if (stat(fullPath,&stBuf) == -1)
return False;
if ((fd = open(fullPath, O_RDONLY)) == -1)
return False;
bufLen = stBuf.st_size;
buf = (void *)XtMalloc(bufLen + 1);
bytesRead = read(fd, buf, bufLen);
if (bytesRead == -1 || bytesRead != bufLen) {
XtFree((char *)buf);
return False;
}
buf[bufLen] = '\0';
*returnType = XA_STRING;
*returnValue = (XtPointer)buf;
*returnLength = bufLen;
*returnFormat = 8;
XtFree(fullPath);
return True;
}
/*
* Convert the filename list into a STRING selection
*/
static Boolean
dndFileListToSelectionValue(
String * fileList,
Cardinal numFiles,
Boolean doNetFile,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat)
{
XTextProperty textProp;
Status status;
String * tmpList;
Cardinal ii;
/*
* Encode the file list
*/
tmpList = (String *)XtMalloc(numFiles * sizeof(String));
for (ii = 0; ii < numFiles; ii++) {
tmpList[ii] = dndFileEncode(fileList[ii], doNetFile);
}
/*
* Convert the encoded file list into a string property
*/
status = XStringListToTextProperty(tmpList, numFiles, &textProp);
for (ii = 0; ii < numFiles; ii++) {
XtFree(tmpList[ii]);
}
XtFree((char *)tmpList);
if (status == 0)
return False;
*returnType = textProp.encoding;
*returnValue = (XtPointer)textProp.value;
*returnLength = textProp.nitems;
*returnFormat = textProp.format;
return True;
}
/*
* Convert the STRING selection into a filename list
*/
static Boolean
dndSelectionValueToFileList(
Atom type,
XtPointer value,
unsigned long length,
int format,
Boolean doNetFile,
String ** returnFileList,
Cardinal * returnNumFiles)
{
XTextProperty textProp;
Status status;
String * tmpList;
String * fileList;
int ii, numFiles;
/*
* Convert text prop to file list
*/
textProp.encoding = type;
textProp.value = (unsigned char *)value;
textProp.nitems = length;
textProp.format = format;
status = XTextPropertyToStringList(&textProp, &tmpList, &numFiles);
if (status == 0)
return False;
/*
* Decode the file list
*/
fileList = (String *)XtMalloc(numFiles * sizeof(String));
for (ii = 0; ii < numFiles; ii++) {
fileList[ii] = dndFileDecode(tmpList[ii], doNetFile);
}
XFreeStringList(tmpList);
*returnFileList = fileList;
*returnNumFiles = numFiles;
return True;
}
/*
* Encodes a file name
* Either into ToolTalk NetFile or into a full path if needed
*/
static String
dndFileEncode(
String fileName,
Boolean doNetFile)
{
String netFile;
String retFile;
if (doNetFile) {
netFile = tt_file_netfile(fileName);
if (tt_ptr_error(netFile) == TT_OK) {
retFile = XtNewString(netFile);
} else {
retFile = XtNewString(fileName);
}
tt_free(netFile);
} else if (fileName[0] != '/') {
char cwd[MAXPATHLEN];
char *realPath;
if (getcwd(cwd,MAXPATHLEN) == NULL) {
strcpy(cwd,"/");
}
realPath = XtMalloc(strlen(cwd) + strlen(fileName) + 2);
sprintf(realPath,"%s/%s",cwd,fileName);
retFile = realPath;
} else {
retFile = XtNewString(fileName);
}
return retFile;
}
/*
* Decodes a file name; possibly from a ToolTalk NetFile
*/
static String
dndFileDecode(
String fileName,
Boolean doNetFile)
{
String file;
String retFile;
if (doNetFile) {
file = tt_netfile_file(fileName);
if (tt_ptr_error(file) == TT_OK) {
retFile = XtNewString(file);
} else {
retFile = XtNewString(fileName);
}
tt_free(file);
} else {
retFile = XtNewString(fileName);
}
return retFile;
}

View File

@@ -0,0 +1,548 @@
/* $XConsortium: DndIcon.c /main/5 1996/06/21 17:28:34 ageorge $ */
/*********************************************************************
*
* File: DndIcon.c
*
* Description: Implemenation of DND drag icons
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <Xm/Screen.h>
#include <Xm/DragIcon.h>
#include "Dnd.h"
#include "DndP.h"
#include "DndIconI.h"
#include "DtSvcLock.h"
/*
* Component types of a drag icon (source/state/operation)
*/
enum {
DtDND_DRAG_SOURCE,
DtDND_DRAG_STATE,
DtDND_DRAG_OPERATION
};
/*
* The XmDragIcon widgets for the state & operation components
* of a Drag Icon
*/
typedef struct _DragIcons {
Widget validIcon, invalidIcon, noneIcon;
Widget moveIcon, copyIcon, linkIcon;
} DragIcons;
/*
* Collection of drag icons for text & data drags
*/
typedef struct _DragCollection {
DtDndDragSource sourceType;
DragIcons text;
DragIcons data;
Widget textSource;
Widget dataSource;
Widget multipleSource;
} DragCollection;
/*
* The context that the DragCollection is stored against.
* Used in getDragCollection() and destroyDragCollection().
*/
static XContext dragCollectionContext;
/*
* Creates an XmDragIcon for use as the source component of the drag icon.
*/
Widget
DtDndCreateSourceIcon(
Widget widget,
Pixmap pixmap,
Pixmap mask)
{
Widget dragIcon;
Window rootWindow;
int pixmapX, pixmapY;
unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
Arg args[20];
Cardinal nn = 0;
_DtSvcWidgetToAppContext(widget);
_DtSvcAppLock(app);
while (XmIsGadget(widget)) {
widget = XtParent(widget);
}
XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
&pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
&pixmapBorder, &pixmapDepth);
XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
XtSetArg(args[nn], XmNmask, mask); nn++;
XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
_DtSvcAppUnlock(app);
return(dragIcon);
}
/*
* Calculates the x,y offsets for the state cursor relative to the source
*/
static void
calcStateIconOffset(
Widget sourceIcon,
int *stateOffsetX,
int *stateOffsetY)
{
Display *dpy = XtDisplayOfObject(sourceIcon);
Pixmap pixmap;
Window root;
int pixmapX, pixmapY;
unsigned int pixmapW, pixmapH, junk;
XtVaGetValues(sourceIcon, XmNpixmap, &pixmap, NULL);
if (pixmap == None)
return;
XGetGeometry(dpy, pixmap, &root,
&pixmapX, &pixmapY, &pixmapW, &pixmapH,
&junk, &junk);
if (pixmapH == 16) {
*stateOffsetX = *stateOffsetY = 8;
} else {
*stateOffsetX = *stateOffsetY = 16;
}
}
/*
* Selects or activates the request type of source by setting
* the default drag icon resources on the XmScreen widget.
*/
static void
selectDragSource(
DragCollection *dc,
Widget xmScreen,
DtDndDragSource sourceType,
Widget sourceIcon)
{
Display *dpy = XtDisplayOfObject(xmScreen);
Widget validIcon, invalidIcon, noneIcon,
moveIcon, copyIcon, linkIcon,
defSourceIcon;
int hotX, hotY,
stateOffsetX, stateOffsetY,
offsetDeltaX, offsetDeltaY;
Arg args[30];
Cardinal nn = 0;
/*
* Choose the state/operation/default-source drag icons based
* on the requested drag-source-type
*/
switch (sourceType) {
case DtDND_DRAG_SOURCE_TEXT:
validIcon = dc->text.validIcon;
invalidIcon = dc->text.invalidIcon;
noneIcon = dc->text.noneIcon;
moveIcon = dc->text.moveIcon;
copyIcon = dc->text.copyIcon;
linkIcon = dc->text.linkIcon;
defSourceIcon = dc->textSource;
hotX = text_x_hot;
hotY = text_y_hot;
stateOffsetX = text_x_offset_state;
stateOffsetY = text_y_offset_state;
offsetDeltaX = text_x_offset_delta;
offsetDeltaY = text_y_offset_delta;
break;
case DtDND_DRAG_SOURCE_DATA:
validIcon = dc->data.validIcon;
invalidIcon = dc->data.invalidIcon;
noneIcon = dc->data.noneIcon;
moveIcon = dc->data.moveIcon;
copyIcon = dc->data.copyIcon;
linkIcon = dc->data.linkIcon;
defSourceIcon = dc->dataSource;
hotX = data_x_hot;
hotY = data_y_hot;
stateOffsetX = data_x_offset_state;
stateOffsetY = data_y_offset_state;
offsetDeltaX = data_x_offset_delta;
offsetDeltaY = data_y_offset_delta;
break;
case DtDND_DRAG_SOURCE_MULTIPLE:
validIcon = dc->data.validIcon;
invalidIcon = dc->data.invalidIcon;
noneIcon = dc->data.noneIcon;
moveIcon = dc->data.moveIcon;
copyIcon = dc->data.copyIcon;
linkIcon = dc->data.linkIcon;
defSourceIcon = dc->multipleSource;
hotX = data_x_hot;
hotY = data_y_hot;
stateOffsetX = data_x_offset_state;
stateOffsetY = data_y_offset_state;
offsetDeltaX = data_x_offset_delta;
offsetDeltaY = data_y_offset_delta;
break;
default:
case DtDND_DRAG_SOURCE_DEFAULT:
validIcon = NULL;
invalidIcon = NULL;
noneIcon = NULL;
moveIcon = NULL;
copyIcon = NULL;
linkIcon = NULL;
defSourceIcon = NULL;
hotX = motif_x_hot;
hotY = motif_y_hot;
stateOffsetX = motif_x_offset_state;
stateOffsetY = motif_y_offset_state;
offsetDeltaX = motif_x_offset_delta;
offsetDeltaY = motif_y_offset_delta;
break;
}
/*
* Calculate the offsets of the state icon from the
* DtDND_DRAG_SOURCE_DATA source icon if specified
*/
if (sourceIcon && sourceType == DtDND_DRAG_SOURCE_DATA) {
calcStateIconOffset(sourceIcon, &stateOffsetX, &stateOffsetY);
}
nn = 0;
XtSetArg(args[nn], XmNhotX, hotX); nn++;
XtSetArg(args[nn], XmNhotY, hotY); nn++;
XtSetArg(args[nn], XmNoffsetX, stateOffsetX); nn++;
XtSetArg(args[nn], XmNoffsetY, stateOffsetY); nn++;
if (validIcon)
XtSetValues(validIcon, args, nn);
if (invalidIcon)
XtSetValues(invalidIcon, args, nn);
if (noneIcon)
XtSetValues(noneIcon, args, nn);
nn = 0;
XtSetArg(args[nn], XmNoffsetX, stateOffsetX + offsetDeltaX); nn++;
XtSetArg(args[nn], XmNoffsetY, stateOffsetY + offsetDeltaY); nn++;
if (moveIcon)
XtSetValues(moveIcon, args, nn);
if (copyIcon)
XtSetValues(copyIcon, args, nn);
if (linkIcon)
XtSetValues(linkIcon, args, nn);
/*
* Set the default drag cursor icons for the XmScreen widget
*/
XtVaSetValues(xmScreen,
XmNdefaultValidCursorIcon, validIcon,
XmNdefaultInvalidCursorIcon, invalidIcon,
XmNdefaultNoneCursorIcon, noneIcon,
XmNdefaultMoveCursorIcon, moveIcon,
XmNdefaultCopyCursorIcon, copyIcon,
XmNdefaultLinkCursorIcon, linkIcon,
XmNdefaultSourceCursorIcon, defSourceIcon,
NULL);
dc->sourceType = sourceType;
}
/*
* Create a drag icon widget from the passed bits
*/
static Widget
makeDragIconFromData(
Widget widget,
unsigned char *bits,
unsigned char *maskbits,
int width,
int height,
int component)
{
Widget icon;
Pixmap pixmap, mask;
Display *dpy = XtDisplayOfObject(widget);
Screen *screen = XtScreenOfObject(widget);
Window root = RootWindowOfScreen(screen);
String name;
Arg args[30];
Cardinal nn = 0;
pixmap = XCreatePixmapFromBitmapData(dpy, root,
(char *)bits, width, height,
1, 0, 1);
mask = XCreatePixmapFromBitmapData(dpy, root,
(char *)maskbits, width, height,
1, 0, 1);
switch (component) {
case DtDND_DRAG_SOURCE:
name = "sourceIcon";
break;
case DtDND_DRAG_STATE:
name = "stateIcon";
XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++;
XtSetArg(args[nn], XmNoffsetX, -6); nn++;
XtSetArg(args[nn], XmNoffsetY, -6); nn++;
XtSetArg(args[nn], XmNhotX, 3); nn++;
XtSetArg(args[nn], XmNhotY, 3); nn++;
break;
case DtDND_DRAG_OPERATION:
name = "operationIcon";
XtSetArg(args[nn], XmNattachment, XmATTACH_NORTH_WEST); nn++;
XtSetArg(args[nn], XmNoffsetX, 1); nn++;
XtSetArg(args[nn], XmNoffsetY, 1); nn++;
break;
}
XtSetArg(args[nn], XmNwidth, width); nn++;
XtSetArg(args[nn], XmNheight, height); nn++;
XtSetArg(args[nn], XmNmaxWidth, width); nn++;
XtSetArg(args[nn], XmNmaxHeight, height); nn++;
XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
XtSetArg(args[nn], XmNmask, mask); nn++;
XtSetArg(args[nn], XmNdepth, 1); nn++;
icon = XmCreateDragIcon(widget, name, args, nn);
return icon;
}
/*
* Create the collection of text & data drag icons; state/operation
* cursors and source icons.
*/
static DragCollection *
makeDragCollection(
Widget widget)
{
DragCollection *dc = XtNew(DragCollection);
Display *dpy = XtDisplayOfObject(widget);
Screen *screen = XtScreenOfObject(widget);
Window root = RootWindowOfScreen(screen);
Widget xmScreen = XmGetXmScreen(screen);
/*
* Text & Data State Cursors
*/
dc->text.invalidIcon = makeDragIconFromData(widget,
text_invalid_bits, text_invalid_m_bits,
text_invalid_width, text_invalid_height,
DtDND_DRAG_STATE);
dc->text.validIcon = makeDragIconFromData(widget,
text_valid_bits, text_valid_m_bits,
text_valid_width, text_valid_height,
DtDND_DRAG_STATE);
dc->text.noneIcon = makeDragIconFromData(widget,
text_none_bits, text_none_m_bits,
text_none_width, text_none_height,
DtDND_DRAG_STATE);
dc->data.invalidIcon = makeDragIconFromData(widget,
data_invalid_bits, data_invalid_m_bits,
data_invalid_width, data_invalid_height,
DtDND_DRAG_STATE);
dc->data.validIcon = makeDragIconFromData(widget,
data_valid_bits, data_valid_m_bits,
data_valid_width, data_valid_height,
DtDND_DRAG_STATE);
dc->data.noneIcon = makeDragIconFromData(widget,
data_none_bits, data_none_m_bits,
data_none_width, data_none_height,
DtDND_DRAG_STATE);
/*
* Text & Data Operation Cursors
*/
dc->data.moveIcon = makeDragIconFromData(widget,
data_move_bits, data_move_m_bits,
data_move_width, data_move_height,
DtDND_DRAG_OPERATION);
dc->data.copyIcon = makeDragIconFromData(widget,
data_copy_bits, data_copy_m_bits,
data_copy_width, data_copy_height,
DtDND_DRAG_OPERATION);
dc->data.linkIcon = makeDragIconFromData(widget,
data_link_bits, data_link_m_bits,
data_link_width, data_link_height,
DtDND_DRAG_OPERATION);
dc->text.moveIcon = dc->data.moveIcon;
dc->text.copyIcon = dc->data.copyIcon;
dc->text.linkIcon = dc->data.linkIcon;
/*
* Text & Data Source Cursors
*/
dc->textSource = makeDragIconFromData(widget,
text_source_bits, text_source_m_bits,
text_source_width, text_source_height,
DtDND_DRAG_SOURCE);
dc->dataSource = makeDragIconFromData(widget,
data_single_bits, data_single_m_bits,
data_single_width, data_single_height,
DtDND_DRAG_SOURCE);
dc->multipleSource = makeDragIconFromData(widget,
data_multiple_bits, data_multiple_m_bits,
data_multiple_width, data_multiple_height,
DtDND_DRAG_SOURCE);
dc->sourceType = DtDND_DRAG_SOURCE_DEFAULT;
return dc;
}
/*
* Destroys the cached DragCollection and context for it
*/
static void
destroyDragCollection(
Widget widget,
XtPointer clientData,
XtPointer callData)
{
DragCollection *dc = (DragCollection *)clientData;
XtFree((char *)dc);
XDeleteContext(XtDisplayOfObject(widget),
RootWindowOfScreen(XtScreenOfObject(widget)),
dragCollectionContext);
}
/*
* Returns the cached DragCollection; will create one if needed
*/
static DragCollection *
getDragCollection(
Widget xmScreen)
{
DragCollection *dc = NULL;
Display *dpy = XtDisplayOfObject(xmScreen);
Screen *screen = XtScreenOfObject(xmScreen);
Window root = RootWindowOfScreen(screen);
int status;
_DtSvcProcessLock();
if (dragCollectionContext == (XContext)NULL) {
dragCollectionContext = XUniqueContext();
}
_DtSvcProcessUnlock();
status = XFindContext(dpy, root, dragCollectionContext, (XtPointer)&dc);
if (status != 0) {
dc = makeDragCollection(xmScreen);
XSaveContext(dpy, root, dragCollectionContext, (XtPointer)dc);
XtAddCallback(xmScreen, XmNdestroyCallback,
destroyDragCollection, (XtPointer)dc);
}
return dc;
}
/*
* Module-public function to select/activate a source type drag icon
*/
void
_DtDndSelectDragSource(
Widget widget,
DtDndDragSource sourceType,
Widget sourceIcon)
{
Widget xmScreen = XmGetXmScreen(XtScreenOfObject(widget));
DragCollection *dc = getDragCollection(xmScreen);
selectDragSource(dc, xmScreen, sourceType, sourceIcon);
}
void
_DtDndGetIconOffset(
Widget dragContext,
DtDndDragSource sourceType,
int * offsetX,
int * offsetY)
{
Widget sourceIcon;
int stateOffsetX, stateOffsetY;
switch (sourceType) {
default:
case DtDND_DRAG_SOURCE_DEFAULT:
*offsetX = -(motif_x_hot + motif_x_offset_state);
*offsetY = -(motif_y_hot + motif_y_offset_state);
break;
case DtDND_DRAG_SOURCE_TEXT:
*offsetX = -(text_x_hot + text_x_offset_state);
*offsetY = -(text_y_hot + text_y_offset_state);
break;
case DtDND_DRAG_SOURCE_DATA:
case DtDND_DRAG_SOURCE_MULTIPLE:
*offsetX = -(data_x_hot + data_x_offset_state);
*offsetY = -(data_y_hot + data_y_offset_state);
XtVaGetValues(dragContext,
XmNsourcePixmapIcon, &sourceIcon,
NULL);
if (sourceIcon != NULL) {
calcStateIconOffset(sourceIcon,
&stateOffsetX, &stateOffsetY);
*offsetX = -(data_x_hot + stateOffsetX);
*offsetY = -(data_y_hot + stateOffsetY);
}
break;
}
}

View File

@@ -0,0 +1,401 @@
/* $XConsortium: DndIconI.h /main/3 1995/10/26 15:05:58 rswiston $ */
/*********************************************************************
*
* File: DndIconI.h
*
* Description: Private include file containing DND drag icons bitmaps
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#ifndef _Dt_DndIconI_h
#define _Dt_DndIconI_h
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------
* Motif Defaults
*-------------------------------------------------------------------*/
#define motif_x_hot 1
#define motif_y_hot 1
#define motif_x_offset_state -8
#define motif_y_offset_state -2
#define motif_x_offset_delta 0
#define motif_y_offset_delta 0
/*-------------------------------------------------------------------
* Text Drags: Cursors
*-------------------------------------------------------------------*/
#define text_x_hot 1
#define text_y_hot 1
#define text_x_offset_state 1
#define text_y_offset_state 1
#define text_x_offset_delta 7
#define text_y_offset_delta 3
/*
* Text: State Valid
*/
#define text_valid_width 16
#define text_valid_height 16
static unsigned char text_valid_bits[] = {
#ifdef OLDTEXTVALID
0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x3e, 0x00,
0x7e, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#else
0x00, 0x00, 0xfe, 0x01, 0xfe, 0x00, 0x7e, 0x00, 0x3e, 0x00, 0x1e, 0x00,
0x0e, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
static unsigned char text_valid_m_bits[] = {
#ifdef OLDTEXTVALID
0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00,
0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#else
0xff, 0x07, 0xff, 0x03, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00,
0x1f, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
/*
* Text: State Invalid
*/
#define text_invalid_width 16
#define text_invalid_height 16
static unsigned char text_invalid_bits[] = {
0x00, 0x00, 0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0c, 0x1e, 0x06, 0x37,
0x86, 0x33, 0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x3c, 0x18, 0x1c, 0x1c,
0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00};
static unsigned char text_invalid_m_bits[] = {
0xe0, 0x03, 0xf8, 0x0f, 0xfc, 0x1f, 0xfe, 0x3f, 0x1e, 0x3f, 0x8f, 0x7f,
0xcf, 0x7f, 0xef, 0x7b, 0xff, 0x79, 0xff, 0x78, 0x7e, 0x3c, 0xfe, 0x3f,
0xfc, 0x1f, 0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00};
/*
* Text: None
*/
#define text_none_width 16
#define text_none_height 16
static unsigned char text_none_bits[] = {
0x00, 0x00, 0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0c, 0x1e, 0x06, 0x37,
0x86, 0x33, 0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x3c, 0x18, 0x1c, 0x1c,
0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00};
static unsigned char text_none_m_bits[] = {
0xe0, 0x03, 0xf8, 0x0f, 0xfc, 0x1f, 0xfe, 0x3f, 0x1e, 0x3f, 0x8f, 0x7f,
0xcf, 0x7f, 0xef, 0x7b, 0xff, 0x79, 0xff, 0x78, 0x7e, 0x3c, 0xfe, 0x3f,
0xfc, 0x1f, 0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00};
/*-------------------------------------------------------------------
* Text Drags: Operation Cursors
*-------------------------------------------------------------------*/
/* Use Data Operation Cursors */
/*
* Text: Operation Move
*/
/*
* Text: Operation Copy
*/
/*
* Text: Operation Link
*/
/*-------------------------------------------------------------------
* Text Drags: Source Cursor
*-------------------------------------------------------------------*/
#define text_source_width 32
#define text_source_height 32
static unsigned char text_source_bits[] = {
#ifdef OLDTEXTSOURCE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xd8, 0xdb, 0xcd, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbe, 0x7f, 0x1f,
0x00, 0x00, 0x00, 0x00, 0xb8, 0xf6, 0xfd, 0x16, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x7b, 0x76, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xbb, 0xff, 0x06,
0x00, 0x00, 0x00, 0x00, 0xd8, 0xde, 0x7b, 0x1d, 0x00, 0x00, 0x00, 0x00,
0x78, 0xd7, 0xb4, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xad, 0xd5, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#else
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xcd, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x7f, 0x1f,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfd, 0x16, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7b, 0x76, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xbb, 0xff, 0x06,
0x00, 0x00, 0x00, 0x00, 0xf0, 0xde, 0x7b, 0x1d, 0x00, 0x00, 0x00, 0x00,
0x78, 0x77, 0xb7, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbd, 0xdd, 0x0f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
static unsigned char text_source_m_bits[] = {
#ifdef OLDTEXTSOURCE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#else
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x3f,
0x00, 0xf0, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x3f,
0x00, 0xfe, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x3f, 0x80, 0xff, 0xff, 0x3f,
0xc0, 0xff, 0xff, 0x3f, 0xe0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f,
0xf8, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f,
0xfc, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
/*-------------------------------------------------------------------
* Data Drags: Cursors
*------------------------------------------------------------------*/
#define data_x_hot 3
#define data_y_hot 3
#define data_x_offset_state 11
#define data_y_offset_state 11
#define data_x_offset_delta 7
#define data_y_offset_delta 7
/*
* Data: State Valid
*/
#define data_valid_width 16
#define data_valid_height 16
static unsigned char data_valid_bits[] = {
0x00, 0x00, 0x06, 0x00, 0x1e, 0x00, 0x7c, 0x00, 0xfc, 0x01, 0xf8, 0x07,
0xf8, 0x07, 0xf0, 0x01, 0xf0, 0x03, 0x60, 0x07, 0x60, 0x0e, 0x00, 0x1c,
0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0x00};
static unsigned char data_valid_m_bits[] = {
0x07, 0x00, 0x1f, 0x00, 0x7f, 0x00, 0xfe, 0x01, 0xfe, 0x07, 0xfc, 0x0f,
0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf0, 0x0f, 0xf0, 0x1f, 0x60, 0x3e,
0x00, 0x7c, 0x00, 0xf8, 0x00, 0xf0, 0x00, 0x60};
/*
* Data: State Invalid
*/
#define data_invalid_width 16
#define data_invalid_height 16
static unsigned char data_invalid_bits[] = {
0x00, 0x00, 0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0c, 0x1e, 0x06, 0x37,
0x86, 0x33, 0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x3c, 0x18, 0x1c, 0x1c,
0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00};
static unsigned char data_invalid_m_bits[] = {
0xe0, 0x03, 0xf8, 0x0f, 0xfc, 0x1f, 0xfe, 0x3f, 0x1e, 0x3f, 0x8f, 0x7f,
0xcf, 0x7f, 0xef, 0x7b, 0xff, 0x79, 0xff, 0x78, 0x7e, 0x3c, 0xfe, 0x3f,
0xfc, 0x1f, 0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00};
/*
* Data: State None
*/
#define data_none_width 16
#define data_none_height 16
static unsigned char data_none_bits[] = {
0x00, 0x00, 0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0c, 0x1e, 0x06, 0x37,
0x86, 0x33, 0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x3c, 0x18, 0x1c, 0x1c,
0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00};
static unsigned char data_none_m_bits[] = {
0xe0, 0x03, 0xf8, 0x0f, 0xfc, 0x1f, 0xfe, 0x3f, 0x1e, 0x3f, 0x8f, 0x7f,
0xcf, 0x7f, 0xef, 0x7b, 0xff, 0x79, 0xff, 0x78, 0x7e, 0x3c, 0xfe, 0x3f,
0xfc, 0x1f, 0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00};
/*-------------------------------------------------------------------
* Data Drags: Operation Cursors
*-------------------------------------------------------------------*/
/*
* Data: Operation Move
*/
#define data_move_width 16
#define data_move_height 16
static unsigned char data_move_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static unsigned char data_move_m_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/*
* Data: Operation Copy
*/
#define data_copy_width 16
#define data_copy_height 16
static unsigned char data_copy_bits[] = {
0x00, 0x00, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x1f, 0x02, 0x11,
0x02, 0x11, 0x02, 0x11, 0x02, 0x11, 0x02, 0x11, 0xfe, 0x11, 0x20, 0x10,
0x20, 0x10, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00};
static unsigned char data_copy_m_bits[] = {
0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f,
0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f,
0xf0, 0x3f, 0xf0, 0x3f, 0xf0, 0x3f, 0x00, 0x00};
/*
* Data: Operation Link
*/
#define data_link_width 16
#define data_link_height 16
static unsigned char data_link_bits[] = {
0x00, 0x00, 0xfe, 0x03, 0x02, 0x02, 0x02, 0x02, 0x32, 0x02, 0x32, 0x3e,
0x42, 0x20, 0x82, 0x20, 0x02, 0x21, 0x3e, 0x26, 0x20, 0x26, 0x20, 0x20,
0x20, 0x20, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00};
static unsigned char data_link_m_bits[] = {
0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x7f, 0xff, 0x7f,
0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xf0, 0x7f,
0xf0, 0x7f, 0xf0, 0x7f, 0xf0, 0x7f, 0x00, 0x00};
/*-------------------------------------------------------------------
* Data Drags: Source Icons
*-------------------------------------------------------------------*/
/*
* Data Source: Single
*/
#define data_single_width 32
#define data_single_height 32
static unsigned char data_single_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x10, 0x00, 0xc0, 0x00,
0x10, 0x00, 0x40, 0x01, 0x10, 0x00, 0x40, 0x02, 0x10, 0x00, 0x40, 0x04,
0x10, 0x00, 0xc0, 0x0f, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08,
0x10, 0x00, 0x00, 0x08, 0xf0, 0xff, 0xff, 0x0f};
static unsigned char data_single_m_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0x00,
0xf0, 0xff, 0xff, 0x01, 0xf0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x07,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f};
/*
* Data Source: Multiple
*/
#define data_multiple_width 32
#define data_multiple_height 32
static unsigned char data_multiple_bits[] = {
0xfc, 0xff, 0x0f, 0x00, 0x04, 0x00, 0x30, 0x00, 0x04, 0x00, 0xd0, 0x1f,
0x04, 0x00, 0x90, 0x10, 0x04, 0x00, 0x10, 0xf1, 0x04, 0x00, 0xf0, 0x93,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x92,
0xfc, 0xff, 0xff, 0x93, 0x20, 0x00, 0x00, 0x90, 0xe0, 0xff, 0xff, 0x9f,
0x00, 0x01, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff};
static unsigned char data_multiple_m_bits[] = {
0xfc, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0xff, 0x1f,
0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
0xfc, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff};
#ifdef __cplusplus
}
#endif
#endif /* _Dt_DndIconI_h */

View File

@@ -0,0 +1,310 @@
/* $XConsortium: DndP.h /main/4 1996/06/21 17:28:31 ageorge $ */
/*********************************************************************
*
* File: DndP.h
*
* Description: Private include file for DND Convenience API.
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#ifndef _Dt_DndP_h
#define _Dt_DndP_h
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Drag and Drop selection targets
*/
extern Atom XA_TARGETS;
extern Atom XA_TIMESTAMP;
extern Atom XA_MULTIPLE;
extern Atom XA_DELETE;
extern Atom XA_NULL;
extern Atom XA_TEXT;
extern Atom XA_HOST_NAME;
extern Atom XA_SUN_FILE_HOST_NAME;
extern Atom XA_SUN_ENUM_COUNT;
extern Atom XA_SUN_DATA_LABEL;
extern Atom XA_SUN_SELN_READONLY;
extern Atom XA_SUN_ATM_FILE_NAME;
extern Atom XA_SUN_ATM_METHODS;
#define DtGetAtom(display, atomname) \
XmInternAtom((display),(atomname),False)
/*
* Drag Icon Styles
*/
typedef enum {
DtDND_DRAG_SOURCE_DEFAULT,
DtDND_DRAG_SOURCE_TEXT,
DtDND_DRAG_SOURCE_DATA,
DtDND_DRAG_SOURCE_MULTIPLE
} DtDndDragSource;
/*
* Drag-n-Drop Data Transfer Protocol
*/
typedef struct _DtDndTransfer {
Atom * targets;
Cardinal numTargets;
struct _DtDndMethods * methods;
} DtDndTransfer;
/*
* Drag Initiator Structure
*/
typedef struct _DtDragInfo {
Widget dragInitiator;
Widget dragContext;
DtDndProtocol protocol;
Cardinal numItems;
unsigned char operations;
XtCallbackList dragConvertCallback;
XtCallbackList dragFinishCallback;
XtCallbackList dropOnRootCallback;
XtCallbackList dragDropFinishCallback;
XtCallbackList dropFinishCallback;
XtCallbackList topLevelEnterCallback;
XtCallbackList topLevelLeaveCallback;
XtCallbackList dropStartCallback;
Widget sourceIcon;
Boolean bufferIsText;
DtDndTransfer * transfer;
DtDndContext * dragData;
Boolean inRoot;
Window backdropWindow;
DtDndStatus status;
XtPointer clientData;
} DtDragInfo;
/*
* Drop Receiver Existing Registration Structure
*/
typedef struct _DtDropSiteInfo {
XtCallbackProc dropProc;
unsigned char operations;
Atom * importTargets;
int numImportTargets;
} DtDropSiteInfo;
/*
* Drop Receiver Data Transfer Structure
*/
typedef struct _DtTransferInfo {
Widget dragContext;
DtDndProtocol protocol;
unsigned char operation;
struct _DtDndMethods * methods;
Atom * transferTargets;
Cardinal numTransferTargets;
Cardinal currentTransfer;
Boolean appTransferCalled;
XEvent * event;
Position x, y;
XtPointer clientData;
XtCallbackList dropAnimateCallback;
} DtTransferInfo;
/*
* Drop Receiver Registration Structure
*/
typedef struct _DtDropInfo {
Widget dropReceiver;
DtDndProtocol protocols;
unsigned char operations;
XtCallbackList dropTransferCallback;
XtCallbackList dropAnimateCallback;
Boolean textIsBuffer;
DtDropSiteInfo * dropSiteInfo;
DtDndTransfer * transfers;
Cardinal numTransfers;
DtTransferInfo * transferInfo;
DtDndContext * dropData;
DtDndStatus status;
} DtDropInfo;
/*
* Drag-n-Drop Data Transfer Protocol Function Prototypes
*/
typedef void
(*DtDndGetAvailTargetsProc)(
DtDragInfo * dtDragInfo,
Atom ** returnAvailTargetsList,
Cardinal * returnNumAvailTargets);
typedef void
(*DtDndGetExportTargetsProc)(
DtDragInfo * dtDragInfo,
Atom ** returnExportTargetsList,
Cardinal * returnNumExportTargets);
typedef void
(*DtDndGetImportTargetsProc)(
DtDropInfo * dtDropInfo,
Atom ** returnImportTargetsList,
Cardinal * returnNumImportTargets);
typedef void
(*DtDndConvertInitProc)(
DtDragInfo * dtDragInfo);
typedef Boolean
(*DtDndConvertProc)(
Widget dragContext,
DtDragInfo * dtDragInfo,
Atom * selection,
Atom * target,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat,
XSelectionRequestEvent *selectionRequestEvent);
typedef void
(*DtDndConvertFinishProc)(
DtDragInfo * dtDragInfo);
typedef void
(*DtDndTransferTargetsProc)(
DtDropInfo * dtDropInfo,
Atom * exportTargets,
Cardinal numExportTargets,
Atom ** returnTransferTargetsList,
Cardinal * returnNumTransferTargets);
typedef void
(*DtDndTransferProc)(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * selection,
Atom * target,
Atom * type,
XtPointer value,
unsigned long * length,
int * format);
typedef void
(*DtDndTransferFinishProc)(
DtDropInfo * dtDropInfo);
/*
* Drag-n-Drop Data Transfer Methods
*/
typedef struct _DtDndMethods {
String name;
DtDndProtocol protocol;
DtDndDragSource sourceType;
DtDndGetAvailTargetsProc getAvailTargets;
DtDndGetExportTargetsProc getExportTargets;
DtDndGetImportTargetsProc getImportTargets;
DtDndConvertInitProc convertInit;
DtDndConvertProc convert;
DtDndConvertFinishProc convertFinish;
DtDndTransferTargetsProc transferTargets;
DtDndTransferProc transfer;
DtDndTransferFinishProc transferFinish;
} DtDndMethods;
/*
* Drag-n-Drop Private Utility Functions
*/
extern DtDndTransfer *
_DtDndCreateExportTransfer(
DtDragInfo * dtDragInfo);
extern DtDndTransfer *
_DtDndCreateImportTransfers(
DtDropInfo * dtDropInfo,
Cardinal * numTransfers);
extern void
_DtDndDestroyTransfers(
DtDndTransfer * transfers,
Cardinal numTransfers);
extern DtDndTransfer *
_DtDndTransferFromTargets(
DtDndTransfer * transfers,
Cardinal numTransfers,
Atom * targets,
Cardinal numTargets);
extern void
_DtDndTransferAdd(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * transferTargets,
Cardinal numTransferTargets);
extern XtCallbackList
_DtDndCopyCallbackList(
XtCallbackList callbacks);
extern void
_DtDndCallCallbackList(
Widget widget,
XtCallbackList callbacks,
XtPointer calldata);
extern void
_DtDndSelectDragSource(
Widget anyWidget,
DtDndDragSource sourceType,
Widget sourceIcon);
extern void
_DtDndGetIconOffset(
Widget dragContext,
DtDndDragSource sourceType,
int * offsetXReturn,
int * offsetYReturn);
extern String
_DtDndGetHostName(void);
#ifdef DEBUG
extern void _DtDndPrintTargets(Display*,Atom*,Cardinal);
extern void _DtDndPrintTransfers(Display*,DtDndTransfer*,Cardinal);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _Dt_DndP_h */

View File

@@ -0,0 +1,385 @@
/* $XConsortium: DndText.c /main/5 1996/08/28 17:46:27 drk $ */
/*********************************************************************
*
* File: DndText.c
*
* Description: Implementation of the Text Transfer routines
* for the DND Convenience API.
*
*********************************************************************
*
*+SNOTICE
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. 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.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <locale.h>
#include <X11/Intrinsic.h>
#include <Xm/AtomMgr.h>
#include <Xm/DragC.h>
#include <Xm/DropSMgr.h>
#include <Xm/DropTrans.h>
#include "Dnd.h"
#include "DndP.h"
#include "DtSvcLock.h"
/*
* Text Transfer Function Prototypes
*/
static void dndTextGetTargets(Atom**, Cardinal*);
static void dndTextGetAvailTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndTextGetExportTargets(DtDragInfo*, Atom**, Cardinal*);
static void dndTextGetImportTargets(DtDropInfo*, Atom**, Cardinal*);
static void dndTextConvertInit(DtDragInfo*);
static Boolean dndTextConvert(Widget, DtDragInfo*, Atom*, Atom*,
Atom*, XtPointer*, unsigned long*, int*,
XSelectionRequestEvent*);
static void dndTextConvertFinish(DtDragInfo*);
static void dndTextTransferTargets(DtDropInfo*,
Atom*, Cardinal, Atom**, Cardinal*);
static void dndTextTransfer(Widget, DtDropInfo*, Atom*, Atom*,
Atom*, XtPointer, unsigned long*, int*);
static void dndTextTransferFinish(DtDropInfo*);
/*
* Text Transfer Selection Target
*/
static Atom XA_COMPOUND_TEXT;
static Boolean dndPreferString;
/*
* Text Transfer ProtocolInfo
*/
static DtDndMethods dndTextTransferProtocol = {
"DtDndTextTransfer", /* name */
(DtDndProtocol)DtDND_TEXT_TRANSFER, /* protocol */
DtDND_DRAG_SOURCE_TEXT, /* sourceType */
dndTextGetAvailTargets, /* getAvailTargets */
dndTextGetExportTargets, /* getExportTargets */
dndTextGetImportTargets, /* getImportTargets */
dndTextConvertInit, /* convertInit */
dndTextConvert, /* convert */
dndTextConvertFinish, /* convertFinish */
dndTextTransferTargets, /* transferTargets */
dndTextTransfer, /* transfer */
dndTextTransferFinish, /* transferFinish */
};
/*
* Text transfer protocol initialization
*/
DtDndMethods *
_DtDndTextTransferProtocolInitialize(
Display * display)
{
_DtSvcProcessLock();
if (XA_COMPOUND_TEXT == 0) {
XA_COMPOUND_TEXT = DtGetAtom(display, "COMPOUND_TEXT");
dndPreferString = (strcmp(setlocale(LC_CTYPE,NULL),"C") == 0);
#ifdef DEBUG
printf("locale = %s, dndPreferString = %d\n",
setlocale(LC_CTYPE,NULL), dndPreferString);
#endif
}
_DtSvcProcessUnlock();
return &dndTextTransferProtocol;
}
/*
* Returns generic export/import targets for text transfers
*/
static void
dndTextGetTargets(
Atom ** targets,
Cardinal * numTargets)
{
int ii = 0;
*numTargets = 3;
*targets = (Atom *)XtMalloc(*numTargets * sizeof(Atom));
(*targets)[ii++] = XA_COMPOUND_TEXT;
(*targets)[ii++] = XA_TEXT;
(*targets)[ii++] = XA_STRING;
}
/*
* Returns available targets for text transfers
*/
static void
dndTextGetAvailTargets(
DtDragInfo * dtDragInfo,
Atom ** availTargets,
Cardinal * numAvailTargets)
{
dndTextGetTargets(availTargets, numAvailTargets);
}
/*
* Returns export targets for text transfers
*/
static void
dndTextGetExportTargets(
DtDragInfo * dtDragInfo,
Atom ** exportTargets,
Cardinal * numExportTargets)
{
dndTextGetTargets(exportTargets, numExportTargets);
}
/*
* Returns import targets for text transfers
*/
static void
dndTextGetImportTargets(
DtDropInfo * dtDropInfo,
Atom ** importTargets,
Cardinal * numImportTargets)
{
dndTextGetTargets(importTargets, numImportTargets);
}
/*
* Initialize protocol specific part of drag data
*/
static void
dndTextConvertInit(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
dragData->data.strings = (XmString *)
XtMalloc(dragData->numItems * sizeof(XmString));
}
/*
* Convert the motif strings into selection data
*/
static Boolean
dndTextConvert(
Widget dragContext,
DtDragInfo * dtDragInfo,
Atom * selection,
Atom * target,
Atom * returnType,
XtPointer * returnValue,
unsigned long * returnLength,
int * returnFormat,
XSelectionRequestEvent * selectionRequestEvent)
{
DtDndContext * dragData = dtDragInfo->dragData;
Display * dpy = XtDisplayOfObject(dragContext);
XmString * stringList;
Cardinal numStrings;
XTextProperty textProp;
XmICCEncodingStyle encStyle;
int status;
/*
* Select the text encoding style; reject unknown targets
*/
if (*target == XA_COMPOUND_TEXT) {
encStyle = XmSTYLE_COMPOUND_TEXT;
} else if (*target == XA_STRING) {
encStyle = XmSTYLE_STRING;
} else if (*target == XA_TEXT) {
encStyle = XmSTYLE_TEXT;
} else {
return False;
}
/*
* Convert the XmString list into a string list
*/
numStrings = dragData->numItems;
stringList = dragData->data.strings;
status = XmCvtXmStringTableToTextProperty(dpy, stringList, numStrings,
encStyle, &textProp);
if (status != Success)
return False;
/*
* Return the text property
*/
*returnType = textProp.encoding;
*returnValue = (XtPointer)textProp.value;
*returnLength = textProp.nitems;
*returnFormat = textProp.format;
return True;
}
/*
* Clean up from the convert init proc
*/
static void
dndTextConvertFinish(
DtDragInfo * dtDragInfo)
{
DtDndContext * dragData = dtDragInfo->dragData;
if (dragData->data.strings) {
XtFree((char *)dragData->data.strings);
dragData->data.strings = NULL;
}
}
/*
* Returns the transfer targets selected from the export targets
*/
static void
dndTextTransferTargets(
DtDropInfo * dtDropInfo,
Atom * exportTargets,
Cardinal numExportTargets,
Atom ** transferTargets,
Cardinal * numTransferTargets)
{
Boolean foundCT, foundText, foundString;
Atom target;
int ii;
foundCT = foundText = foundString = False;
for (ii = 0; ii < numExportTargets; ii++) {
if (exportTargets[ii] == XA_COMPOUND_TEXT) {
foundCT = True;
} else if (exportTargets[ii] == XA_TEXT) {
foundText = True;
} else if (exportTargets[ii] == XA_STRING) {
foundString = True;
}
}
if (dndPreferString && foundString) {
target = XA_STRING;
} else if (foundCT) {
target = XA_COMPOUND_TEXT;
} else if (foundText) {
target = XA_TEXT;
} else if (foundString) {
target = XA_STRING;
} else {
*numTransferTargets = 0;
*transferTargets = NULL;
return;
}
*numTransferTargets = 1;
*transferTargets = (Atom *)XtMalloc(*numTransferTargets * sizeof(Atom));
(*transferTargets)[0] = target;
}
/*
* Transfer the selection data into motif strings
*/
static void
dndTextTransfer(
Widget dropTransfer,
DtDropInfo * dtDropInfo,
Atom * selection,
Atom * target,
Atom * type,
XtPointer value,
unsigned long * length,
int * format)
{
Display * display = XtDisplayOfObject(dropTransfer);
DtDndContext * dropData = dtDropInfo->dropData;
XmString * stringList;
XTextProperty textProp;
char ** text;
int ii, status, textCount;
/*
* Ignore transfers we don't understand or if we've already transferred
*/
if (value == NULL || dropData->data.strings ||
(*target != XA_COMPOUND_TEXT &&
*target != XA_TEXT &&
*target != XA_STRING) ) {
if (value != NULL)
XtFree(value);
return;
}
/*
* Convert the text property to a text list
*/
textProp.value = (unsigned char *)value;
textProp.encoding = *type;
textProp.format = *format;
textProp.nitems = *length;
status = XmbTextPropertyToTextList(display, &textProp,
&text, &textCount);
XtFree((char *)value);
if (status != Success) {
dtDropInfo->status = DtDND_FAILURE;
return;
}
/*
* Convert the text list into a XmString list
*/
stringList = (XmString *)XtMalloc(textCount * sizeof(XmString));
for (ii = 0; ii < textCount; ii++) {
stringList[ii] = XmStringCreateLocalized(text[ii]);
}
XFreeStringList(text);
dropData->numItems = textCount;
dropData->data.strings = stringList;
}
/*
* Clean up from the transfer proc
*/
static void
dndTextTransferFinish(
DtDropInfo * dtDropInfo)
{
DtDndContext * dropData = dtDropInfo->dropData;
int ii;
for (ii = 0; ii < dropData->numItems; ii++) {
XmStringFree(dropData->data.strings[ii]);
}
XtFree((char *)dropData->data.strings);
}

View File

@@ -0,0 +1,23 @@
/* $XConsortium: Dt.c /main/4 1995/12/04 10:04:04 rswiston $ */
/*
* (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. *
*/
/*********************************************************************
*
* File: Dt.c
*
* Description: Repository for libDtSvc-wide information.
*
*********************************************************************/
#include <Dt/Dt.h>
/* CDE Version information */
externaldef(dtversion) const int DtVersion = DtVERSION_NUMBER;
externaldef(dtversionstring) const char* DtVersionString = DtVERSION_STRING;

View File

@@ -0,0 +1,71 @@
/* $TOG: Dt.h /main/12 1999/10/18 14:49:57 samborn $ */
/*
* (c) Copyright 1997, The Open Group
*/
/*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993-1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#ifndef _Dt_Dt_h
#define _Dt_Dt_h
#include <X11/Intrinsic.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Constants
*/
/* CDE Version information */
#define DtVERSION 2
#define DtREVISION 1
#define DtUPDATE_LEVEL 30
#define DtVERSION_NUMBER (DtVERSION * 10000 + \
DtREVISION * 100 + \
DtUPDATE_LEVEL)
#define DtVERSION_STRING "CDE Version 2.1.30"
/*
* CDE Version information
*/
externalref const int DtVersion;
externalref const char *DtVersionString;
/*
* Functions
*/
extern Boolean DtInitialize(
Display *display,
Widget widget,
char *name,
char *tool_class);
extern Boolean DtAppInitialize(
XtAppContext app_context,
Display *display,
Widget widget,
char *name,
char *tool_class);
#ifdef __cplusplus
}
#endif
#endif /* _Dt_Dt_h */

View File

@@ -0,0 +1,299 @@
/* $XConsortium: DtHash.c /main/4 1996/05/09 04:21:56 drk $ */
/*
Name: hash.c
Synopsis:
#include "DtHash.h"
void * _DtUtilMakeHash(int size)
void * _DtUtilMakeIHash(int size)
void ** _DtUtilGetHash(void * tbl, unsigned char * key)
void ** _DtUtilFindHash(void * tbl,unsigned char * key)
void ** _DtUtilDelHash(void * tbl, unsigned char * key)
int _DtUtilOperateHash(void * tbl, void (*op_func)(), void * usr_arg)
void _DtUtilDestroyHash(void * tbl, int (*des_func)(), void * usr_arg)
Description:
These routines provide a general purpose hash table facility that
supports multiple open hash tables. Each entry in the table consists of a
key and a data ptr. The key is a null terminated character string, while
the data ptr is opaque. Since all the entries are maintained in a doubly
linked lists, deletions and operations on entire table execute very quickly.
This make these routines suitable for use when the tables may be very ephemeral.
DtUtilMakeHash returns a pointer to the created table. The size argument
indicate the number of buckets the routine is to allocate. This should be ~
the max number of items expected in the table for maximum performance....
but /2 or /3 should still be ok. Note that for maximum efficiency the hash
table size should be a prime number (a side effect of the hash alorithm).
DtUtilMakeIHash performs the same function as DtUtilMakeHash, except that the hash
routines will use the key arguments as arbitrary integers rather than strings.
DtUtilGetHash searches the specified hash table tbl for an entry with the
specified key. If the entry does not exist, it is created with a NULL data
ptr. The routine returns a ptr to the area where the data ptr is (can be)
stored.
DtUtilFindHash searchs the table for an entry with the specified key. If the
entry is found, the address of the data pointer associated with the key is
returned. If no such entry exists, the routine returns NULL.
DtUtilDelHash deletes the specified table entry and returns the associated data
ptr. If the entry did not exist ( or the data ptr was NULL), the routine
returns NULL.
DtUtilOperateHash calls the routine pointed to by op_func once for each entry
in tbl, with three arguments: the data ptr, the usr_arg ptr and a ptr to the
key for that entry (which should NOT be altered). This is useful for
transversing a hash table quickly and operating on the entries. Note that
the order of the traversal of the hash table is the reverse order of
insertion.
DtUtilDestroyHash destroys the specified hash table after operating on it
with the specified des_func function as described for DtUtilOperateHash. All storage
allocated by the hash routines is reclaimed.
Author: Bart Smaalders 1/89
*/
#include <stdio.h> /* grab NULL define */
#include "DtHash.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int hash_string(const unsigned char * s, int modulo);
typedef struct hash_entry {
struct hash_entry
* next_entry,
* right_entry,
* left_entry;
unsigned char * key;
void * data;
} hash_entry;
typedef struct hash {
int size;
hash_entry ** table;
hash_entry * start;
enum hash_type { String_Key = 0 , Integer_Key = 1} hash_type;
} hash;
DtHashTbl _DtUtilMakeHash(int size)
{
hash * ptr;
ptr = (hash *) malloc(sizeof(*ptr));
ptr->size = size;
ptr->table = (hash_entry **) malloc( (unsigned) (sizeof(hash_entry *) * size) );
(void)memset((char *) ptr->table, (char) 0, sizeof(hash_entry *)*size);
ptr->start = NULL;
ptr->hash_type = String_Key;
return((DtHashTbl)ptr);
}
DtHashTbl _DtUtilMakeIHash(int size)
{
hash * ptr;
ptr = (hash *) malloc(sizeof(*ptr));
ptr->size = size;
ptr->table = (hash_entry **) malloc( (unsigned) (sizeof(hash_entry *) * size) );
(void)memset((char *) ptr->table, (char) 0, sizeof(hash_entry *)*size);
ptr->start = NULL;
ptr->hash_type = Integer_Key;
return((DtHashTbl) ptr);
}
void ** _DtUtilGetHash(DtHashTbl t, const unsigned char * key)
{
hash * tbl = (hash *) t;
register int bucket;
register hash_entry * tmp;
hash_entry * new;
if(tbl->hash_type == String_Key)
tmp = tbl->table[bucket = hash_string(key, tbl->size)];
else
tmp = tbl->table[bucket = abs((int)key) % tbl->size];
if(tbl->hash_type == String_Key)
while(tmp!=NULL)
{
if(strcmp((char *)tmp->key, (char*)key)==0)
return(&tmp->data);
tmp = tmp->next_entry;
}
else
while(tmp!=NULL)
{
if(tmp->key == key)
return(&tmp->data);
tmp = tmp->next_entry;
}
/*
not found....
insert new entry into bucket...
*/
new = (hash_entry *) malloc(sizeof(*new));
new->key = (unsigned char *)((tbl->hash_type == String_Key)?(unsigned char *)strdup((char*)key):key);
/*
hook into chain from tbl...
*/
new->right_entry = NULL;
new->left_entry = tbl->start;
tbl->start = new;
/*
hook into bucket chain
*/
new->next_entry = tbl->table[bucket];
tbl->table[bucket] = new;
new->data = NULL; /* so we know that it is new */
return((void*)& new->data);
}
void ** _DtUtilFindHash(DtHashTbl t, const unsigned char * key)
{
register hash * tbl = (hash *) t;
register hash_entry * tmp;
if(tbl->hash_type == String_Key)
{
tmp = tbl->table[hash_string(key, tbl->size)];
for(;tmp!=NULL; tmp = tmp->next_entry)
if(!strcmp((char*)tmp->key, (char*)key))
return((void *)&tmp->data);
}
else
{
tmp = tbl->table[abs((int)key) % tbl->size];
for(;tmp!=NULL; tmp = tmp->next_entry)
if(tmp->key == key)
return((void *)&tmp->data);
}
return(NULL);
}
void * _DtUtilDelHash(DtHashTbl t, const unsigned char * key)
{
register hash * tbl = (hash *) t;
register int bucket;
register hash_entry * tmp, * prev = NULL;
if(tbl->hash_type == String_Key)
bucket = hash_string(key, tbl->size);
else
bucket = abs((int)key) % tbl->size;
if((tmp = tbl->table[bucket])==NULL)
return(NULL);
else
{
if(tbl->hash_type == String_Key)
while(tmp!=NULL)
{
if(!strcmp((char*)tmp->key, (char*)key))
break; /* found item to delete ! */
prev = tmp;
tmp = tmp->next_entry;
}
else
while(tmp!=NULL)
{
if(tmp->key == key)
break;
prev = tmp;
tmp = tmp->next_entry;
}
if(tmp == NULL)
return(NULL); /* not found */
}
/* tmp now points to entry marked for deletion, prev to
item preceeding in bucket chain or NULL if tmp is first.
remove from bucket chain first....
*/
if(tbl->hash_type == String_Key)
free(tmp->key);
if(prev!=NULL)
prev->next_entry = tmp->next_entry;
else
tbl->table[bucket] = tmp->next_entry;
/*
now remove from tbl chain....
*/
if(tmp->right_entry !=NULL) /* not first in chain.... */
tmp->right_entry->left_entry = (tmp->left_entry ?
tmp->left_entry->right_entry: NULL);
else
tbl->start = (tmp->left_entry ?tmp->left_entry->right_entry: NULL);
return(tmp->data);
}
int _DtUtilOperateHash(DtHashTbl t, void (*ptr)(), void * usr_arg)
{
hash * tbl = (hash *) t;
register hash_entry * tmp = tbl->start;
int c = 0;
while(tmp)
{
(*ptr)(tmp->data,usr_arg, tmp->key);
tmp = tmp->left_entry;
c++;
}
return(c);
}
void _DtUtilDestroyHash(DtHashTbl t, int (*ptr)(), void * usr_arg)
{
hash * tbl = (hash *) t;
register hash_entry * tmp = tbl->start, * prev;
while(tmp)
{
if(ptr)
(*ptr)(tmp->data,usr_arg, tmp->key);
if(tbl->hash_type == String_Key)
free(tmp->key);
prev = tmp;
tmp = tmp->left_entry;
free((char *)prev);
}
free((char *)tbl->table);
free(tbl);
}
static int hash_string(register const unsigned char * s, int modulo)
{
register unsigned result = 0;
register int i=1;
while(*s!=0)
result += (*s++ << i++);
return(result % modulo);
}

View File

@@ -0,0 +1,27 @@
/* $XConsortium: DtHash.h /main/5 1996/08/29 15:42:13 cde-dec $ */
#ifndef _DtHash_h
#define _DtHash_h
typedef void * DtHashTbl;
DtHashTbl _DtUtilMakeHash(int size);
DtHashTbl _DtUtilMakeIHash(int size);
void ** _DtUtilGetHash(DtHashTbl tbl, const unsigned char * key);
void ** _DtUtilFindHash(DtHashTbl tbl,const unsigned char * key);
void * _DtUtilDelHash(DtHashTbl tbl, const unsigned char * key);
int _DtUtilOperateHash(DtHashTbl tbl, void (*op_func)(), void * usr_arg);
void _DtUtilDestroyHash(DtHashTbl tbl, int (*des_func)(), void * usr_arg);
typedef void (*DtHashOperateFunc)();
typedef int (*DtHashDestroyFunc)();
#endif /* _DtHash_h */

View File

@@ -0,0 +1,54 @@
/* $XConsortium: DtShmDb.h /main/4 1996/05/09 04:22:30 drk $ */
#ifndef DtShmDb_h
#define DtShmDb_h
/*
this include file provides prototypes for the various
shared memory database routines
*/
typedef void * DtShmProtoStrtab;
typedef void * DtShmProtoInttab;
typedef void * DtShmProtoIntList;
typedef const void * DtShmStrtab;
typedef const void * DtShmInttab;
typedef const int * DtShmIntList;
typedef int DtShmBoson;
/*
routines used while building shared memory databases
*/
DtShmProtoStrtab _DtShmProtoInitStrtab (int estimated_entries);
DtShmBoson _DtShmProtoAddStrtab (DtShmProtoStrtab prototab, const char * string, int * isnew);
const char * _DtShmProtoLookUpStrtab (DtShmProtoStrtab prototab, DtShmBoson boson);
int _DtShmProtoSizeStrtab (DtShmProtoStrtab prototab);
DtShmStrtab _DtShmProtoCopyStrtab (DtShmProtoStrtab prototab, void * dataspace);
int _DtShmProtoDestroyStrtab (DtShmProtoStrtab prototab);
DtShmProtoInttab _DtShmProtoInitInttab (int estimated_entries);
int _DtShmProtoAddInttab (DtShmProtoInttab prototab, unsigned int keyin, int datain);
int * _DtShmProtoLookUpInttab (DtShmProtoInttab prototab, unsigned int keyin);
int _DtShmProtoSizeInttab (DtShmProtoInttab prototab);
DtShmInttab _DtShmProtoCopyInttab (DtShmProtoInttab prototab, void * dataspace);
int _DtShmProtoDestroyInttab (DtShmProtoInttab prototab);
DtShmProtoIntList _DtShmProtoInitIntLst (int estimated_entries);
int * _DtShmProtoAddIntLst (DtShmProtoIntList protolist, int size, int * index_value);
int _DtShmProtoSizeIntLst (DtShmProtoIntList protolist);
DtShmIntList _DtShmProtoCopyIntLst (DtShmProtoIntList protolist, void * dataspace);
int _DtShmProtoDestroyIntLst (DtShmProtoIntList protolist);
/*
run-time routines once shared memory area is built
*/
DtShmBoson _DtShmStringToBoson (DtShmStrtab tab, const char * string);
const char * _DtShmBosonToString (DtShmStrtab tab, DtShmBoson boson);
const int * _DtShmFindIntTabEntry (DtShmInttab tab, unsigned int key);
#endif /* DtShmDb_h */

2235
cde/lib/DtSvc/DtUtil1/Dts.c Normal file

File diff suppressed because it is too large Load Diff

159
cde/lib/DtSvc/DtUtil1/Dts.h Normal file
View File

@@ -0,0 +1,159 @@
/* $XConsortium: Dts.h /main/5 1996/03/05 13:30:59 drk $ */
/*
* (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.
*/
#ifndef _Dt_Dts_h
#define _Dt_Dts_h
#include <sys/stat.h>
#include <X11/Intrinsic.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Constants
*/
#define DtDTS_DC_NAME "DATA_CRITERIA"
#define DtDTS_NAME_PATTERN "NAME_PATTERN"
#define DtDTS_PATH_PATTERN "PATH_PATTERN"
#define DtDTS_CONTENT "CONTENT"
#define DtDTS_MODE "MODE"
#define DtDTS_LINK_PATH "LINK_PATH"
#define DtDTS_LINK_NAME "LINK_NAME"
#define DtDTS_DATA_ATTRIBUTES_NAME "DATA_ATTRIBUTES_NAME"
#define DtDTS_DT_RECURSIVE_LINK "RECURSIVE_LINK"
#define DtDTS_DT_BROKEN_LINK "BROKEN_LINK"
#define DtDTS_DT_UNKNOWN "UNKNOWN"
#define DtDTS_DA_IS_SYNTHETIC "IS_SYNTHETIC"
#define DtDTS_DA_LABEL "LABEL"
#define DtDTS_DA_NAME "DATA_ATTRIBUTES"
#define DtDTS_DA_DESCRIPTION "DESCRIPTION"
#define DtDTS_DA_DATA_HOST "DATA_HOST"
#define DtDTS_DA_ICON "ICON"
#define DtDTS_DA_INSTANCE_ICON "INSTANCE_ICON"
#define DtDTS_DA_PROPERTIES "PROPERTIES"
#define DtDTS_DA_ACTION_LIST "ACTIONS"
#define DtDTS_DA_NAME_TEMPLATE "NAME_TEMPLATE"
#define DtDTS_DA_MODE_TEMPLATE "MODE_TEMPLATE"
#define DtDTS_DA_MOVE_TO_ACTION "MOVE_TO_ACTION"
#define DtDTS_DA_COPY_TO_ACTION "COPY_TO_ACTION"
#define DtDTS_DA_LINK_TO_ACTION "LINK_TO_ACTION"
#define DtDTS_DA_IS_TEXT "IS_TEXT"
#define DtDTS_DA_MEDIA "MEDIA"
#define DtDTS_DA_MIME_TYPE "MIME_TYPE"
#define DtDTS_DA_MIME_TO_MEDIA_FILTER "MIME_TO_MEDIA_FILTER"
#define DtDTS_DA_MEDIA_TO_MIME_FILTER "MEDIA_TO_MIME_FILTER"
#define DtDTS_DA_X400_TYPE "X400_TYPE"
#define DtDTS_DA_X400_TO_MEDIA_FILTER "X400_TO_MEDIA_FILTER"
#define DtDTS_DA_MEDIA_TO_X400_FILTER "MEDIA_TO_X400_FILTER"
#define DtDTS_DA_IS_ACTION "IS_ACTION"
#define DtDTS_DA_IS_EXECUTABLE "IS_EXECUTABLE"
#define DtDTS_DT_DIR ".DtDirDataType"
/*
* Types
*/
typedef struct _DtDtsAttribute
{
char *name;
char *value;
} DtDtsAttribute;
/*
* Functions
*/
extern void DtDtsLoadDataTypes(void);
extern void DtDtsRelease(void);
extern char *DtDtsDataToDataType(
const char *filepath,
const void *buffer,
const int size,
const struct stat *stat_buff,
const char *link_name,
const struct stat *link_stat_buff,
const char *opt_name);
extern char *DtDtsFileToDataType(
const char *filepath);
extern char *DtDtsFileToAttributeValue(
const char *filepath,
const char *attr);
extern DtDtsAttribute **DtDtsFileToAttributeList(
const char *filepath);
extern char *DtDtsBufferToDataType(
const void *buffer,
const int size,
const char *opt_name);
extern char *DtDtsBufferToAttributeValue(
const void *buffer,
const int size,
const char *attr,
const char *opt_name);
extern DtDtsAttribute **DtDtsBufferToAttributeList(
const void *buffer,
const int size,
const char *opt_name);
extern char *DtDtsDataTypeToAttributeValue(
const char *datatype,
const char *attr,
const char *opt_name);
extern DtDtsAttribute **DtDtsDataTypeToAttributeList(
const char *datatype,
const char *opt_name);
extern void DtDtsFreeDataTypeNames(
char **namelist);
extern void DtDtsFreeAttributeList(
DtDtsAttribute **attr_list);
extern void DtDtsFreeAttributeValue(
char *attr_value);
extern void DtDtsFreeDataType(
char *datatype);
extern char **DtDtsDataTypeNames(void);
extern char **DtDtsFindAttribute(
const char *name,
const char *value);
extern char *DtDtsSetDataType(
const char *filepath,
const char *datatype,
const int override);
extern int DtDtsDataTypeIsAction(
const char *datatype);
extern Boolean DtDtsIsTrue(
const char *str);
#ifdef __cplusplus
}
#endif
#endif /* _Dt_Dts_h */

View File

@@ -0,0 +1,539 @@
/*
* (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. *
*/
/*
*+SNOTICE
*
* $TOG: DtsDb.c /main/10 1998/10/23 13:48:04 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef SUN_DB
#include <sys/mman.h>
#endif
#include <string.h>
#include <Dt/DbReader.h>
#include "Dt/DtsDb.h"
#include <Dt/UserMsg.h>
#include "DtSvcLock.h"
extern char *strdup(const char *);
#define PADMEM 10
typedef int (*genfunc)(const void *, const void *);
static DtDtsDbDatabase **db_list;
static int num_db = 0;
_DtDtsDbPrintFields(DtDtsDbRecord *rec_ptr, FILE *fd)
{
int fld;
DtDtsDbField *fld_ptr;
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
{
fld_ptr = rec_ptr->fieldList[fld];
fprintf(fd, "\t\t[%d]\t%s\t%s\n", fld,
XrmQuarkToString(fld_ptr->fieldName),
fld_ptr->fieldValue?
fld_ptr->fieldValue:"(NULL)");
}
}
_DtDtsDbPrintRecords(DtDtsDbDatabase *db_ptr, FILE *fd)
{
int rec;
DtDtsDbRecord *rec_ptr;
_DtSvcProcessLock();
fprintf(fd, "%d Records\n", db_ptr->recordCount);
for(rec = 0; rec < db_ptr->recordCount; rec++)
{
rec_ptr = db_ptr->recordList[rec];
fprintf(fd, "\tRec[%d] name = %s\n\t%d Fields\n", rec,
XrmQuarkToString(rec_ptr->recordName),
rec_ptr->fieldCount);
_DtDtsDbPrintFields(rec_ptr, fd);
}
_DtSvcProcessUnlock();
}
void
_DtDtsDbPrint(FILE *org_fd)
{
int db;
int rec;
DtDtsDbDatabase *db_ptr;
DtDtsDbRecord *rec_ptr;
FILE *fd = org_fd;
_DtSvcProcessLock();
for(db = 0; db < num_db; db++)
{
if(!db_list[db])
{
continue;
}
db_ptr = db_list[db];
if(fd == 0)
{
chdir("/tmp");
if((fd = fopen(db_ptr->databaseName, "w")) == NULL)
{
_DtSimpleError(
DtProgName, DtError, NULL,
db_ptr->databaseName, NULL);
continue;
}
}
fprintf(fd, "DB[%d] ", db);
fprintf(fd, "name = %s\n", db_ptr->databaseName);
_DtDtsDbPrintRecords(db_ptr, fd);
if(org_fd == 0)
{
fclose(fd);
fd = 0;
}
}
_DtSvcProcessUnlock();
}
int
_DtDtsDbCompareRecordNames(DtDtsDbRecord **a, DtDtsDbRecord **b)
{
return ((*a)->recordName - (*b)->recordName);
}
int
_DtDtsDbCompareFieldNames(DtDtsDbField **a, DtDtsDbField **b)
{
return ((*a)->fieldName - (*b)->fieldName);
}
#include <Dt/Dts.h>
DtDtsDbDatabase **
_DtDtsDbInit(void)
{
DtDtsDbDatabase **db;
_DtSvcProcessLock();
num_db = 0;
db = db_list = (DtDtsDbDatabase **)calloc(num_db+3, sizeof(DtDtsDbDatabase *));
db_list[0] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
db_list[0]->databaseName = (char *)strdup(DtDTS_DC_NAME);
db_list[0]->ActionSequenceNumber = 0;
num_db++;
db_list[1] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
db_list[1]->databaseName = (char *)strdup(DtDTS_DA_NAME);
db_list[1]->ActionSequenceNumber = 0;
num_db++;
_DtSvcProcessUnlock();
return(db);
}
char **
_DtsDbListDb()
{
int i;
char **list = 0;
_DtSvcProcessLock();
for ( i = 0; db_list[i]; i++ );
if(i > 0)
{
list = (char **)calloc(i+1, sizeof(char *));
for ( i = 0; db_list[i]; i++ )
{
list[i] = (char *)strdup(db_list[i]->databaseName);
}
}
_DtSvcProcessUnlock();
return(list);
}
DtDtsDbDatabase *
_DtDtsDbAddDatabase( char *db_name )
{
int i = 0;
DtDtsDbDatabase **new_db_list;
DtDtsDbDatabase *ret_db;
_DtSvcProcessLock();
if ( !db_list )
{
_DtDtsDbInit();
}
for ( i = 0; db_list[i]; i++ )
{
if ( !strcmp(db_list[i]->databaseName,db_name) )
{
/*
* A database with the given name already exists.
* return a pointer to the existing database.
*/
ret_db = db_list[i];
_DtSvcProcessUnlock();
return ret_db;
}
}
/*
* We now have a count of the existing databases.
* allocate enough space for the existing databases + the new one
* + a NULL pointer to terminate the vector.
*/
new_db_list = (DtDtsDbDatabase **)calloc(i+2,sizeof(DtDtsDbDatabase *));
memmove(new_db_list,db_list,sizeof(DtDtsDbDatabase *) * i );
new_db_list[i] = (DtDtsDbDatabase *)calloc(1, sizeof(DtDtsDbDatabase));
new_db_list[i]->databaseName = strdup(db_name);
new_db_list[i]->ActionSequenceNumber = 0;
free(db_list);
db_list = new_db_list;
num_db++;
ret_db = db_list[i];
_DtSvcProcessUnlock();
return ret_db;
}
int
_DtDtsDbDeleteDb(DtDtsDbDatabase *db)
{
int i;
int flag = 0;
_DtSvcProcessLock();
_DtDtsDbDeleteRecords(db);
if(db->databaseName) free(db->databaseName);
if(db) free(db);
for(i = 0; db_list[i]; i++)
{
if(db_list[i] == db)
{
flag = 1;
db_list[i] = 0;
}
if(flag)
{
db_list[i] = db_list[i+1];
}
}
if(db_list[0] == 0)
{
if(db_list)free(db_list);
db_list = 0;
}
_DtSvcProcessUnlock();
return(0);
}
DtDtsDbDatabase *
_DtDtsDbGet(char *name)
{
DtDtsDbDatabase *ret_db;
int i;
_DtSvcProcessLock();
if(!db_list)
{
_DtDtsDbInit();
}
for(i = 0; db_list && db_list[i] && db_list[i]->databaseName; i++)
{
if(strcmp(db_list[i]->databaseName, name) == 0)
{
ret_db = db_list[i];
_DtSvcProcessUnlock();
return(ret_db);
}
}
_DtSvcProcessUnlock();
return(NULL);
}
void
_DtDtsDbFieldSort(DtDtsDbRecord *rec, _DtDtsDbFieldCompare compare)
{
if(compare == NULL)
{
compare = _DtDtsDbCompareFieldNames;
}
qsort(rec->fieldList,
rec->fieldCount,
sizeof(DtDtsDbField *),
(genfunc)compare);
rec->compare = compare;
}
void
_DtDtsDbRecordSort(DtDtsDbDatabase *db, _DtDtsDbRecordCompare compare)
{
if(compare == NULL)
{
compare = _DtDtsDbCompareRecordNames;
}
qsort(db->recordList,
db->recordCount,
sizeof(DtDtsDbRecord *),
(genfunc)compare);
db->compare = compare;
}
DtDtsDbField *
_DtDtsDbGetField(DtDtsDbRecord *rec, char *name)
{
register int i;
/*
* Field names have been quarked so quark 'name' and
* do a linear search for the quark'ed field name.
*/
XrmQuark tmp = XrmStringToQuark (name);
for (i = 0; i < rec->fieldCount; i++)
{
if (rec->fieldList[i]->fieldName == tmp)
{
return (rec->fieldList[i]);
}
}
return(NULL);
}
char *
_DtDtsDbGetFieldByName(DtDtsDbRecord *rec, char *name)
{
DtDtsDbField *result;
result = _DtDtsDbGetField(rec, name);
if(result)
{
return(result->fieldValue);
}
else
{
return(NULL);
}
}
DtDtsDbRecord *
_DtDtsDbGetRecordByName(DtDtsDbDatabase *db, char *name)
{
DtDtsDbRecord srch;
DtDtsDbRecord **result;
DtDtsDbRecord *s = &srch;
register int i;
XrmQuark name_quark = XrmStringToQuark(name);
/*
* If the fields are not sorted in alphanumeric order
* by name a binary search will fail. So do the slow but
* sure linear search.
*/
if(db->compare != _DtDtsDbCompareRecordNames)
{
for (i = 0; i < db->recordCount; i++)
{
if (db->recordList[i]->recordName == name_quark)
{
return (db->recordList[i]);
}
}
return NULL;
}
srch.recordName = name_quark;
if(db->recordCount == 0 || db->recordList == NULL)
{
result = NULL;
}
else
{
result = (DtDtsDbRecord **)bsearch(&s,
db->recordList,
db->recordCount,
sizeof(DtDtsDbRecord *),
(genfunc)_DtDtsDbCompareRecordNames);
}
if(result)
{
return(*result);
}
else
{
return(NULL);
}
}
DtDtsDbRecord *
_DtDtsDbAddRecord(DtDtsDbDatabase *db)
{
DtDtsDbRecord **newlist;
int rec = db->recordCount;
db->compare = (_DtDtsDbRecordCompare)NULL;
if(rec%PADMEM == 0)
{
newlist = (DtDtsDbRecord **)calloc(rec+PADMEM,
sizeof(DtDtsDbRecord *));
if(db->recordList)
{
memmove(newlist, db->recordList,
rec*sizeof(DtDtsDbRecord *));
if(db->recordList) free(db->recordList);
}
db->recordList = newlist;
}
db->recordList[rec] = (DtDtsDbRecord *)calloc(1, sizeof(DtDtsDbRecord));
db->recordCount++;
return(db->recordList[rec]);
}
int
_DtDtsDbDeleteRecord(DtDtsDbRecord *rec, DtDtsDbDatabase *db)
{
int i;
_DtDtsDbDeleteFields(rec);
if(rec) free(rec);
for(i = 0; i < db->recordCount; i++)
{
if(db->recordList[i] == rec)
{
memmove( &(db->recordList[i]),
&(db->recordList[i+1]),
(db->recordCount - i - 1)*
sizeof(DtDtsDbRecord *));
db->recordCount--;
return(1);
}
}
return(0);
}
int
_DtDtsDbDeleteRecords(DtDtsDbDatabase *db)
{
int i;
for(i = 0; i < db->recordCount; i++)
{
_DtDtsDbDeleteFields(db->recordList[i]);
if(db->recordList[i])
free(db->recordList[i]);
}
if(db->recordList)
free(db->recordList);
db->recordList = 0;
return(0);
}
DtDtsDbField *
_DtDtsDbAddField(DtDtsDbRecord *rec)
{
DtDtsDbField **newlist;
int flds = rec->fieldCount;
if(flds%PADMEM == 0)
{
newlist = (DtDtsDbField **)calloc(flds+PADMEM,
sizeof(DtDtsDbField *));
if(rec->fieldList)
{
memmove(newlist, rec->fieldList,
flds*sizeof(DtDtsDbField *));
if(rec->fieldList)
free(rec->fieldList);
}
rec->fieldList = newlist;
}
rec->fieldList[flds] = (DtDtsDbField *)calloc(1, sizeof(DtDtsDbField));
rec->fieldCount++;
return(rec->fieldList[flds]);
}
int
_DtDtsDbDeleteField(DtDtsDbField *fld, DtDtsDbRecord *rec)
{
int i;
if(fld) free(fld);
for(i = 0; i < rec->fieldCount; i++)
{
if(rec->fieldList[i] == fld)
{
memmove( &(rec->fieldList[i]),
&(rec->fieldList[i+1]),
(rec->fieldCount - i - 1)*
sizeof(DtDtsDbField *));
rec->fieldCount--;
return(1);
}
}
return(0);
}
int
_DtDtsDbDeleteFields(DtDtsDbRecord *rec)
{
int i;
for(i = 0; i < rec->fieldCount; i++)
{
if(rec->fieldList[i]->fieldValue)
free(rec->fieldList[i]->fieldValue);
if(rec->fieldList[i])
free(rec->fieldList[i]);
}
if(rec->fieldList) free(rec->fieldList);
rec->fieldList = 0;
return(0);
}
int
_DtDtsMMCreateFile(DtDirPaths *dirs, const char *CacheFile)
{
return _MMWriteDb(dirs, num_db, db_list, CacheFile);
}

View File

@@ -0,0 +1,132 @@
/*
* (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. *
*/
/*
*+SNOTICE
*
* $XConsortium: DtsDb.h /main/5 1996/08/28 14:32:17 rswiston $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#ifndef DT_DTS_DB_H
#define DT_DTS_DB_H
#include <X11/Xresource.h>
#include <Dt/DbReader.h>
typedef int OtBoolean;
/* typedefs for casting comparison functions if needed */
typedef int (*_DtDtsDbFieldCompare)(DtDtsDbField **fld1, DtDtsDbField **fld2);
/* entry of a list of attribute/pairs */
typedef struct
{
XrmQuark recordName;
_DtDtsDbFieldCompare compare;
long pathId;
int seq;
int fieldCount;
DtDtsDbField **fieldList;
} DtDtsDbRecord;
/* typedefs for casting record comparison functions if needed */
typedef int (*_DtDtsDbRecordCompare)(DtDtsDbRecord **rec1, DtDtsDbRecord **rec2);
/* a "database" of a collection of entrys (i.e. OBJECT-TYPE, ACTION, FILE-TYPE
This is a private Structure to the DtDtsDb component.
*/
typedef struct
{
char *databaseName;
_DtDtsDbRecordCompare compare;
int recordCount;
DtDtsDbRecord **recordList;
unsigned long ActionSequenceNumber;
} DtDtsDbDatabase;
/* for the mmaped database this the use_in_memory_db variable is used
to call the old API while the database is being built and is set to
false when the mmaped versions are being accessed.
*/
extern int use_in_memory_db;
/*
* adds a new database to the list of databases -- returns a pointer to the
* new database. If a database of the given name already exists it returns
* a pointer to that database.
*/
extern DtDtsDbDatabase *_DtDtsDbAddDatabase( char *dbname );
/* returns the handle for the database where name is the Database name */
extern DtDtsDbDatabase *_DtDtsDbGet(char *name);
extern char **_DtDtsDbListDb(void);
/* Record Sort function:
* sorts the specified database, usually obtained from _DtDtsDbGet(), in the
* order specified by the comparison function. If (*compare) == 0 then
* _DtDtsDbCompareRecordNames() is used as the (*compare) function.
*/
extern void _DtDtsDbRecordSort(DtDtsDbDatabase *database,
_DtDtsDbRecordCompare compare);
/* Field Sort function:
* sorts the specified Record in the order specified by the comparison function
* If (*compare) == 0 then _DtDtsDbCompareFieldNames() is used as the
* (*compare) function.
*/
extern void _DtDtsDbFieldSort(DtDtsDbRecord *record,
_DtDtsDbFieldCompare compare);
/* Name Comparison functions:
* These routines can be passed in to the corresponding sort function to
* sort by name.
*
*/
extern int _DtDtsDbCompareRecordNames(DtDtsDbRecord **entry1, DtDtsDbRecord **entry2);
extern int _DtDtsDbCompareFieldNames(DtDtsDbField **entry1, DtDtsDbField **entry2);
/* retrieves the Record that matches the specified entry from the record */
extern DtDtsDbField *_DtDtsDbGetField(DtDtsDbRecord *record,
char *value);
/* retrieves the entry of the specified entry from the specified database */
extern DtDtsDbRecord *_DtDtsDbGetRecord(DtDtsDbDatabase *database,
DtDtsDbRecord *value);
/* Get By Name functions:
* retrieves the entry of the specified name from the specified database
* ** IF ** the _DtDtsDb*Sort routine has been called with the corresponding
* _DtDtsDbCompare*Name comparison function. Otherwise use the standard
* _DtDtsDbGet* functions.
*/
extern char *_DtDtsDbGetFieldByName(DtDtsDbRecord *record, char *name);
extern DtDtsDbRecord *_DtDtsDbGetRecordByName(DtDtsDbDatabase *database, char *name);
extern DtDtsDbRecord *_DtDtsDbAddRecord(DtDtsDbDatabase *db);
extern DtDtsDbField *_DtDtsDbAddField(DtDtsDbRecord *rec);
extern int _DtDtsDbDeleteDb(DtDtsDbDatabase *db);
extern int _DtDtsDbDeleteRecord(DtDtsDbRecord *rec, DtDtsDbDatabase *db);
extern int _DtDtsDbDeleteRecords(DtDtsDbDatabase *db);
extern int _DtDtsDbDeleteField(DtDtsDbField *fld, DtDtsDbRecord *rec);
extern int _DtDtsDbDeleteFields(DtDtsDbRecord *rec);
#endif

View File

@@ -0,0 +1,227 @@
/*
* (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. *
*/
/*
* +SNOTICE
*
* $XConsortium: DtsInit.c /main/5 1996/08/28 16:08:50 rswiston $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special restrictions in a
* confidential disclosure agreement bertween HP, IBM, Sun, USL, SCO and
* Univel. Do not distribute this document outside HP, IBM, Sun, USL, SCO,
* or Univel wihtout Sun's specific written approval. This documment and all
* copies and derivative works thereof must be returned or destroyed at Sun's
* request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
* +ENOTICE
*/
#include <stdio.h>
#include <sys/types.h>
#ifdef __hpux
#include <ndir.h>
#else
#if defined(sun) || defined(USL) || defined(sco) || defined(__uxp__)
#include <dirent.h>
#else
#include <sys/dir.h>
#endif /* sun || USL */
#endif /* __hpux */
#include <ctype.h>
#include <string.h>
#ifdef NLS16
#include <limits.h>
#endif
#include <sys/stat.h>
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
#include <Dt/DbReader.h>
#include <Dt/DtsDb.h>
#include <Dt/Dts.h>
#include "DtSvcLock.h"
extern char *strdup(const char *);
static int cur_dc_count = 0;
static int cur_da_count = 0;
#define _DtFT_NUM_FIELDS 20
int
_DtDtsNextDCSeq()
{
int nextDCSeq;
_DtSvcProcessLock();
nextDCSeq = ++cur_dc_count;
_DtSvcProcessUnlock();
return(nextDCSeq);
}
int
_DtDtsNextDASeq()
{
int nextDASeq;
_DtSvcProcessLock();
nextDASeq = ++cur_da_count;
_DtSvcProcessUnlock();
return(nextDASeq);
}
void
_DtDtsSeqReset()
{
_DtSvcProcessLock();
cur_dc_count = 0;
cur_da_count = 0;
_DtSvcProcessUnlock();
}
void
_DtDtsDCConverter(DtDtsDbField * fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus)
{
DtDtsDbDatabase *db;
DtDtsDbRecord *rec;
DtDtsDbField *fld;
int i = 0;
_DtSvcProcessLock();
db = _DtDtsDbGet(DtDTS_DC_NAME);
while (fields[i].fieldName && fields[i].fieldValue)
{
if (i == 0)
{
if(rec=_DtDtsDbGetRecordByName(db,fields[i].fieldValue))
{
char *value = _DtDtsDbGetFieldByName(rec,DtDTS_DA_IS_SYNTHETIC);
/*
* Check if the record is SYNTHETIC --
* if so then replace it with this real
* definition -- otherwise return.
*/
if (value && !strcmp(value,"True") )
{
/* free up the current record */
_DtDtsDbDeleteRecord(rec,db);
}
else
{
_DtSvcProcessUnlock();
return;
}
}
rec = _DtDtsDbAddRecord(db);
rec->recordName = XrmStringToQuark(fields[i].fieldValue);
rec->seq = _DtDtsNextDCSeq();
rec->pathId = (int)pathId;
}
else
{
fld = _DtDtsDbAddField(rec);
fld->fieldName = fields[i].fieldName;
fld->fieldValue = strdup(fields[i].fieldValue);
}
i++;
}
_DtSvcProcessUnlock();
}
void
_DtDtsDAConverter(DtDtsDbField * fields,
DtDbPathId pathId,
char *hostPrefix,
Boolean rejectionStatus)
{
DtDtsDbDatabase *db;
DtDtsDbRecord *rec;
DtDtsDbField *fld;
int i = 0;
_DtSvcProcessLock();
db = _DtDtsDbGet(DtDTS_DA_NAME);
while (fields[i].fieldName && fields[i].fieldValue)
{
if (i == 0)
{
if(rec = _DtDtsDbGetRecordByName(db, fields[i].fieldValue))
{
char *value = _DtDtsDbGetFieldByName(rec,DtDTS_DA_IS_SYNTHETIC);
/*
* Check if the record is SYNTHETIC --
* if so then replace it with this real
* definition -- otherwise return.
*/
if (value && !strcmp(value,"True") )
{
/* free up the current record */
_DtDtsDbDeleteRecord(rec,db);
}
else
{
_DtSvcProcessUnlock();
return;
}
}
rec = _DtDtsDbAddRecord(db);
rec->recordName = XrmStringToQuark(fields[i].fieldValue);
rec->seq = _DtDtsNextDASeq();
fld = _DtDtsDbAddField(rec);
fld->fieldName = XrmStringToQuark(DtDTS_DA_DATA_HOST);
fld->fieldValue = hostPrefix?strdup(hostPrefix):(char *) 0;
rec->pathId = (int)pathId;
}
else
{
fld = _DtDtsDbAddField(rec);
fld->fieldName = fields[i].fieldName;
fld->fieldValue = strdup(fields[i].fieldValue);
}
i++;
}
_DtSvcProcessUnlock();
}
/******************************************************************************
*
* DtDtsLoadDataTypes -
*
* Reads in the file types and action databases.
*
* Also initializes the variable DtMaxFileTypes to the number
* of entries in the file types database.
*
* MODIFIED:
*
* DtMaxFtFileTypes
* DtMaxFileTypes - set to the number of real filetypes
* ( Holdovers from previous filetypes stuff -- still used by
* some clients. i.e. dtfile )
*
*****************************************************************************/
void
DtDtsLoadDataTypes(void)
{
/* with new mmap database this function is not needed to
* load the database. Just to initialize it.
*/
_DtDtsMMUnLoad();
}

View File

@@ -0,0 +1,752 @@
/*
* $TOG: DtsMM.c /main/16 1998/10/23 13:48:28 mgreess $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* (c) Copyright 1993,1994,1995 Sun Microsystems, Inc.
* All rights reserved.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SUN_DB
#ifdef SUN_DB
#include <sys/utsname.h>
#include <dirent.h>
#include <sys/mman.h>
#include <sys/param.h>
#endif
#include <string.h>
#define X_INCLUDE_DIRENT_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <Dt/DbReader.h>
#include "Dt/DtsMM.h"
#include "Dt/DtNlUtils.h"
#include <Dt/UserMsg.h>
#include "DtSvcLock.h"
extern char *strdup(const char *);
static int MMValidateDb(DtDirPaths *dirs, char *suffix);
static int _debug_print_name(char *name, char *label);
typedef int (*genfunc)(const void *, const void *);
static DtDtsMMDatabase *db_list;
static caddr_t mmaped_db = 0;
static size_t mmaped_size = 0;
static int mmaped_fd = 0;
static DtDtsMMHeader *head = 0;
void *
_DtDtsMMGetPtr(int index)
{
DtShmIntList int_list;
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
int_list = (DtShmIntList)&mmaped_db[sizeof(DtDtsMMHeader)];
_DtSvcProcessUnlock();
return((void *)&int_list[index]);
}
int
_DtDtsMMGetPtrSize(int index)
{
DtShmIntList int_list;
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
int_list = (DtShmIntList)&mmaped_db[sizeof(DtDtsMMHeader)];
_DtSvcProcessUnlock();
return(int_list[index-1]);
}
int *
_DtDtsMMGetDCNameIndex(int *size)
{
int *result;
_DtSvcProcessLock();
*size = _DtDtsMMGetPtrSize(head->name_list_offset);
result = (int*) _DtDtsMMGetPtr(head->name_list_offset);
_DtSvcProcessUnlock();
return(result);
}
int *
_DtDtsMMGetDbName(DtDtsMMDatabase *db, DtShmBoson boson)
{
DtShmInttab tab = (DtShmInttab)_DtDtsMMGetPtr(db->nameIndex);
return((int *)_DtShmFindIntTabEntry(tab, boson));
}
int *
_DtDtsMMGetNoNameIndex(int *size)
{
int *result;
_DtSvcProcessLock();
if(head->no_name_offset == -1)
{
*size = 0;
_DtSvcProcessUnlock();
return(0);
}
*size = _DtDtsMMGetPtrSize(head->no_name_offset);
result = (int *) _DtDtsMMGetPtr(head->no_name_offset);
_DtSvcProcessUnlock();
return(result);
}
/* returns the pointer to buffer only name list */
int *
_DtDtsMMGetBufferIndex(int *size)
{
int *list = (int*)_DtDtsMMGetNoNameIndex(size);
int *bufferIndex;
_DtSvcProcessLock();
*size -= head->buffer_start_index;
bufferIndex = &list[head->buffer_start_index];
_DtSvcProcessUnlock();
return(bufferIndex);
}
DtShmInttab
_DtDtsMMGetFileList(void)
{
DtShmInttab file_index;
_DtSvcProcessLock();
file_index = (DtShmStrtab)_DtDtsMMGetPtr(head->files_offset);
_DtSvcProcessUnlock();
return(file_index);
}
const char *
_DtDtsMMBosonToString(DtShmBoson boson)
{
DtShmStrtab str_table;
if (boson == 0)
return(0);
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
str_table = (DtShmStrtab)_DtDtsMMGetPtr(head->str_tbl_offset);
_DtSvcProcessUnlock();
return(_DtShmBosonToString(str_table, boson));
}
DtShmBoson
_DtDtsMMStringToBoson(const char *string)
{
DtShmStrtab str_table;
if ((string == (char *)NULL) || (*string == '\0'))
return(-1);
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
str_table = (DtShmStrtab)_DtDtsMMGetPtr(head->str_tbl_offset);
_DtSvcProcessUnlock();
return(_DtShmStringToBoson(str_table, string));
}
void
_DtDtsMMPrintFld(int fld, DtDtsMMField *fld_ptr, FILE *fd_in)
{
const char *tmp;
const char *tmpv;
FILE *fd = fd_in;
if(!fd) fd = stdout;
tmp = _DtDtsMMBosonToString(fld_ptr->fieldName);
tmpv = _DtDtsMMBosonToString(fld_ptr->fieldValue);
fprintf(fd, "\t\t[%d]\t%s(%d)\t%s(%d)\n", fld, tmp,fld_ptr->fieldName,
tmpv?tmpv:"(NULL)", fld_ptr->fieldValue);
}
void
_DtDtsMMPrintRec(int rec, DtDtsMMRecord *rec_ptr, FILE *fd_in)
{
int fld;
DtDtsMMField *fld_ptr;
DtDtsMMField *fld_ptr_list;
const char *tmp;
FILE *fd = fd_in;
if(!fd) fd = stdout;
tmp = _DtDtsMMBosonToString(rec_ptr->recordName);
fprintf(fd, "\tRec[%d] name = %s(%d)\n\t%d Fields\n", rec,
tmp, rec_ptr->recordName,
rec_ptr->fieldCount);
fld_ptr_list = _DtDtsMMGetPtr(rec_ptr->fieldList);
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
{
fld_ptr = &fld_ptr_list[fld];
_DtDtsMMPrintFld(fld, fld_ptr, fd);
}
}
void
_DtDtsMMPrintDb(int db, DtDtsMMDatabase *db_ptr, FILE *fd_in)
{
int rec;
DtDtsMMRecord *rec_ptr;
DtDtsMMRecord *rec_ptr_list;
const char *tmp;
FILE *fd = fd_in;
if(!fd) fd = stdout;
fprintf(fd, "DB[%d] ", db);
tmp = _DtDtsMMBosonToString(db_ptr->databaseName);
fprintf(fd, "name = %s(%d)\n", tmp, db_ptr->databaseName);
fprintf(fd, "%d Records\n", db_ptr->recordCount);
rec_ptr_list = _DtDtsMMGetPtr(db_ptr->recordList);
for(rec = 0; rec < db_ptr->recordCount; rec++)
{
rec_ptr = &rec_ptr_list[rec];
_DtDtsMMPrintRec(rec, rec_ptr, fd);
}
}
void
_DtDtsMMPrint(FILE *org_fd)
{
int db;
DtDtsMMDatabase *db_ptr;
FILE *fd = org_fd;
const char *tmp;
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
for(db = 0; db < head->num_db; db++)
{
db_ptr = &db_list[db];
if(fd == 0)
{
chdir("/tmp");
tmp = _DtDtsMMBosonToString(db_ptr->databaseName);
if((fd = fopen(tmp, "w")) == NULL)
{
_DtSimpleError(
DtProgName, DtError, NULL,
(char*) tmp, NULL);
continue;
}
}
_DtDtsMMPrintDb(db, db_ptr, fd);
if(org_fd == 0)
{
fclose(fd);
fd = 0;
}
}
_DtSvcProcessUnlock();
}
int
_DtDtsMMCompareRecordNames(DtDtsMMRecord *a, DtDtsMMRecord *b)
{
return (a->recordName - b->recordName);
}
int
_DtDtsMMCompareFieldNames(DtDtsMMField *a, DtDtsMMField *b)
{
return (a->fieldName - b->fieldName);
}
#include <Dt/Dts.h>
int
_DtDtsMMInit(int override)
{
DtDirPaths *dirs = _DtGetDatabaseDirPaths();
char *CacheFile = _DtDtsMMCacheName(1);
if(override)
{
if (!_DtDtsMMCreateDb(dirs, CacheFile, override))
{
free(CacheFile);
_DtFreeDatabaseDirPaths(dirs);
return 0;
}
_debug_print_name(CacheFile, "Init");
}
else
{
int success = _DtDtsMMapDB(CacheFile);
if(success)
{
if(!MMValidateDb(dirs, ".dt"))
{
success = 0;
}
else
{
_debug_print_name(CacheFile, "Mapped");
}
}
if(!success)
{
free(CacheFile);
CacheFile = _DtDtsMMCacheName(0);
_debug_print_name(CacheFile, "Private");
/* Check return status, and pass status to caller. */
if (!_DtDtsMMCreateDb(dirs, CacheFile, override))
{
free(CacheFile);
_DtFreeDatabaseDirPaths(dirs);
return 0;
}
}
}
free(CacheFile);
_DtFreeDatabaseDirPaths(dirs);
return 1;
}
char **
_DtsMMListDb()
{
int i;
char **list;
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
list = (char **)malloc((head->num_db+1)*sizeof(char *));
for ( i = 0; i < head->num_db; i++ )
{
list[i] = (char *)_DtDtsMMBosonToString(db_list[i].databaseName);
}
list[i] = 0;
_DtSvcProcessUnlock();
return(list);
}
DtDtsMMDatabase *
_DtDtsMMGet(const char *name)
{
int i;
DtShmBoson boson = _DtDtsMMStringToBoson(name);
DtDtsMMDatabase *ret_db;
_DtSvcProcessLock();
if(!mmaped_db)
{
_DtDtsMMInit(0);
}
for(i = 0; i < head->num_db; i++)
{
if(db_list[i].databaseName == boson)
{
ret_db = &db_list[i];
_DtSvcProcessUnlock();
return(ret_db);
}
}
_DtSvcProcessUnlock();
return(NULL);
}
DtDtsMMField *
_DtDtsMMGetField(DtDtsMMRecord *rec, const char *name)
{
register int i;
int fld;
DtDtsMMField *fld_ptr;
DtDtsMMField *fld_ptr_list;
/*
* Field names have been quarked so quark 'name' and
* do a linear search for the quark'ed field name.
*/
DtShmBoson tmp = _DtDtsMMStringToBoson (name);
fld_ptr_list = _DtDtsMMGetPtr(rec->fieldList);
for (i = 0; i < rec->fieldCount; i++)
{
fld_ptr = &fld_ptr_list[i];
if (fld_ptr->fieldName == tmp)
{
return (fld_ptr);
}
}
return(NULL);
}
const char *
_DtDtsMMGetFieldByName(DtDtsMMRecord *rec, const char *name)
{
DtDtsMMField *result;
result = _DtDtsMMGetField(rec, name);
if(result)
{
return(_DtDtsMMBosonToString(result->fieldValue));
}
else
{
return(NULL);
}
}
DtDtsMMRecord *
_DtDtsMMGetRecordByName(DtDtsMMDatabase *db, const char *name)
{
DtDtsMMRecord srch;
DtDtsMMRecord *result;
DtDtsMMRecord *s = &srch;
register int i;
DtShmBoson name_quark = _DtDtsMMStringToBoson(name);
DtDtsMMRecord *rec_ptr;
DtDtsMMRecord *rec_ptr_list;
/*
* If the fields are not sorted in alphanumeric order
* by name a binary search will fail. So do the slow but
* sure linear search.
*/
rec_ptr_list = _DtDtsMMGetPtr(db->recordList);
for (i = 0; i < db->recordCount; i++)
{
rec_ptr = &rec_ptr_list[i];
if (rec_ptr->recordName == name_quark)
{
return (rec_ptr);
}
}
return NULL;
}
int
_DtDtsMMPathHash(DtDirPaths *dirs)
{
int pathhash = 0;
DIR *dirp;
struct dirent *dp = NULL;
int suffixLen;
int nameLen;
char *file_suffix;
char *next_path;
char *suffix = ".dt";
int i;
char *cur_dir = getcwd(0,MAXPATHLEN);
struct stat buf;
_Xreaddirparams dirEntryBuf;
struct dirent *result;
for(i = 0; dirs->paths[i] ; i++)
{
if(chdir(dirs->paths[i]) == -1)
{
continue;
}
dirp = opendir (".");
while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL)
{
if ((int)strlen (result->d_name) >= (int)strlen(suffix))
{
suffixLen = DtCharCount(suffix);
nameLen = DtCharCount(result->d_name);
file_suffix = (char *)_DtGetNthChar(result->d_name,
nameLen - suffixLen);
stat(result->d_name, &buf);
if (file_suffix &&
(strcmp(file_suffix, suffix) == 0) &&
(buf.st_mode&S_IFREG))
{
char *c = dirs->paths[i];
while(*c)
{
pathhash += (int)*c;
c++;
}
break;
}
}
}
closedir(dirp);
}
chdir(cur_dir);
free(cur_dir);
return(pathhash);
}
char *
_DtDtsMMCacheName(int override)
{
char *dsp = getenv("DISPLAY");
char *results = 0;
char *c;
if(override && dsp)
{
results = malloc(strlen(_DTDTSMMTEMPDIR)+
strlen(_DTDTSMMTEMPFILE)+
strlen(dsp)+3);
sprintf(results, "%s/%s%s\0",
_DTDTSMMTEMPDIR,
_DTDTSMMTEMPFILE,
dsp);
c = strchr(results, ':');
c = strchr(c, '.');
if(c)
{
*c = '\0';
}
}
else
{
/* tempnam(3) is affected by the TMPDIR environment variable. */
/* This creates problems for rename() if "tmpfile" and "cacheFile" */
/* are on different file systems. Use tmpnam(3) to create the */
/* unique file name instead. */
char tmpnam_buf[L_tmpnam + 1];
results = (char *)malloc(sizeof(_DTDTSMMTEMPDIR) +
sizeof(_DTDTSMMTEMPFILE) +
L_tmpnam + 3);
tmpnam(tmpnam_buf);
sprintf(results, "%s/%s%s", _DTDTSMMTEMPDIR, _DTDTSMMTEMPFILE,
basename(tmpnam_buf));
}
return(results);
}
int
_DtDtsMMapDB(const char *CacheFile)
{
struct stat buf;
int success = FALSE;
_DtSvcProcessLock();
if (mmaped_fd > 0)
{
/* Already have a file memory-mapped. Unload it. */
_DtDtsMMUnLoad();
}
mmaped_fd = open(CacheFile, O_RDONLY, 0400);
if(mmaped_fd != -1)
{
if(fstat(mmaped_fd, &buf) == 0 && buf.st_uid == getuid())
{
mmaped_db = (char *)mmap(NULL,
buf.st_size,
PROT_READ,
#if defined(sun) || defined(USL)
/* MAP_NORESERVE is only supported
on sun and novell platforms */
MAP_SHARED|MAP_NORESERVE,
#else
MAP_SHARED,
#endif
mmaped_fd,
NULL);
if(mmaped_db != (void *) -1)
{
success = TRUE;
mmaped_size = buf.st_size;
head = (DtDtsMMHeader *)mmaped_db;
db_list = (DtDtsMMDatabase *)_DtDtsMMGetPtr(head->db_offset);
}
else
{
_DtSimpleError(
DtProgName, DtError, NULL,
(char*) CacheFile, NULL);
}
}
}
if(!success)
{
mmaped_db = 0;
}
_DtSvcProcessUnlock();
return(success);
}
static int
MMValidateDb(DtDirPaths *dirs, char *suffix)
{
DIR *dirp;
struct dirent *direntp;
struct stat buf;
struct stat new_buf;
int size = sizeof(buf.st_mtime);
DtShmBoson *boson_list = 0;
time_t *mtime_list;
int count = 0;
int i;
const char *file;
int pathhash = _DtDtsMMPathHash(dirs);
_DtSvcProcessLock();
if(head->pathhash != pathhash)
{
_DtSvcProcessUnlock();
return(0);
}
count = head->files_count;
mtime_list = _DtDtsMMGetPtr(head->mtimes_offset);
boson_list = _DtDtsMMGetPtr(head->files_offset);
for(i = 0; i < count; i++)
{
file = _DtDtsMMBosonToString(boson_list[i]);
stat(file, &buf);
if(mtime_list[i] != buf.st_mtime)
{
_DtSvcProcessUnlock();
return(0);
}
}
_DtSvcProcessUnlock();
return(1);
}
char *
_DtDtsMMExpandValue(const char *value)
{
char *newval;
if(!value)
{
return NULL;
}
newval = (char *)malloc(1024);
strcpy(newval, value);
_DtDbFillVariables(&newval);
return(newval);
}
void
_DtDtsMMSafeFree(char *value)
{
if(value && !_DtDtsMMIsMemory(value))
{
free(value);
}
}
int
_DtDtsMMIsMemory(const char *value)
{
_DtSvcProcessLock();
if((caddr_t)value < mmaped_db || (caddr_t)value > mmaped_db+mmaped_size)
{
_DtSvcProcessUnlock();
return(0);
}
else
{
_DtSvcProcessUnlock();
return(1);
}
}
int
_DtDtsMMUnLoad()
{
int error = 0;
_DtSvcProcessLock();
_DtDtsClear();
if(mmaped_db == 0)
{
_DtSvcProcessUnlock();
return(error);
}
if(munmap(mmaped_db, mmaped_size) == -1)
{
_DtSimpleError(DtProgName, DtError, NULL,
"munmap of dts_cache file", NULL);
error = -1;
}
if(close(mmaped_fd) == -1)
{
_DtSimpleError(DtProgName, DtError, NULL,
"close of dts_cache file", NULL);
}
db_list = 0;
mmaped_db = 0;
mmaped_size = 0;
mmaped_fd = 0;
head = 0;
_DtSvcProcessUnlock();
return(error);
}
#include "Dt/UserMsg.h"
static int
_debug_print_name(char *name, char *label)
{
#ifdef DEBUG
static char *db = (char *)-1;
_DtSvcProcessLock();
if(db == (char *)-1)
{
db = getenv("MMAP_DEBUG");
}
_DtSvcProcessUnlock();
if(db)
_DtSimpleError(db,
DtInformation,
NULL,
"%s - db name = %s\n", label,
name);
#endif /* DEBUG */
return(0);
}

View File

@@ -0,0 +1,152 @@
/* $XConsortium: DtsMM.h /main/8 1996/08/28 14:27:26 rswiston $ */
/*
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#ifndef DT_DTS_MM_H
#define DT_DTS_MM_H
#include <stdio.h>
#include <Dt/DtShmDb.h>
#include <X11/Intrinsic.h>
#include "Dt/DbReader.h"
#define DTDTSDB_TMPDATABASENAME "%s/.dt/.tmp_dt_db_cache.%s\0"
#define DTDTSDB_DATABASENAME "%s/.dt/.dt_db_cache.%s\0"
#define _DTDTSMMTEMPFILE "dtdbcache_"
/*
* NOTE: _DTDTSMMTEMPDIR affects the location of the dtdbcache
* file, and therefore affects the Xsession.src, Xreset.src, and
* Xstartup.src scripts in dtlogin/config.
*/
#ifdef __osf__
# define _DTDTSMMTEMPDIR "/var/tmp"
#else
# define _DTDTSMMTEMPDIR "/tmp"
#endif
typedef int DtDtsMMSeqNo; /* the order it occures in db */
typedef int DtDtsMMFieldCount; /* number of fields in record */
typedef int DtDtsMMRecordCount; /* number of records in field */
typedef int DtDtsMMDataBaseCount; /* how many databases */
typedef int DtDtsMMFieldStart; /* index in table where field list starts */
typedef int DtDtsMMRecordStart; /* index in table where record list starts */
typedef int DtDtsMMDataBaseStart; /* index in table where database list starts */
typedef int DtDtsMMIndexOffset;
typedef int DtDtsMMNameIndex;
typedef int DtDtsMMPathHash;
typedef struct
{
DtDtsMMPathHash pathhash; /* hash of dir. we visit */
DtDtsMMDataBaseCount num_db; /* number of databases */
DtDtsMMDataBaseStart db_offset; /* index to databases */
DtDtsMMNameIndex name_list_offset; /* index to name list */
DtDtsMMNameIndex no_name_offset; /* index to nonunique names */
DtDtsMMNameIndex buffer_start_index; /* index to list of buffers */
DtDtsMMIndexOffset str_tbl_offset; /* index to table of strings */
DtDtsMMIndexOffset files_count; /* number of loaded files */
DtDtsMMIndexOffset files_offset; /* index to list of loaded files */
DtDtsMMIndexOffset mtimes_offset; /* index to modified times of files */
} DtDtsMMHeader;
/* one set of attribute/pair */
typedef struct
{
DtShmBoson fieldName; /* name of attribute */
DtShmBoson fieldValue; /* value of attribute */
} DtDtsMMField;
/* typedefs for casting comparison functions if needed */
typedef int (*_DtDtsMMFieldCompare)(DtDtsMMField *fld1, DtDtsMMField *fld2);
/* entry of a list of attribute/pairs */
typedef struct
{
DtShmBoson recordName; /* name of this entry */
DtShmBoson pathId; /* file entry is located in */
DtDtsMMSeqNo seq; /* sequence this got loaded */
DtDtsMMFieldCount fieldCount; /* number of fields in record */
DtDtsMMFieldStart fieldList; /* index to field table */
} DtDtsMMRecord;
/* typedefs for casting record comparison functions if needed */
typedef int (*_DtDtsMMRecordCompare)(DtDtsMMRecord *rec1, DtDtsMMRecord *rec2);
/* a "database" of a collection of entrys (i.e. OBJECT-TYPE, ACTION, FILE-TYPE
This is a private Structure to the DtDtsMM component.
*/
typedef struct
{
DtShmBoson databaseName; /* name of database */
DtDtsMMIndexOffset nameIndex; /* index for DataCriteria quick find */
DtDtsMMRecordCount recordCount; /* number of records */
DtDtsMMRecordStart recordList; /* index to records table */
} DtDtsMMDatabase;
/* Db Internal pointers */
int * _DtDtsMMGetDCNameIndex(int *size);
int * _DtDtsMMGetBufferIndex(int *size);
int * _DtDtsMMGetNoNameIndex(int *size);
void * _DtDtsMMGetPtr(int index);
DtShmInttab _DtDtsMMGetFileList(void);
int _DtDtsMMGetPtrSize(int index);
int _DtDtsMMInit(int);
void _DtDtsMMPrint(FILE *org_fd);
int _DtDtsMMCreateDb(DtDirPaths *dirs, const char *CacheFile, int override);
int _DtDtsMMCreateFile(DtDirPaths *dirs, const char *CacheFile);
char * _DtDtsMMCacheName(int);
int _DtDtsMMapDB(const char *CacheFile);
const char * _DtDtsMMBosonToString(DtShmBoson boson);
DtShmBoson _DtDtsMMStringToBoson(const char *string);
extern int use_in_memory_db;
/* returns the handle for the database where name is the Database name */
extern DtDtsMMDatabase *_DtDtsMMGet(const char *name);
extern char **_DtDtsMMListDb(void);
/* Name Comparison functions:
* These routines can be passed in to the corresponding sort function to
* sort by name.
*
*/
extern int _DtDtsMMCompareRecordNames(DtDtsMMRecord *entry1, DtDtsMMRecord *entry2);
extern int _DtDtsMMCompareFieldNames(DtDtsMMField *entry1, DtDtsMMField *entry2);
/* retrieves the Record that matches the specified entry from the record */
extern DtDtsMMField *_DtDtsMMGetField(DtDtsMMRecord *record,
const char *value);
extern const char *_DtDtsMMGetFieldByName(DtDtsMMRecord *rec, const char *name);
/* retrieves the entry of the specified entry from the specified database */
extern DtDtsMMRecord *_DtDtsMMGetRecord(DtDtsMMDatabase *database,
DtDtsMMRecord *value);
extern DtDtsMMRecord *_DtDtsMMGetRecordByName(DtDtsMMDatabase *database,
const char *value);
/* Get By Name functions:
* retrieves the entry of the specified name from the specified database
* ** IF ** the _DtDtsMM*Sort routine has been called with the corresponding
* _DtDtsMMCompare*Name comparison function. Otherwise use the standard
* _DtDtsMMGet* functions.
*/
char * _DtDtsMMExpandValue(const char *value);
void _DtDtsMMSafeFree(char *value);
int _DtDtsMMIsMemory(const char *value);
extern DtShmBoson _DtDtsMMNameStringToBoson(const char *string);
#endif /* DT_DTS_MM_H */

View File

@@ -0,0 +1,451 @@
/*
* (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. *
*/
/*
*+SNOTICE
*
* $XConsortium: DtsSort.c /main/6 1996/11/21 19:56:08 drk $
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement bertween
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
* Sun's specific written approval. This documment and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*+ENOTICE
*/
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
#define X_INCLUDE_STRING_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <Dt/DbReader.h>
#include "Dt/DtsDb.h"
#include "Dt/Dts.h"
extern char *strdup(const char *);
static char *
get_value(DtDtsDbRecord *ce_entry, char *value)
{
int i=0;
XrmQuark tmp = XrmStringToQuark (value);
for(i = 0; i < ce_entry->fieldCount; i++)
{
if(ce_entry->fieldList[i]->fieldName == tmp)
{
return(ce_entry->fieldList[i]->fieldValue);
}
}
return(NULL);
}
void
parts_of_pattern(char *c, int *spec, int *count, int *front)
{
int nested = 0;
int found = 0;
int len;
(*count) = 0;
(*spec) = 0;
(*front) = 0;
while(*c)
{
if((len = mblen(c, MB_CUR_MAX)) > 1) {
(*count) += len;
if(!found)
(*front) += len;
c += len;
continue;
}
switch(*c)
{
case '*':
if(!nested)
{
(*spec) += 100;
found = 1;
}
break;
case '?':
if(!nested)
{
(*spec) += 1;
found = 1;
}
break;
case '[':
(*spec) += 10;
nested ++;
found = 1;
break;
case ']':
if(nested)
{
nested --;
}
break;
case '\\':
if(!nested)
{
if((len = mblen(c + 1, MB_CUR_MAX)) > 1) {
(*count) += len + 1;
c += len;
}
else {
(*count) += 2;
c++;
}
}
break;
default:
(*count)++;
if(!found)
{
(*front)++;
}
}
c++;
}
}
int
check_pattern(char *value1, char *value2)
{
int spec1 = 0,count1 = 0, front1 = 0;
int spec2 = 0,count2 = 0, front2 = 0;
if(value1 && value2)
{
parts_of_pattern(value1, &spec1, &count1, &front1);
parts_of_pattern(value2, &spec2, &count2, &front2);
}
else if(!value1 && !value2)
{
return(0);
}
else if(value1)
{
return(-1);
}
else
{
return(1);
}
if(front1 != front2)
{
return(front2 - front1);
}
if(spec1 != spec2)
{
return(spec1 - spec2);
}
if(count1 != count2)
{
return(count2-count1);
}
return (0);
}
int
mode_count(char *c)
{
int count = 0;
while(c && *c)
{
if(strchr("fcbdlrwx", *c))
{
count++;
}
c++;
}
return(count);
}
#ifdef DEBUG
static int
bool(int i)
{
if(i > 0) return(1);
if(i < 0) return(-1);
else return(0);
}
#endif
check_content(char *val1, char *val2)
{
char *v1 = strdup(val1);
char *v2 = strdup(val2);
char *loc1;
char *loc2;
char *type1;
char *type2;
char *cnt1;
char *cnt2;
int ret = 0;
_Xstrtokparams strtok_buf;
loc1 = _XStrtok(v1, "\t \n", strtok_buf);
type1 = _XStrtok(NULL, "\t \n", strtok_buf);
cnt1 = &type1[strlen(type1)+1];
while(isspace((u_char)*cnt1))cnt1++;
loc2 = _XStrtok(v2, "\t \n", strtok_buf);
type2 = _XStrtok(NULL, "\t \n", strtok_buf);
cnt2 = &type2[strlen(type2)+1];
while(isspace((u_char)*cnt2))cnt2++;
ret = strcmp(type1, type2);
if(loc1 && loc2 && ret == 0)
{
int l1 = atoi(loc1);
int l2 = atoi(loc2);
int sl1 = strlen(cnt1);
int sl2 = strlen(cnt2);
char sym;
if (sl1 > sl2) ret = -1;
else if (sl1 < sl2) ret = 1;
else if (l1 > l2 ) ret = 1;
else if (l1 < l2 ) ret = -1;
else ret = strcmp(cnt1,cnt2);
#ifdef DEBUG
switch(bool(ret))
{
case 0:
sym = '=';
break;
case -1:
sym = '>';
break;
case 1:
sym = '<';
}
printf("cc (%d,%d) for \"%s\" %c \"%s\"\n", l1, l2, cnt1, sym, cnt2);
#endif
}
free(v1);
free(v2);
return(ret);
}
static int
sfe(DtDtsDbRecord * item1, DtDtsDbRecord * item2)
{
int test1 = 0;
int test2 = 0;
int loc1;
int loc2;
char *value1, *value2;
DtDtsDbRecord *rec;
DtDtsDbField *fld;
int val;
test1 |= get_value(item1, DtDTS_CONTENT) ? 2 : 0;
test2 |= get_value(item2, DtDTS_CONTENT) ? 2 : 0;
value1 = get_value(item1, DtDTS_NAME_PATTERN);
if (value1)
{
if ((strlen(value1) == 1) && (*value1 == '*'))
{
test1 |= 0;
}
else
{
test1 |= 1;
}
}
value2 = get_value(item2, DtDTS_NAME_PATTERN);
if (value2)
{
if ((strlen(value2) == 1) && (*value2 == '*'))
{
test2 |= 0;
}
else
{
test2 |= 1;
}
}
if (!(test1 & 1))
{
test1 |= get_value(item1, DtDTS_PATH_PATTERN) ? 1 : 0;
}
if (!(test2 & 1))
{
test2 |= get_value(item2, DtDTS_PATH_PATTERN) ? 1 : 0;
}
switch (test1)
{
case 0:
loc1 = 4;
break;
case 1:
loc1 = 2;
break;
case 2:
loc1 = 3;
break;
case 3:
loc1 = 1;
break;
}
switch (test2)
{
case 0:
loc2 = 4;
break;
case 1:
loc2 = 2;
break;
case 2:
loc2 = 3;
break;
case 3:
loc2 = 1;
break;
}
if (loc1 - loc2)
{
return (loc1 - loc2);
}
if (loc1 == 2) /* loc1 == loc2 */
{
val = check_pattern(get_value(item1, DtDTS_PATH_PATTERN),
get_value(item2, DtDTS_PATH_PATTERN));
if(val)
{
return(val);
}
val = check_pattern(get_value(item1, DtDTS_NAME_PATTERN),
get_value(item2, DtDTS_NAME_PATTERN));
if(val)
{
return(val);
}
}
if( loc1 == 3)
{
val = check_content(get_value(item1, DtDTS_CONTENT),
get_value(item2, DtDTS_CONTENT));
if(val)
{
return(val);
}
}
/*
* neither pattern nor content, only needs to compare the
* number of fields. If they are equal then which has shorter
* record name will be more specific
*/
if (item2->fieldCount - item1->fieldCount)
{
return (item2->fieldCount - item1->fieldCount);
}
val = mode_count(get_value(item2, DtDTS_MODE)) -
mode_count(get_value(item1, DtDTS_MODE));
if(val)
{
return(val);
}
val = strlen(XrmQuarkToString(item1->recordName)) -
strlen(XrmQuarkToString(item2->recordName));
if(val)
{
return(val);
}
else
{
return(item1->recordName - item2->recordName);
}
}
int
cde_dc_compare(DtDtsDbRecord ** a, DtDtsDbRecord ** b)
{
DtDtsDbRecord **x = (DtDtsDbRecord **) a;
DtDtsDbRecord **y = (DtDtsDbRecord **) b;
int results;
char c;
results = sfe(*x, *y);
return(results);
}
static int
cde_ft_field_value(XrmQuark name_quark)
{
if (name_quark == XrmStringToQuark(DtDTS_PATH_PATTERN))
return (1);
else if (name_quark == XrmStringToQuark(DtDTS_NAME_PATTERN))
return (2);
else if (name_quark == XrmStringToQuark(DtDTS_MODE))
return (3);
else if (name_quark == XrmStringToQuark(DtDTS_LINK_PATH))
return (4);
else if (name_quark == XrmStringToQuark(DtDTS_LINK_NAME))
return (5);
else if (name_quark == XrmStringToQuark(DtDTS_CONTENT))
return (6);
else if (name_quark == XrmStringToQuark(DtDTS_DATA_ATTRIBUTES_NAME))
return (7);
else if (name_quark == XrmStringToQuark(DtDTS_DA_IS_SYNTHETIC))
return (8);
else
return (9);
}
int
cde_dc_field_compare(DtDtsDbField ** a, DtDtsDbField ** b)
{
return (cde_ft_field_value((*a)->fieldName) -
cde_ft_field_value((*b)->fieldName));
}
cde_da_compare(DtDtsDbRecord ** a, DtDtsDbRecord ** b)
{
int results = ((*a)->recordName) - ((*b)->recordName);
if (!results)
{
results = (*a)->seq - (*b)->seq;
}
return (results);
}

View File

@@ -0,0 +1,190 @@
/* $XConsortium: GetMwmW.c /main/5 1996/05/20 16:07:08 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1990,1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
/************************************<+>*************************************
****************************************************************************
**
** File: GetMwmW.c
**
** Project: DT Workspace Manager
**
** Description: Gets the mwm window id.
**
****************************************************************************
************************************<+>*************************************/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <Xm/MwmUtil.h>
#include <Xm/Xm.h>
#include <Xm/AtomMgr.h>
/******** Public Function Declarations ********/
extern int _DtGetMwmWindow(
Display *display,
Window root,
Window *pMwmWindow) ;
/******** End Public Function Declarations ********/
/******** Static Function Declarations ********/
static int _GetMwmWindow(
Display *display,
Window root,
Window *pMwmWindow,
Atom property) ;
/******** End Static Function Declarations ********/
/*************************************<->*************************************
*
* int _GetMwmWindow (display, root, pMwmWindow, property)
*
*
* Description:
* -----------
* Get the Motif Window manager window
*
*
* Inputs:
* ------
* display - display
* root - root window of screen
* pMwmWindow - pointer to a window (to be returned)
* property - the property atom
*
* Outputs:
* --------
* *pMwmWindow - mwm window id, if successful
* Return - status from XGetWindowProperty
*
* Comments:
* --------
* This can fail if mwm is not managing the screen for the root window
* passed in.
*
*************************************<->***********************************/
static int
_GetMwmWindow(
Display *display,
Window root,
Window *pMwmWindow,
Atom property )
{
Atom actualType;
int actualFormat;
unsigned long nitems;
unsigned long leftover;
PropMotifWmInfo *pWmInfo = NULL;
int rcode;
Window wroot, wparent, *pchildren;
unsigned int nchildren;
*pMwmWindow = NULL;
if ((rcode=XGetWindowProperty(display,root,
property,0L, PROP_MWM_INFO_ELEMENTS,
False,property,
&actualType,&actualFormat,
&nitems,&leftover,(unsigned char **)&pWmInfo))==Success)
{
if (actualType != property)
{
/* wrong type, force failure */
rcode = BadValue;
}
else
{
rcode = BadWindow; /* assume the worst */
/*
* The mwm window should be a direct child of root
*/
if (XQueryTree (display, root, &wroot, &wparent,
&pchildren, &nchildren))
{
int i;
for (i = 0; (i < nchildren) && (rcode != Success); i++)
{
if (pchildren[i] == pWmInfo->wmWindow)
{
rcode = Success;
}
}
}
if (rcode == Success);
{
*pMwmWindow = pWmInfo->wmWindow;
}
if (pchildren)
{
XFree ((char *)pchildren);
}
}
if (pWmInfo)
{
XFree ((char *)pWmInfo);
}
}
return(rcode);
} /* END OF FUNCTION _GetMwmWindow */
/*************************************<->*************************************
*
* int _DtGetMwmWindow (display, root, pMwmWindow)
*
*
* Description:
* -----------
* Get the Motif Window manager window
*
*
* Inputs:
* ------
* display - display
* root - root window of screen
* pMwmWindow - pointer to a window (to be returned)
*
* Outputs:
* --------
* *pMwmWindow - mwm window id, if successful
* Return - status from XGetWindowProperty
*
* Comments:
* --------
* This can fail if mwm is not managing the screen for the root window
* passed in.
*
*************************************<->***********************************/
int
_DtGetMwmWindow(
Display *display,
Window root,
Window *pMwmWindow )
{
Atom xa_MWM_INFO;
xa_MWM_INFO = XmInternAtom (display, _XA_MWM_INFO, False);
return (_GetMwmWindow (display, root, pMwmWindow, xa_MWM_INFO));
}

View File

@@ -0,0 +1,167 @@
/* $XConsortium: GetVWmHint.c /main/5 1996/05/20 16:07:19 drk $
*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1991,1993,1994,1996 Hewlett-Packard Company.
* (c) Copyright 1993,1994,1996 International Business Machines Corp.
* (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
* (c) Copyright 1993,1994,1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
/************************************<+>*************************************
****************************************************************************
**
** File: GetVwmHint.c
**
** Project: DT Workspace Manager
**
** Description: Get Dt Window manager hints
**
****************************************************************************
************************************<+>*************************************/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <Dt/Wsm.h>
#include <Dt/WsmP.h>
#include <Xm/Xm.h>
#include <Xm/AtomMgr.h>
/*************************************<->*************************************
*
* int _DtWsmGetDtWmHints (display, window, ppDtWmHints)
*
*
* Description:
* -----------
* Get the contents of the _DT_WM_HINTS property on a window
*
*
* Inputs:
* ------
* display - display
* window - window to get hints from
* ppDtWmHints- pointer to a pointer to return
*
* Outputs:
* --------
* *ppDtWmHints-points to the DtWmHints structure retrieved from
* the window (NOTE: This should be freed using XFree)
*
* Comments:
* ---------
*
*************************************<->***********************************/
int
_DtWsmGetDtWmHints(
Display *display,
Window window,
DtWmHints **ppDtWmHints)
{
Atom actualType;
int actualFormat;
unsigned long leftover, items, length;
int rcode;
Atom property;
#ifdef HP_VUE
unsigned long oldlength;
#endif /* HP_VUE */
property = XmInternAtom(display, _XA_DT_WM_HINTS, False);
length = sizeof (DtWmHints) / sizeof (long);
*ppDtWmHints = NULL;
if ((rcode=XGetWindowProperty(
display,
window,
property,
0L, /* offset */
length,
False, /* delete */
property, /* req_type */
&actualType,
&actualFormat,
&items, /* items returned */
&leftover,
(unsigned char **)ppDtWmHints))==Success)
{
if ((actualType != property) || (items < length))
{
/* wrong type, force failure */
rcode = BadValue;
if (actualType != None)
{
XFree ((char *)*ppDtWmHints);
}
*ppDtWmHints = NULL;
}
}
#ifdef HP_VUE
else {
/*
* Didn't get the Dt hints, try to get the Vue hints.
* Not that the Vue hints had the same structure, just
* under a different property name.
*/
property = XmInternAtom(display, _XA_VUE_WM_HINTS, False);
/*
* Property previously existed without attachWindow.
*/
oldlength = length - (sizeof(Window)/sizeof(long));
*ppDtWmHints = NULL;
if ((rcode=XGetWindowProperty(
display,
window,
property,
0L, /* offset */
length,
False, /* delete */
property, /* req_type */
&actualType,
&actualFormat,
&items, /* items returned */
&leftover,
(unsigned char **)ppDtWmHints))==Success)
{
if ((actualType != property) ||
(items < oldlength))
{
/* wrong type, force failure */
rcode = BadValue;
if (actualType != None)
{
XFree ((char *)*ppDtWmHints);
}
*ppDtWmHints = NULL;
}
if (*ppDtWmHints && (items < length))
{
DtWmHints *pvh;
/* assume old property, return full sized
property with empty values */
pvh = (DtWmHints *) malloc (length * sizeof (long));
pvh->flags = (*ppDtWmHints)->flags;
pvh->functions = (*ppDtWmHints)->functions;
pvh->behaviors = (*ppDtWmHints)->behaviors;
pvh->attachWindow = NULL;
XFree ((char *) *ppDtWmHints);
*ppDtWmHints = pvh;
}
}
}
#endif /* HP_VUE */
return(rcode);
} /* END OF FUNCTION _DtWsmGetDtWmHints */

View File

@@ -0,0 +1,167 @@
XCOMM $XConsortium: Imakefile /main/6 1996/08/20 14:48:27 drk $
#define DoNormalLib NormalLibDtSvc
#define DoSharedLib SharedLibDtSvc
#define DoDebugLib DebugLibDtSvc
#define DoProfileLib ProfileLibDtSvc
#define LibName DtSvc
#define SoRev SODTSVCREV
#define IncSubdir Dt
#define LibCreate NO
#define LargePICTable YES
#include <Threads.tmpl>
#ifndef DtSvcDefines
# define DtSvcDefines -DXK_MISCELLANY -DMULTIBYTE
#endif
DEFINES = DtSvcDefines \
-DCDE_INSTALLATION_TOP=\"$(CDE_INSTALLATION_TOP)\" \
-DCDE_CONFIGURATION_TOP=\"$(CDE_CONFIGURATION_TOP)\"
INCLUDES = -I. -I../include
HEADERS = \
Action.h \
ActionDb.h \
ActionDbP.h \
ActionP.h \
ActionFind.h \
ActionUtilP.h \
CmdInv.h \
CmdInvP.h \
DbReader.h \
DbUtil.h \
Dnd.h \
DndP.h \
DndIconI.h \
Dt.h \
Dts.h \
DtsDb.h \
DtsMM.h \
DtHash.h \
DtShmDb.h \
Qualify.h \
Saver.h \
SaverP.h \
Session.h \
SessionM.h \
SessionP.h \
Wsm.h \
WsmM.h \
WsmP.h
SRCS = \
Action.c \
ActionTt.c \
ActionDb.c \
ActionFind.c \
ActionUtil.c \
DbReader.c \
DbUtil.c \
CmdSpc.c \
CmdMain.c \
CmdProcess.c \
CmdUtilityP.c \
Dnd.c \
DndDrag.c \
DndDrop.c \
DndIcon.c \
DndBuff.c \
DndFile.c \
DndText.c \
Dt.c \
Dts.c \
DtsDb.c \
DtsSort.c \
DbLoad.c \
DtsInit.c \
DtHash.c \
intarray.c \
inttab.c \
strtab.c \
DtsMM.c \
MMDb.c \
GetVWmHint.c \
GetMwmW.c \
Qualify.c \
Saver.c \
SetVWmHint.c \
SmComm.c \
SmUtil.c \
WmAddDelWs.c \
WmBackWin.c \
WmChBackD.c \
WmGWsInfo.c \
WmGWsList.c \
WmMarquee.c \
WmRestart.c \
WmRmWsFcn.c \
WmSetTitle.c \
WmWsCallB.c \
WmSetWs.c \
WmWsHints.c \
WmWsOccupy.c
/* WARNING!!!!
* Any .o's added to this list need to be added to DTUTIL1_OBJS1
* and SHARED_DTUTIL1_OBJS1 in the DtSvc Imakefile.
*/
OBJS = \
Action.o \
ActionTt.o \
ActionDb.o \
ActionFind.o \
ActionUtil.o \
DbReader.o \
DbUtil.o \
CmdSpc.o \
CmdMain.o \
CmdProcess.o \
CmdUtilityP.o \
Dnd.o \
DndDrag.o \
DndDrop.o \
DndIcon.o \
DndBuff.o \
DndFile.o \
DndText.o \
Dt.o \
Dts.o \
DtsDb.o \
DtsSort.o \
DbLoad.o \
DtsInit.o \
DtHash.o \
intarray.o \
inttab.o \
strtab.o \
DtsMM.o \
MMDb.o \
GetVWmHint.o \
GetMwmW.o \
Qualify.o \
Saver.o \
SetVWmHint.o \
SmComm.o \
SmUtil.o \
WmAddDelWs.o \
WmBackWin.o \
WmChBackD.o \
WmGWsInfo.o \
WmGWsList.o \
WmMarquee.o \
WmRestart.o \
WmRmWsFcn.o\
WmSetTitle.o \
WmWsCallB.o \
WmSetWs.o \
WmWsHints.o \
WmWsOccupy.o
#include <Library.tmpl>
SubdirLibraryRule($(OBJS))
DependTarget()

View File

@@ -0,0 +1,717 @@
/* $TOG: MMDb.c /main/19 1998/10/23 13:48:52 mgreess $ */
/*
* +SNOTICE
*
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
*
* +ENOTICE
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <malloc.h>
#include <sys/utsname.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef NLS16
#include <limits.h>
#endif
#include <sys/stat.h>
#include <sys/param.h> /* MAXPATHLEN, MAXHOSTNAMELEN */
#define X_INCLUDE_DIRENT_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <Dt/DbReader.h>
#include <Dt/DtsDb.h>
#include <Dt/DtsMM.h>
#include <Dt/DtShmDb.h>
#include <Dt/Dts.h>
#include <Dt/ActionP.h>
#include <Dt/ActionDbP.h>
#include <Dt/ActionUtilP.h>
#include <Dt/DtNlUtils.h>
#include <Dt/UserMsg.h>
#include "myassertP.h"
#include "DtSvcLock.h"
static void build_file_list(DtShmProtoIntList, DtDirPaths *,
DtDtsMMHeader *, const char *);
extern int cde_dc_field_compare(DtDtsDbField **, DtDtsDbField **);
extern int cde_dc_compare(DtDtsDbRecord **, DtDtsDbRecord **);
static void _DtMMSortDataTypes(DtShmProtoStrtab str_handle);
static void _DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr);
static int write_db(DtDtsMMHeader *header, void *index, int size,
const char *CacheFile);
static int build_new_db(DtShmProtoStrtab, DtShmProtoIntList, int, DtDtsDbDatabase **);
static int build_name_list(DtDtsDbDatabase *, DtShmProtoIntList, DtDtsMMHeader *);
static DtShmProtoStrtab shm_handle = 0;
static DtShmProtoIntList int_handle = 0;
#define QtB(a) _DtShmProtoAddStrtab(shm_handle, XrmQuarkToString(a), &isnew)
int
_MMWriteDb(DtDirPaths *dirs, int num_db, DtDtsDbDatabase **db_list,
const char *CacheFile)
{
DtDtsMMHeader header;
char *suffix = ".dt";
int tbl_size;
void *tbl_data;
DtDtsDbDatabase *db;
int returnCode;
_DtSvcProcessLock();
memset(&header, '\0', sizeof(header));
int_handle = _DtShmProtoInitIntLst(50000);
shm_handle = _DtShmProtoInitStrtab(10000);
build_file_list(int_handle, dirs, &header, suffix);
_DtMMSortDataTypes(shm_handle);
db = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DA_NAME);
_DtMMAddActionsToDataAttribute(db);
header.pathhash = _DtDtsMMPathHash(dirs);
header.num_db = num_db;
header.db_offset = build_new_db(shm_handle, int_handle, num_db,
db_list);
db = (DtDtsDbDatabase *) _DtDtsDbGet("DATA_CRITERIA");
build_name_list(db, int_handle, &header);
tbl_size = _DtShmProtoSizeStrtab(shm_handle);
tbl_data = (void *) _DtShmProtoAddIntLst(int_handle,
tbl_size/sizeof(int), &header.str_tbl_offset);
_DtShmProtoCopyStrtab(shm_handle, tbl_data);
tbl_size = _DtShmProtoSizeIntLst(int_handle);
tbl_data = (void *)malloc(tbl_size);
memset(tbl_data, '\0', tbl_size);
tbl_data = (void *)_DtShmProtoCopyIntLst(int_handle, tbl_data);
returnCode = write_db(&header, tbl_data, tbl_size, CacheFile);
_DtShmProtoDestroyStrtab(shm_handle);
_DtShmProtoDestroyIntLst(int_handle);
_DtSvcProcessUnlock();
free(tbl_data);
return returnCode;
}
static void
build_file_list(DtShmProtoIntList int_handle, DtDirPaths *dirs,
DtDtsMMHeader *header, const char *suffix)
{
DIR *dirp;
struct dirent *dp = NULL;
struct stat buf;
char cur_path[MAXPATHLEN+1];
void *data;
int size = sizeof(buf.st_mtime);
int i;
int isnew;
DtShmBoson *boson_list = 0;
time_t *mtime_list = 0;
int count = 0;
_Xreaddirparams dirEntryBuf;
struct dirent *result;
/* Theses here to make sure it gets into the string tables
because actions uses it in its "types" field. */
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_UNKNOWN, &isnew);
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_RECURSIVE_LINK, &isnew);
_DtShmProtoAddStrtab(shm_handle, DtDTS_DT_BROKEN_LINK, &isnew);
getcwd(cur_path, sizeof(cur_path));
for(i = 0; dirs->paths[i]; i++)
{
chdir(dirs->paths[i]);
stat(".", &buf);
count++;
boson_list = (int *)realloc(boson_list, count*sizeof(int));
mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
mtime_list[count-1] = buf.st_mtime;
boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle, dirs->paths[i], &isnew);
dirp = opendir(".");
while ((result = _XReaddir(dirp, dirEntryBuf)) != NULL)
{
char *c = strrchr(result->d_name, suffix[0]);
if(c && strcmp(c, suffix) == 0)
{
char *pathname = malloc(MAXPATHLEN+1);
sprintf(pathname, "%s/%s", dirs->paths[i], result->d_name);
stat(result->d_name, &buf);
count++;
boson_list = (int *)realloc(boson_list, count*sizeof(int));
mtime_list = (time_t *)realloc(mtime_list, count*sizeof(time_t));
mtime_list[count-1] = buf.st_mtime;
boson_list[count-1] = _DtShmProtoAddStrtab(shm_handle,
pathname, &isnew);
if (pathname) free(pathname);
continue;
}
}
(void)closedir( dirp );
}
chdir(cur_path);
data = _DtShmProtoAddIntLst(int_handle, count, &header->files_offset);
memcpy(data, boson_list, count*sizeof(int));
data = _DtShmProtoAddIntLst(int_handle, count*sizeof(time_t)/sizeof(int), &header->mtimes_offset);
memcpy(data, mtime_list, count*sizeof(time_t));
header->files_count = count;
if(boson_list)free(boson_list);
if(mtime_list)free(mtime_list);
return;
}
static int
db_table_size(int num_db, DtDtsDbDatabase **db_list)
{
int db;
DtDtsDbDatabase *db_ptr;
int rec;
DtDtsDbRecord *rec_ptr;
int fld;
DtDtsDbField *fld_ptr;
int size = 0;
size += num_db*sizeof(DtDtsMMDatabase);
for(db = 0; db < num_db; db++)
{
db_ptr = db_list[db];
size += db_ptr->recordCount * sizeof(DtDtsMMRecord);
for(rec = 0; rec < db_ptr->recordCount; rec++)
{
rec_ptr = db_ptr->recordList[rec];
size += rec_ptr->fieldCount * sizeof(DtDtsMMField);
}
}
return(size/sizeof(int));
}
static void
_DtMMSortDataTypes(DtShmProtoStrtab str_handle)
{
DtDtsDbDatabase *dc;
DtDtsDbDatabase *da;
int i;
_DtSvcProcessLock();
dc = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DC_NAME);
da = (DtDtsDbDatabase *) _DtDtsDbGet(DtDTS_DA_NAME);
/*_DtDtsDbPrintRecords(dc, stdout);*/
for(i = 0; i < dc->recordCount; i++)
{
if(dc->recordList[i]->compare != cde_dc_field_compare)
{
_DtDtsDbFieldSort(dc->recordList[i],
cde_dc_field_compare);
}
}
_DtDtsDbRecordSort(dc, cde_dc_compare);
for(i = 0; i < da->recordCount; i++)
{
if(da->recordList[i]->compare !=
_DtDtsDbCompareFieldNames)
{
_DtDtsDbFieldSort(da->recordList[i],
_DtDtsDbCompareFieldNames);
}
}
_DtDtsDbRecordSort(da, _DtDtsDbCompareRecordNames);
/*_DtDtsDbPrintRecords(dc, stdout);*/
_DtSvcProcessUnlock();
}
static void
add_if_missing(DtDtsDbRecord *rec_ptr, XrmQuark name, char *value)
{
DtDtsDbField *fld_ptr;
int fld;
int found = 0;
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
{
fld_ptr = rec_ptr->fieldList[fld];
if(name == fld_ptr->fieldName)
{
found = 1;
break;
}
}
if(found)
{
return;
}
fld_ptr = _DtDtsDbAddField(rec_ptr);
fld_ptr->fieldName = name;
fld_ptr->fieldValue = value;
_DtDtsDbFieldSort(rec_ptr, 0);
return;
}
static void
_DtMMAddActionsToDataAttribute(DtDtsDbDatabase *db_ptr)
{
int rec;
DtDtsDbRecord *rec_ptr;
int action_flag = 0;
int sort_flag = 0;
int found_flag = 0;
int n;
const char *tmp;
XrmQuark desc_qrk = XrmStringToQuark(DtDTS_DA_DESCRIPTION);
XrmQuark icon_qrk = XrmStringToQuark(DtDTS_DA_ICON);
XrmQuark label_qrk = XrmStringToQuark(DtDTS_DA_LABEL);
for(rec = 0; rec < db_ptr->recordCount; rec++)
{
int found_des = 0;
int found_icon = 0;
int found_label = 0;
char *obj_type;
rec_ptr = db_ptr->recordList[rec];
obj_type = XrmQuarkToString(rec_ptr->recordName);
if ( _DtDtsDbGetFieldByName(rec_ptr,
DtDTS_DA_IS_ACTION) == 0 )
{
continue;
}
add_if_missing(rec_ptr, desc_qrk,
DtActionDescription(obj_type));
add_if_missing(rec_ptr, icon_qrk, DtActionIcon(obj_type));
add_if_missing(rec_ptr, label_qrk, DtActionLabel(obj_type));
}
}
static int
build_new_db(DtShmProtoStrtab shm_handle, DtShmProtoIntList int_handle, int num_db, DtDtsDbDatabase **db_list)
{
DtDtsMMDatabase *new_db_list;
int db;
DtDtsDbDatabase *db_ptr;
DtDtsMMDatabase *new_db_ptr;
int rec;
DtDtsDbRecord *rec_ptr;
DtDtsMMRecord *new_rec_ptr;
DtDtsMMRecord *new_rec_ptr_list;
int fld;
DtDtsDbField *fld_ptr;
DtDtsMMField *new_fld_ptr;
DtDtsMMField *new_fld_ptr_list;
int index;
int db_index;
int isnew;
char *tmp;
/* create a space to hold the list of database structures */
new_db_list = (DtDtsMMDatabase *)_DtShmProtoAddIntLst(int_handle,
num_db*sizeof(DtDtsMMDatabase)/sizeof(int),
&db_index);
for(db = 0; db < num_db; db++)
{
int last_boson = -1;
int list_count = 0;
DtShmProtoInttab nameIndex;
int size;
int *idx;
new_db_ptr = &new_db_list[db];
db_ptr = db_list[db];
new_db_ptr->databaseName = _DtShmProtoAddStrtab(shm_handle, db_ptr->databaseName, &isnew);
new_db_ptr->recordCount = db_ptr->recordCount;
/* create space to hold record list */
new_rec_ptr_list = (DtDtsMMRecord *)_DtShmProtoAddIntLst(int_handle,
db_ptr->recordCount*sizeof(DtDtsMMRecord)/sizeof(int),
&index);
new_db_ptr->recordList = index;
/* create index to names list */
nameIndex = _DtShmProtoInitInttab(db_ptr->recordCount);
for(rec = 0; rec < db_ptr->recordCount; rec++)
{
new_rec_ptr = &new_rec_ptr_list[rec];
rec_ptr = db_ptr->recordList[rec];
new_rec_ptr->recordName = QtB(rec_ptr->recordName);
if(new_rec_ptr->recordName != last_boson)
{
/* save name position */
_DtShmProtoAddInttab(nameIndex, new_rec_ptr->recordName, rec);
last_boson = new_rec_ptr->recordName;
}
new_rec_ptr->pathId = _DtShmProtoAddStrtab(shm_handle,
tmp = _DtDbPathIdToString(rec_ptr->pathId),
&isnew);
XtFree(tmp);
new_rec_ptr->seq = rec_ptr->seq;
new_rec_ptr->fieldCount = rec_ptr->fieldCount;
/* create space for field list */
new_fld_ptr_list = (DtDtsMMField *)_DtShmProtoAddIntLst(int_handle,
rec_ptr->fieldCount*sizeof(DtDtsMMField)/sizeof(int),
&index);
new_rec_ptr->fieldList = index;
for(fld = 0; fld < rec_ptr->fieldCount; fld++)
{
new_fld_ptr = &new_fld_ptr_list[fld];
fld_ptr = rec_ptr->fieldList[fld];
new_fld_ptr->fieldName = QtB(fld_ptr->fieldName);
new_fld_ptr->fieldValue = fld_ptr->fieldValue?_DtShmProtoAddStrtab(shm_handle,
fld_ptr->fieldValue, &isnew):0;
}
}
/* create table for index and save it */
size = _DtShmProtoSizeInttab(nameIndex);
idx = _DtShmProtoAddIntLst(int_handle, size/sizeof(int), &new_db_ptr->nameIndex);
_DtShmProtoCopyInttab(nameIndex, (void *)idx);
_DtShmProtoDestroyInttab(nameIndex);
}
return(db_index);
}
struct list
{
DtShmBoson boson;
int rec;
};
static int
srch(const void *a, const void *b)
{
int results = ((struct list *)a)->boson - ((struct list *)b)->boson;
if(results == 0)
{
results = ((struct list *)a)->rec - ((struct list *)b)->rec;
}
return(results);
}
static void
showtable(
DtDtsDbDatabase *db,
struct list *name_index,
struct list *other,
DtDtsMMHeader *head,
int other_break)
{
int i;
printf("============== names =====================\n");
for(i = 0; name_index[i].boson; i++)
{
printf("%20s -> %s\n",
XrmQuarkToString(db->recordList[name_index[i].rec]->recordName),
_DtShmProtoLookUpStrtab(shm_handle,
name_index[i].boson));
}
printf("%d entries\n", i);
printf("============= other ======================\n");
for(i = 0; i < other_break; i++)
{
printf("%s\n",
XrmQuarkToString(db->recordList[other[i].rec]->recordName));
}
printf("%d entries\n", i);
}
static int
build_name_list(DtDtsDbDatabase *db,
DtShmProtoIntList int_handle,
DtDtsMMHeader *head)
{
struct list *other;
int i;
char *c;
int isnew;
struct list *name_index;
int next = 0;
int other_break = 0;
DtShmProtoInttab indexList = 0;
DtShmBoson last_boson = -1;
int *list_of_recs = 0;
int list_count = 0;
int index = 0;
int size;
void *space;
/* create tmp space for two lists */
name_index = (struct list *)calloc(db->recordCount*2,
sizeof(struct list));
other = (struct list *)calloc(db->recordCount, sizeof(struct list));
/* step through all records */
for(i = 0; i < db->recordCount; i++)
{
DtShmBoson boson;
char *attr;
char *t;
/* see if a name pattern exist */
attr = _DtDtsDbGetFieldByName(db->recordList[i],
DtDTS_NAME_PATTERN);
if(!attr)
{
/* it didn't so check path pattern */
attr = _DtDtsDbGetFieldByName(db->recordList[i],
DtDTS_PATH_PATTERN);
if(!attr)
{
/* neither exist so save it as plain buffer */
if(!head->buffer_start_index)
{
head->buffer_start_index = other_break;
}
other[other_break++].rec = i;
continue; /* go to next record */
}
}
/* we have a name now find its final component */
c = strrchr(attr, '/');
if(c)
{
c++;
}
if(!c)
{
c = attr;
}
else
{
attr = c;
}
/* now see if that final component has any *,?,[ */
while(c && *c &&
!(*c == '*' ||
*c == '[' ||
*c == '?' ||
*c == '$' ))
{
c++;
}
if(c && *c == '\0')
{
/* it doesn't so save it in the name index */
name_index[next].boson =
_DtShmProtoAddStrtab(shm_handle,
(const char *)attr, &isnew);
name_index[next++].rec = i;
continue; /* next record */
}
/* the name had something in it now lets get the suffix */
c = strrchr(attr, '.');
attr = c;
/* lets see if the suffix has any *,?,[ */
while(c && *c &&
!(*c == '*' ||
*c == '[' ||
*c == '?' ||
*c == '$' ))
{
c++;
}
if(c && *c == '\0')
{
/* it doesn't so save it in the name index */
name_index[next].boson =
_DtShmProtoAddStrtab(shm_handle,
(const char *)attr, &isnew);
name_index[next++].rec = i;
}
else
{
/* couldn't find any thing so save it as other */
other[other_break++].rec = i;
}
}
if (next > 0)
{
qsort(name_index, next, sizeof(struct list), srch);
}
/*
showtable(db, name_index, other, head, other_break);
printf(" next = %d\n", next);
printf(" other_break = %d\n", other_break);
printf("head->buffer_start_index = %d\n", head->buffer_start_index);
*/
/* create a table and add the records to it. However
duplicates need to be in separate lists.
*/
indexList = _DtShmProtoInitInttab(next+3);
for(i = 0; i <= next; i++)
{
if(i != next && (last_boson == -1 || name_index[i].boson == last_boson))
{
/* this a new list of records or an addition to one */
list_of_recs = (int *)realloc(list_of_recs,
++list_count*sizeof(int));
last_boson = name_index[i].boson;
list_of_recs[list_count-1] = name_index[i].rec;
}
else
{
/* we reached the end of a list now we check how many
are in the list.
*/
if(list_count == 1)
{
/* if just one just add it in the index */
_DtShmProtoAddInttab(indexList,
last_boson, list_of_recs[0]);
}
else
{
/* if there are multiple items in the list
create a table for them */
int *list = _DtShmProtoAddIntLst(int_handle,
list_count, &index);
/* write the list to the to the table */
memcpy(list, list_of_recs,
list_count*sizeof(int));
/* then index on the negative of the boson
so that we know it is a list */
_DtShmProtoAddInttab(indexList,
last_boson, -index);
list_count = 0;
list_of_recs = (int *)realloc(list_of_recs,
++list_count*sizeof(int));
}
if ( i != next )
{
/* reset for the next set */
last_boson = name_index[i].boson;
list_of_recs[list_count-1] = name_index[i].rec;
}
}
}
/* same thing but they all go into a separate list */
if(other_break > 0)
{
/* create the space */
int *list = _DtShmProtoAddIntLst(int_handle,
other_break, &head->no_name_offset);
/* copy it into the list */
for(i = 0; i < other_break; i++)
{
list[i] = other[i].rec;
}
}
else
{
head->no_name_offset = -1;
}
/* make the real space */
size = _DtShmProtoSizeInttab(indexList);
space = _DtShmProtoAddIntLst(int_handle, size/sizeof(int),
&head->name_list_offset);
_DtShmProtoCopyInttab(indexList, space);
_DtShmProtoDestroyInttab(indexList);
if(name_index)free(name_index);
if(list_of_recs)free(list_of_recs);
if(other)free(other);
return(index);
}
static int
write_db(DtDtsMMHeader *header, void *index, int size, const char *CacheFile)
{
int fd;
mode_t cmask = umask((mode_t)077);
char *tmpfile;
/* tempnam(3) is affected by the TMPDIR environment variable. */
/* This creates problems for rename() is "tmpfile" and "cacheFile" */
/* are on different file systems. Use tmpnam(3) to create the */
/* unique file name instead. */
char tmpnam_buf[L_tmpnam + 1];
tmpfile = (char *)malloc(sizeof(_DTDTSMMTEMPDIR) +
sizeof(_DTDTSMMTEMPFILE) + L_tmpnam + 3);
tmpnam(tmpnam_buf);
sprintf(tmpfile, "%s/%s%s", _DTDTSMMTEMPDIR, _DTDTSMMTEMPFILE,
basename(tmpnam_buf));
fd = open(tmpfile, O_RDWR|O_CREAT, 0600);
umask(cmask);
if(fd == -1)
{
_DtSimpleError(
DtProgName, DtError, NULL,
(char*) tmpfile, NULL);
return(0);
}
/* Remove file on write failure - we don't */
/* want a partial dtdbcache file. */
if ((write(fd, header, sizeof(DtDtsMMHeader))
!= sizeof(DtDtsMMHeader)) ||
(write(fd, index, size) != size))
{
close(fd);
unlink(tmpfile);
free(tmpfile);
return(0);
}
close(fd);
if(rename((const char *)tmpfile, CacheFile) == -1)
{
_DtSimpleError(
DtProgName, DtError, NULL,
(char*) CacheFile, NULL);
unlink(CacheFile); /* Just in case? */
unlink(tmpfile);
free(tmpfile);
return(0);
}
free(tmpfile);
return(1);
}
_DtActionCompareRecordBoson(
DtDtsMMRecord *record1,
DtDtsMMRecord *record2 )
{
int results = (int)record1->recordName - (int)record2->recordName;
if (results)
return(results);
return((int)record1 - (int)record2);
}

View File

@@ -0,0 +1,92 @@
/************************************<+>*************************************
****************************************************************************
**
** File: Qualify.c
**
** RCS: $XConsortium: Qualify.c /main/3 1995/10/26 15:09:47 rswiston $
**
** Project: DT
**
** Description: Fully qualify a file with the first path found
** in a list of colon-separated paths
**
** (c) Copyright 1993 by Hewlett-Packard Company
**
****************************************************************************
************************************<+>*************************************/
#include <stdio.h>
#include <string.h>
/*********************************************************************
* _DtQualifyWithFirst
*
* takes: an unqualified filename like foo.txt, and
* a colon-separated list of pathnames, such as
* /etc/dt:/usr/dt/config
*
* returns: a fully qualified filename. Space for the filename
* has been allocated off the heap using malloc. It is
* the responsibility of the calling function to dispose
* of the space using free.
*
* example: ...
* char * filename;
* ...
* filename = _DtQualifyWithFirst("configFile",
* "/foo/first/location:/foo/second/choice");
* < use filename >
* free(filename);
*
**********************************************************************/
char * _DtQualifyWithFirst
(
char * filename,
char * searchPath
)
{
char * paths = searchPath;
char * path;
char * chance;
FILE * f;
/* assert that the arguments cannot be NULL and cannot be empty */
if (filename == NULL || searchPath == NULL ||
filename[0] == 0 || searchPath[0] == 0)
return NULL;
while (1) {
/* if there is a :, zero it */
if ((path = strchr(paths, ':')) != NULL)
*path = 0;
/* allocate space and create the qualified filename */
chance = (char *)malloc(strlen(paths) + strlen(filename) + 2);
if (filename[0] == '/')
sprintf(chance,"%s%s",paths,filename);
else
sprintf(chance,"%s/%s",paths,filename);
/* see if it is there by opening it for reading */
if (f = fopen(chance,"r")) {
fclose(f); /* it's there so close it, .... */
if (path) /* ... restore the colon, .... */
*path = ':';
return chance; /* return the fully qualified filename */
}
free(chance);
if (path == NULL) /* reached the end of the list of paths */
break;
*path = ':'; /* restore the colon */
paths = path + 1; /* try the next path */
}
return NULL;
}

View File

@@ -0,0 +1,56 @@
/*****************************************************************************
*
* File: Qualify.h
* RCS: $XConsortium: Qualify.h /main/3 1995/10/26 15:10:03 rswiston $
* Description: Public header file for the Qualify routine
* Project: DT Runtime Library
* Language: C
* Package: N/A
*
* (c) Copyright 1993 by Hewlett-Packard Company
*
*****************************************************************************/
/*********************************************************************
* _DtQualifyWithFirst
*
* takes: an unqualified filename like foo.txt, and
* a colon-separated list of pathnames, such as
* /etc/dt:/usr/dt/config
*
* returns: a fully qualified filename. Space for the filename
* has been allocated off the heap using malloc. It is
* the responsibility of the calling function to dispose
* of the space using free.
*
* example: ...
* char * filename;
* ...
* filename = _DtQualifyWithFirst("configFile",
* "/foo/first/location:/foo/second/choice");
* < use filename >
* free(filename);
*
**********************************************************************/
#ifndef _Dt_Qualify_h
#define _Dt_Qualify_h
# ifdef __cplusplus
extern "C" {
# endif
extern char * _DtQualifyWithFirst
(
char *, /* file to locate */
char * /* list of colon-separated paths in which to look */
);
# ifdef __cplusplus
}
# endif
#endif /* _Dt_Qualify_h */
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,515 @@
/* $XConsortium: Saver.c /main/8 1996/11/21 19:56:41 drk $ */
/* *
* (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. *
*/
/*************************************<+>*************************************
*****************************************************************************
**
** File: Saver.c
**
** Description:
** -----------
** This file contains public and private screen saver utilities.
**
** Public:
** DtSaverGetWindows() - return array of windows on which saver can draw
**
** Private:
** _DtSaverStart() - launch specified screen saver
** _DtSaverStop() - kill specified screen saver
**
*****************************************************************************
*************************************<+>*************************************/
#include <stdio.h>
#include <stdlib.h>
#define X_INCLUDE_STRING_H
#define XOS_USE_XT_LOCKING
#include <X11/Xos_r.h>
#include <X11/Intrinsic.h>
#include <Saver.h>
#include <SaverP.h>
#include "DtSvcLock.h"
/*
* Constants global to this file.
*/
#define DT_SAVER_MAX_SCREENS 10
struct saver_state {
unsigned short serial;
Window xid;
struct saver_state *next;
};
static Atom xa_saver_register;
static struct saver_state saver_list = {0, (Window)0, NULL};
/*
* Local functions.
*/
static void RegisterSaverCB(
Widget w,
XtPointer client_data,
XEvent *event,
Boolean *continue_to_dispatch
);
/*************************************<->*************************************
*
* _DtSaverStart() - start a screen saver
*
* Description:
* -----------
* _DtSaverStart() is one of a suite of screen saver API's used in the
* desktop. These APIs are:
*
* _DtSaverStart() starts a screen saver (private)
* _DtSaverStop() stops a screen saver (private)
* DtSaverGetWindows() return array of windows on which saver can draw
*
* The _DtSaverStart() API allocates a state variable for the screen saver
* which contains a serial number and NIL window ID. A list of these state
* variables is maintained, one for each call to _DtSaverStart().
* DtSaverStart() then sets up the DTSAVERINFO environment variable containing
* the serial number, window count and window list provided. Finally, it
* launches the provided action and returns an opaque pointer to the state
* variable. The action is expected to be a screen saver which makes use
* of the DtSaverGetWindows() API.
*
* When the screen saver starts, it calls the DtSaverGetWindows() API. From
* the screen saver perspective, the API returns an array of windows on which
* the screen saver can draw. To to this, the API obtains the DTSAVERINFO
* environment variable, and parses out the window array. The API also
* creates a window and sends a ClientMessage to the first DTSAVERINFO window
* containing the serial number and newly created window id.
*
* RegisterSaverCB() is a callback called when the ClientMessage arrives from
* a screen saver. This callback first searches the screen saver state list
* by serial number. If a state variable is not found, RegisterSaverCB()
* assumes the screen saver must have been stopped by a call to
* _DtSaverStop(), so kills the client via XKillClient() using the window id
* provided in the message. If the state variable is located,
* RegisterSaverCB() stores the window id in the state variable.
*
* _DtSaverStop() searches the screen saver list using the serial number
* provided in the input state variable. It should always be found. When
* found, if the state variable window id is set, _DtSaverStop() kills the
* screen saver client via XKillClient(), deletes the state variable from
* the list and deallocates the state variable.
*
* Inputs:
* ------
* display - display structure
* drawArea - array of widgets to be stored drawn upon by saver
* count - number of elements in drawArea array
* saverAction - screen saver action name to invoke
* wAction - widget on which possible DtActionInvoke() errors should display
*
* Outputs:
* -------
*
* Return:
* -------
* state - pointer to opaque state structure
*
* Comments:
* --------
* This function uses DtActionInvoke() to launch an action. As a result,
* the caller is responsible for loading and maintaining the action database
* using the DtDbLoad() function and procedures. The caller
* must call _DtSaverStop() to terminate screen saver
*
*************************************<->***********************************/
void *
_DtSaverStart(
Display *display,
Widget *drawArea,
int count,
char *saverAction,
Widget wAction)
{
static char envdata[(DT_SAVER_MAX_SCREENS * 12) + 20];
struct saver_state *state;
struct saver_state *p;
int i;
_DtSvcProcessLock();
/*
* If first time in, insert envdata in process environment.
*/
if (saver_list.serial == 0)
{
putenv(envdata);
envdata[0] = '\0';
xa_saver_register = XInternAtom(display, "_DT_SAVER_REGISTER", False);
}
/*
* Add event handler (it might already be there - that's ok).
*/
XtAddEventHandler(drawArea[0], 0, True, RegisterSaverCB, NULL);
/*
* Allocate state structure for this saver.
*/
if (!(state = (struct saver_state *)malloc(sizeof(struct saver_state))))
{
_DtSvcProcessUnlock();
return(NULL);
}
/*
* Initialize state structure and append to saver_list.
*/
state->serial = saver_list.serial++;
state->xid = (Window)0;
state->next = NULL;
p = &saver_list;
while (p->next != NULL)
{
p = p->next;
}
p->next = state;
/*
* Set up environment. It will look like:
* DTSAVERINFO="<serial> <count> <win0> <win1> ... <winN>"
*/
sprintf(envdata, "DTSAVERINFO=%u %i %lx",
state->serial, count, XtWindow(drawArea[0]));
for (i = 1; i < count; i++)
{
char *pe = envdata + strlen(envdata);
sprintf(pe, " %lx", XtWindow(drawArea[i]));
}
_DtSvcProcessUnlock();
/*
* Launch saver.
*/
DtActionInvoke(wAction, saverAction, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
/*
* Return array as state information.
*/
return((void *)state);
}
/*************************************<->*************************************
*
* _DtSaverStop() - stop a screen saver
*
* Description:
* -----------
* Stop an external screen saver started with DtStartSaver().
*
* _DtSaverStop() searches the screen saver list using the serial number
* provided in the input state variable. It should always be found. When
* found, if the state variable window id is set, _DtSaverStop() kills the
* screen saver client via XKillClient(), deletes the state variable from
* the list and deallocates the state variable.
*
* Inputs:
* ------
* display - display structure
* state - state returned from _DtSaverStart()
*
* Outputs:
* -------
*
* Return:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
void
_DtSaverStop(
Display *display,
void *pstate)
{
struct saver_state *state = (struct saver_state *)pstate;
struct saver_state *p;
_DtSvcProcessLock();
/*
* Unlink from saver_list.
*/
p = &saver_list;
while (p->next != state)
{
p = p->next;
}
p->next = state->next;
_DtSvcProcessUnlock();
/*
* Kill client using window id provided by RegisterSaverCB().
*/
if (state->xid != (Window)0)
{
XKillClient(display, state->xid);
}
/*
* Free state allocated by _DtSaverStart();
*/
free(pstate);
}
/*************************************<->*************************************
*
* DtSaverGetWindows() - return array of windows on which saver can draw
*
* Description:
* -----------
*
* This is a PUBLIC API.
*
* When the screen saver starts, it calls the DtSaverGetWindows() API. From
* the screen saver perspective, the API returns an array of windows on which
* the screen saver can draw. To to this, the API obtains the DTSAVERINFO
* environment variable, and parses out the window array. The API also
* creates a window and sends a ClientMessage to the first DTSAVERINFO window
* containing the serial number and newly created window id.
*
* Inputs:
* ------
* display - display structure
* window - pointer to memory in which to place pointer to array
* count - pointer to memory in which to place count
*
* Outputs:
* -------
* *window - pointer to array
* *count - count
*
* Return:
* -------
* True - window list returned
* False - window list not returned
*
* Comments:
* --------
* The array memory should be freed by the caller via free().
*
*************************************<->***********************************/
Boolean
DtSaverGetWindows(
Display *display,
Window **window,
int *count)
{
char *envdata, *p, *q;
unsigned short serial;
int envcount;
XClientMessageEvent event;
Window xid_window;
_Xstrtokparams strtok_buf;
_DtSvcDisplayToAppContext(display);
_DtSvcAppLock(app);
*window = NULL;
*count = 0;
_DtSvcProcessLock();
xa_saver_register = XInternAtom(display, "_DT_SAVER_REGISTER", False);
/*
* Get invocation information from environment.
*/
envdata = getenv("DTSAVERINFO");
if (!envdata)
{
_DtSvcProcessUnlock();
_DtSvcAppUnlock(app);
return(False);
}
/*
* Copy string for later strtok() use.
*/
p = strdup(envdata);
if (!p)
{
_DtSvcProcessUnlock();
_DtSvcAppUnlock(app);
return(False);
}
/*
* Extract serial.
*/
q = _XStrtok(p, " ", strtok_buf);
serial = (unsigned short)strtoul(q, NULL, 10);
/*
* Extract envcount.
*/
q = _XStrtok(NULL, " ", strtok_buf);
envcount = (int)strtoul(q, NULL, 10);
/*
* Allocate memory for window array.
*/
*window = (Window *)malloc((envcount)*sizeof(Window *));
if (!*window)
{
free(p);
_DtSvcProcessUnlock();
_DtSvcAppUnlock(app);
return(False);
}
/*
* Populate result array and envcount.
*/
for (*count = 0; *count < envcount; (*count)++)
{
q = _XStrtok(NULL, " ", strtok_buf);
(*window)[*count] = (Window)strtoul(q, NULL, 16);
}
/*
* Free temp copy of envdata.
*/
free(p);
/*
* Create dummy window to obtain XID.
*/
xid_window = XCreateWindow(display, DefaultRootWindow(display),
0, 0, 1, 1, 0,
CopyFromParent, InputOutput, CopyFromParent,
0, NULL);
if (xid_window == (Window)0)
{
/*
* Could not create dummy window.
*/
free((char *)*window);
*window = NULL;
*count = 0;
_DtSvcProcessUnlock();
_DtSvcAppUnlock(app);
return(False);
}
/*
* Send client message to win0 to register.
*/
event.type = ClientMessage;
event.window = (*window)[0];
event.message_type = xa_saver_register;
event.format = 32;
event.data.l[0] = (Atom)0;
event.data.l[1] = (long)serial;
event.data.l[2] = (long)xid_window;
event.data.l[3] = CurrentTime;
XSendEvent(display, (*window)[0], False, NoEventMask,
(XEvent *) &event);
_DtSvcProcessUnlock();
/*
* Ensure window creation and client message have been processed by
* the server before continuing.
*/
XSync(display, False);
_DtSvcAppUnlock(app);
return(True);
}
/*************************************<->*************************************
*
* RegisterSaverCB() - register a screen saver
*
* Description:
* -----------
* RegisterSaverCB() is a callback called when the ClientMessage arrives from
* a screen saver. This callback first searches the screen saver state list
* by serial number. If a state variable is not found, RegisterSaverCB()
* assumes the screen saver must have been stopped by a call to
* _DtSaverStop(), so kills the client via XKillClient() using the window id
* provided in the message. If the state variable is located,
* RegisterSaverCB() stores the window id in the state variable.
*
* Inputs:
* ------
* w - widget from which we derive the display
* client_data - pointer to client data (unused)
* event - ClientMessage event structure
* continue_to_dispatch - dispatch to remaining event handlers (unused)
*
* Outputs:
* -------
*
* Return:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
static void
RegisterSaverCB(
Widget w,
XtPointer client_data,
XEvent *event,
Boolean *continue_to_dispatch)
{
if (event->type == ClientMessage)
{
XClientMessageEvent *cEvent = (XClientMessageEvent *) event;
_DtSvcProcessLock();
if (cEvent->message_type == xa_saver_register)
{
unsigned short serial = (unsigned short)cEvent->data.l[1];
Window win = (Window)cEvent->data.l[2];
struct saver_state *state;
/*
* Find event in saver list.
*/
state = saver_list.next;
while (state != NULL && state->serial != serial)
{
state = state->next;
}
if (state != NULL)
{
/*
* _DtSaverStop() not yet called for this saver. Store xid in
* saver's state for _DtSaverStop()'s use.
*/
state->xid = win;
}
else
{
/*
* _DtSaverStop() has already been called for this saver, but at the
* time, the saver had not yet registered. Kill the saver client.
*/
XKillClient(XtDisplay(w), win);
}
}
_DtSvcProcessUnlock();
}
}

View File

@@ -0,0 +1,30 @@
/* $XConsortium: Saver.h /main/3 1995/10/26 15:10:29 rswiston $ */
/*
* (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.
*/
#ifndef _dtsaver_h
#define _dtsaver_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* Functions
*/
extern Boolean DtSaverGetWindows(
Display *display,
Window **window,
int *count);
#ifdef __cplusplus
} /* Close scope of 'extern "C"' declaration which encloses file. */
#endif
#endif /*_dtsaver_h*/
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,90 @@
/* $XConsortium: SaverP.h /main/4 1995/10/26 15:10:42 rswiston $ */
/* *
* (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. *
*/
/************************************<+>*************************************
****************************************************************************
**
** File: Saver.h
**
** Description
** -----------
** Variables and declarations needed for
** managing external screen savers
**
****************************************************************************
************************************<+>*************************************/
#ifndef _dtsaverp_h
#define _dtsaverp_h
/*************************************<->*************************************
*
* _DtSaverStart()
*
*
* Description:
* -----------
* Store provided array of windows on root window property
* _DT_SAVER_WINDOWS and launch specified screen saver. Screen savers
* will attempt to use these windows as drawables.
*
* Inputs:
* ------
* display - display structure
* drawArea - array of widgets to be drawn upon by screen saver
* count - number of elements in drawArea array
* saverAction - screen saver action to invoke
* wAction - action UI widget
*
* Outputs:
* -------
*
* Return:
* -------
* state - pointer to opaque state structure
*
* Comments:
* --------
* This function uses _DtActionInvoke() to launch an action. As a result,
* the caller is responsible for loading and maintaining the action database
* using the DtDbLoad() function and procedures. The caller
* must call _DtSaverStop() to terminate screen saver
*
*************************************<->***********************************/
extern void * _DtSaverStart(Display *, Widget *, int, char *, Widget);
/*************************************<->*************************************
*
* _DtSaverStop()
*
*
* Description:
* -----------
* Stop an external screen saver started with DtStartSaver(). Deletes
* _DT_SAVER_WINDOWS property from root window.
*
* Inputs:
* ------
* display - display structure
* state - state returned from _DtSaverStart()
*
* Outputs:
* -------
*
* Return:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
extern void _DtSaverStop(Display *, void *);
#endif /*_dtsaverp_h*/
/* DON'T ADD ANYTHING AFTER THIS #endif */

View File

@@ -0,0 +1,37 @@
/* $XConsortium: Session.h /main/3 1995/10/26 15:10:56 rswiston $ */
/*
* (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.
*/
#ifndef _Dt_Session_h
#define _Dt_Session_h
#include <X11/Intrinsic.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Functions
*/
extern Boolean DtSessionSavePath(
Widget widget,
char **save_path,
char **save_file);
extern Boolean DtSessionRestorePath(
Widget widget,
char **restore_path,
char *restore_file);
#ifdef __cplusplus
}
#endif
#endif /* _Dt_Session_h */

View File

@@ -0,0 +1,228 @@
/* $TOG: SessionM.h /main/8 1998/07/30 12:10:49 mgreess $ */
/*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company
* (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
/*************************************<+>*************************************
*****************************************************************************
**
** File: SessionM.h
**
** Description:
** -----------
** Contains all variables needed for SM messaging. All messages serviced,
** and the tool class name for the session manager
**
**
**
*******************************************************************
** (c) Copyright Hewlett-Packard Company, 1990. All rights are
** reserved. Copying or other reproduction of this program
** except for archival purposes is prohibited without prior
** written consent of Hewlett-Packard Company.
********************************************************************
**
**
*****************************************************************************
*************************************<+>*************************************/
#ifndef _SessionM_h
#define _SessionM_h
/*
* Include files
*/
/* If <X11/Intrinsic.h> is included along with this file, <X11/Intrinsic.h>
MUST be included first due to "typedef Boolean ..." problems. The following
conditional #define is also part of the solution to this problem. */
#include <X11/X.h>
#include <X11/Intrinsic.h>
/*
* Tool class for the session manager
*/
#define DtSM_TOOL_CLASS "SESSIONMGR"
/*
* SM_STARTUP_CHANGE an SM_STATE parameters
*/
#define DtSM_VERBOSE_MODE 1
#define DtSM_QUIET_MODE 2
#define DtSM_ASK_STATE 0
#define DtSM_HOME_STATE 3
#define DtSM_CURRENT_STATE 4
/*
* Atoms for session manager/style manager communication
*/
#define _XA_DT_SM_STM_PROTOCOL "_DT_SM_STM_PROTOCOL"
#define _XA_DT_SM_SAVE_TO_HOME "_DT_SM_SAVE_TO_HOME"
#define _XA_DT_SM_STATE_CHANGE "_DT_SM_STATE_CHANGE"
#define _XA_DT_SM_RESTORE_DEFAULT "_DT_SM_RESTORE_DEFAULT"
#define _XA_DT_SM_PREFERENCES "_DT_SM_PREFERENCES"
/*
* Atoms for lock changes
*/
#define _XA_DT_SM_LOCK_CHANGE "_DT_SM_LOCK_CHANGE"
#define CoverScreenMask (1L<<0)
#define LockOnTimeoutMask (1L<<1)
/*
* Parameters to be sent into session manager
*/
/*
* Atoms for communicating configuration changes and state
*/
/*
* Defines needed for getting/setting the sm window property on the root
*/
#define PROP_DT_SM_WINDOW_INFO_ELEMENTS 2
#define _XA_DT_SM_WINDOW_INFO "_DT_SM_WINDOW_INFO"
/*
* Defines needed for getting the session manager state off it's window
*/
#define PROP_DT_SM_STATE_INFO_ELEMENTS 13
#define _XA_DT_SM_STATE_INFO "_DT_SM_STATE_INFO"
/*
* Defines needed for the screen saver list property.
*/
#define _XA_DT_SM_SAVER_INFO "_DT_SM_SAVER_INFO"
/*
* Defines needed for the screen saver property
*/
#define PROP_DT_SM_SCREEN_INFO_ELEMENTS 5
#define _XA_DT_SM_SCREEN_INFO "_DT_SM_SCREEN_INFO"
/*
* Defines needed for the audio property
*/
#define PROP_DT_SM_AUDIO_INFO_ELEMENTS 4
#define _XA_DT_SM_AUDIO_INFO "_DT_SM_AUDIO_INFO"
/*
* Defines needed for the keyboard property
*/
#define PROP_DT_SM_KEYBOARD_INFO_ELEMENTS 3
#define _XA_DT_SM_KEYBOARD_INFO "_DT_SM_KEYBOARD_INFO"
/*
* Define needed for the font info property
*/
#define _XA_DT_SM_FONT_INFO "_DT_SM_FONT_INFO"
/*
* Define needed for the font info property
*/
#define _XA_DT_SM_POINTER_INFO "_DT_SM_POINTER_INFO"
/*
* Define needed for the preeditType info property
*/
#define _XA_DT_SM_PREEDIT_INFO "_DT_SM_PREEDIT_INFO"
/* bit definitions for SmStateInfo.flags */
#define SM_STATE_NONE 0
#define SM_STATE_START (1L << 0)
#define SM_STATE_CONFIRM (1L << 1)
#define SM_STATE_COMPAT (1L << 2)
#define SM_STATE_SEND (1L << 3)
#define SM_STATE_COVER (1L << 4) /* Obsolete */
#define SM_STATE_LOTOUT (1L << 5) /* Obsolete */
#define SM_STATE_LOTOUTSTAT (1L << 6)
#define SM_STATE_CYCLETIMEOUT (1L << 7)
#define SM_STATE_LOCKTIMEOUT (1L << 8)
#define SM_STATE_SAVERTIMEOUT (1L << 9)
#define SM_STATE_RANDOM (1L << 10)
#define SM_STATE_DISP_SESSION (1L << 11)
#define SM_STATE_ALL (SM_STATE_START | SM_STATE_CONFIRM |\
SM_STATE_COMPAT | SM_STATE_SEND |\
SM_STATE_COVER | SM_STATE_LOTOUT |\
SM_STATE_LOTOUTSTAT | SM_STATE_CYCLETIMEOUT |\
SM_STATE_LOCKTIMEOUT | SM_STATE_SAVERTIMEOUT |\
SM_STATE_RANDOM | SM_STATE_DISP_SESSION)
/*
* typedef statements for structures to be returned
*/
typedef struct
{
int flags;
int smStartState;
int smConfirmMode;
Boolean smCompatMode;
Boolean smSendSettings;
Boolean smCoverScreen; /* Obsolete */
Boolean smLockOnTimeout; /* Obsolete */
Boolean smLockOnTimeoutStatus;
int smCycleTimeout;
int smLockTimeout;
int smSaverTimeout;
Boolean smRandom;
Boolean smDisplaySpecific; /* If True, the currently running
session is for a specific display */
} SmStateInfo;
typedef struct
{
char *saverList;
} SmSaverInfo;
typedef struct
{
int flags;
int smTimeout;
int smInterval;
int smPreferBlank;
int smAllowExp;
} SmScreenInfo;
typedef struct
{
int flags;
int smBellPercent;
unsigned int smBellPitch;
unsigned int smBellDuration;
} SmAudioInfo;
typedef struct
{
int flags;
int smKeyClickPercent;
int smGlobalAutoRepeat;
} SmKeyboardInfo;
/*
* Function definitions
*/
extern Status _DtGetSmWindow(Display *, Window, Window *) ;
extern Status _DtGetSmState(Display *, Window, SmStateInfo *);
extern Status _DtSetSmState(Display *, Window, SmStateInfo *);
extern Status _DtGetSmSaver(Display *, Window, SmSaverInfo *);
extern void _DtSetSmSaver(Display *, Window, SmSaverInfo *);
extern Status _DtGetSmScreen(Display *, Window, Atom, SmScreenInfo *);
extern Status _DtGetSmAudio(Display *, Window, Atom, SmAudioInfo *);
extern Status _DtGetSmKeyboard(Display *, Window, Atom, SmKeyboardInfo *);
extern Status _DtGetSmFont(Display *, Window, Atom, char **);
extern Status _DtGetSmPointer(Display *, Window, Atom, char **);
extern Status _DtGetSmPreedit(Display *, Window, Atom, char **);
#endif /* _SessionM_h */

View File

@@ -0,0 +1,108 @@
/* $TOG: SessionP.h /main/5 1998/07/30 12:11:06 mgreess $ */
/* *
* (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. *
*/
/*************************************<+>*************************************
*****************************************************************************
**
** File: SessionP.h
**
** Description: Private header for Session Management routines
** -----------
**
*******************************************************************
** (c) Copyright Hewlett-Packard Company, 1990. All rights are
** reserved. Copying or other reproduction of this program
** except for archival purposes is prohibited without prior
** written consent of Hewlett-Packard Company.
********************************************************************
**
**
**
*****************************************************************************
*************************************<+>*************************************/
#ifndef _SessionP_h
#define _SessionP_h
/*
* include statements
*/
/*
* define statements
*/
/*
* typedef statements
*/
/*
* Definition for the _DT_SM_WINDOW_INFO property.
*/
typedef struct
{
unsigned long flags;
unsigned long smWindow;
} PropDtSmWindowInfo;
/*
* Definition for the _DT_SM_STATE_INFO property
*/
typedef struct
{
unsigned long flags;
unsigned long smStartState;
unsigned long smConfirmMode;
unsigned long smCompatMode;
unsigned long smSendSettings;
unsigned long smCoverScreen;
unsigned long smLockOnTimeout;
unsigned long smLockOnTimeoutStatus;
unsigned long smCycleTimeout;
unsigned long smLockTimeout;
unsigned long smSaverTimeout;
unsigned long smRandom;
unsigned long smDisplaySpecific;
} PropDtSmStateInfo;
/*
* Definition for the _DT_SM_SCREEN_INFO property
*/
typedef struct
{
unsigned long flags;
unsigned long smTimeout;
unsigned long smInterval;
unsigned long smPreferBlank;
unsigned long smAllowExp;
} PropDtSmScreenInfo;
/*
* Definition for the _DT_SM_AUDIO_INFO property
*/
typedef struct
{
unsigned long flags;
unsigned long smBellPercent;
unsigned long smBellPitch;
unsigned long smBellDuration;
} PropDtSmAudioInfo;
/*
* Definition for the _DT_SM_KEYBOARD_INFO property
*/
typedef struct
{
unsigned long flags;
unsigned long smKeyClickPercent;
unsigned long smGlobalAutoRepeat;
} PropDtSmKeyboardInfo;
#endif /* _SessionP_h */
/* Do not add anything after this endif. */

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