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,40 @@
XCOMM $XConsortium: Imakefile /main/6 1996/10/30 19:10:03 cde-hp $
/*********************************************************************
* (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 Unix System Labs, Inc., a subsidiary of
* Novell, Inc.
**********************************************************************/
DESKTOP_VERSION_STRING = DesktopVersionString
XCOMM
XCOMM Imakefile: for DT Print Dialog Manager Daemon
XCOMM
/* General case INCLUDES DEFINES LOCAL_LIBRARIES
* Each individual architecture may have more or less of the above.
* Use EXTRA_DEFINES and EXTRA_INCLUDES to add defines and includes
* to an individual architecture. There is no equivalent for
* LOCAL_LIBRARIES.
* USE_libraryname in LOCAL_LIBRARIES is by default empty.
* It should be set when necessary to the real library macro name.
*/
DEFINES = -DCDE_INSTALLATION_TOP='"'$(CDE_INSTALLATION_TOP)'"'
INCLUDES = -I.
DEPLIBS = $(DEPXTOOLLIB) $(DEPXPLIB) $(DEPXAUTHLIB) $(DEPXLIB)
LOCAL_LIBRARIES = $(XTOOLLIB) $(XPLIB) $(XAUTHLIB) $(XLIB)
SYS_LIBRARIES = DtClientSysLibs
SRCS = dispatch.c dtpdmd.c mailbox.c \
manager.c records.c setup.c \
util.c nlmsg.c
OBJS = dispatch.o dtpdmd.o mailbox.o \
manager.o records.o setup.o \
util.o nlmsg.o
ComplexProgramTarget(dtpdmd)

View File

@@ -0,0 +1,243 @@
/******************************************************************************
******************************************************************************
**
** File: dispatch.c
** RCS: $XConsortium: dispatch.c /main/4 1996/05/28 13:33:53 cde-hp $
**
** Description:
**
** (c) Copyright 1995, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define DISPATCH_DOT_C
#include "dtpdmdP.h"
/******************************************************************************
*
* Dispatch PDM_MANAGER requests
*
* note: 'rec->pdm_exec_errorcode' is set to 0 (zero) and
* stays that way as long as no errors occur.
* Ultimately it gets set to either and error or
* success code.
*/
void dispatch_mgr( XEvent *report )
{
XpPdmServiceRec *rec;
/*
* Locate or create a client record for this request.
*/
rec = find_rec( report->xselectionrequest.requestor );
/*
* Setup the client record per the request.
*/
mgr_initialize( report, rec );
if ( rec->pdm_exec_errorcode ) {
/*
* Reply to requestor, but with bad news that
* basic initialization in prep to launch a
* pdm could not be completed.
*/
mgr_launch_reply( rec );
delete_rec( rec );
return;
}
/*
* Locate the pdm to be launched.
*/
mgr_fetch_pdm( rec );
if ( rec->pdm_exec_errorcode ) {
/*
* Reply to requestor, but with bad news that
* selection of a pdm to launch could not be
* completed.
*/
mgr_launch_reply( rec );
delete_rec( rec );
return;
}
/*
* Launch the pdm.
*/
mgr_launch_pdm( rec );
if ( rec->pdm_exec_errorcode ) {
/*
* Reply to requestor, but with bad news that
* the pdm could not be launched.
*/
mgr_launch_reply( rec );
delete_rec( rec );
return;
}
/*
* Set state flags indicating a pdm has been started, but
* defer the calling of 'mgr_launch_reply' until after the
* pdm itself tells us it is up and running.
*
* The pdm can generate stderr which we will trap, and can
* generate a SIGCLD which we will also trap and take
* significant on.
*/
rec->pdm_exec_errorcode = g.pdm_start_ok;
rec->do_launch_reply = True;
/* sometime later someone else calls mgr_launch_reply( rec ) */
return;
}
/******************************************************************************
*
* Dispatch MBOX and MAIL requests
*/
void dispatch_mbox( XEvent *report )
{
XpPdmServiceRec *rec;
if (report->type == SelectionRequest) {
/*
* Locate or create a client record for this request.
*/
rec = find_rec( report->xselectionrequest.requestor );
mbox_initialize( report, rec );
mbox_build( rec );
mbox_reply( rec );
}
else /* if (report->type == ClientMessage) */ {
/*
* Locate (do not create) a client record for this request.
*/
rec = find_rec_by_mbox_win( report->xclient.window );
mbox_receive( rec, report );
}
return;
}
/******************************************************************************
*
* Dispatch TARGETS requests
*/
void dispatch_targets( XEvent *report )
{
Atom *target_list;
int target_count;
XEvent reply;
Status status;
target_count = 4;
target_list = (Atom *) Xmalloc( sizeof(Atom) * target_count );
target_list[0] = g.pdm_targets;
target_list[1] = g.pdm_start;
target_list[2] = g.pdm_timestamp;
target_list[3] = g.pdm_mbox;
/* target_list[4] = g.pdm_multiple; */
XChangeProperty( report->xselectionrequest.display,
report->xselectionrequest.requestor,
report->xselectionrequest.property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *) target_list,
target_count );
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = report->xselectionrequest.requestor;
reply.xselection.selection = report->xselectionrequest.selection;
reply.xselection.target = report->xselectionrequest.target;
reply.xselection.property = report->xselectionrequest.property;
reply.xselection.time = report->xselectionrequest.time;
status = XSendEvent( report->xselectionrequest.display,
report->xselectionrequest.requestor,
True, 0, &reply );
}
/******************************************************************************
*
* Dispatch MULTIPLE requests
*/
void dispatch_multiple( XEvent *report )
{
}
/******************************************************************************
*
* Dispatch TIMESTAMP requests
*/
void dispatch_timestamp( XEvent *report )
{
XEvent reply;
Status status;
XChangeProperty( report->xselectionrequest.display,
report->xselectionrequest.requestor,
report->xselectionrequest.property,
XA_INTEGER,
32,
PropModeReplace,
(unsigned char *) &g.time,
1 );
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = report->xselectionrequest.requestor;
reply.xselection.selection = report->xselectionrequest.selection;
reply.xselection.target = report->xselectionrequest.target;
reply.xselection.property = report->xselectionrequest.property;
reply.xselection.time = report->xselectionrequest.time;
status = XSendEvent( report->xselectionrequest.display,
report->xselectionrequest.requestor,
True, 0, &reply );
}
/******************************************************************************
*
* Dispatch unsupported selection requests
*/
void dispatch_not_supported( XEvent *report )
{
XEvent reply;
Status status;
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = report->xselectionrequest.requestor;
reply.xselection.selection = report->xselectionrequest.selection;
reply.xselection.target = report->xselectionrequest.target;
reply.xselection.property = None;
reply.xselection.time = report->xselectionrequest.time;
status = XSendEvent( report->xselectionrequest.display,
report->xselectionrequest.requestor,
True, 0, &reply );
}

View File

@@ -0,0 +1,456 @@
/* $XConsortium: dtpdmd.c /main/9 1996/10/30 19:10:08 cde-hp $ */
/******************************************************************************
******************************************************************************
**
** File: dtpdmd.c
**
** Description: main file for the implementation of the dtpdmd.
**
** (c) Copyright 1995, 1996 Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
/******************************************************************************
*
* BASIC dtpdmd FLOW
*
* Other than setup, one event loop runs the show.
*
* Legend:
*
* -> means XtAppNextEvent breaks out with an event, and a
* case statement figures out where the event should go.
*
* => means XtAppNextEvent dispatches the handler for
* the event directly.
*
* XtAppNextEvent()
*
* -> dispatch_mgr
* o find_rec }
* o mgr_initialize } mgr_launch_reply and delete_rec
* o mgr_fetch_pdm } called as soon as any errors occur
* o mgr_launch_pdm }
* o mgr_shutdown_scan }
*
* -> dispatch_mbox
* o find_rec }
* o mbox_initialize } request for
* o mbox_build } mailbox
* o mbox_reply }
* o mgr_shutdown_scan }
* or
* o find_rec_by_mbox_win } receive incoming
* o mbox_receive } mail
* o mgr_shutdown_scan }
*
* => xtkick_proc (SIGCLD write to pipe handler causes this)
* o mgr_shutdown_scan
*
* => message_pipe_handler
* o child's stderr to pipe to malloc'ed buffer
* o trap EOF on pipe
* o mgr_shutdown_scan
*
* ~> SIGCLD (not really dispatched)
* o the handler notes which child, and exit status,
* then writes a byte to tickle the xtkick_proc
*
* Note the final usage of:
*
* mgr_shutdown_scan
* o possibly pdm_launch_reply
* o possibly pdm_shutdown_reply
* o as appropriate, delete_rec
*/
/******************************************************************************
*
* XIO Error Handling Strategy:
*
* XIO errors can occur from up to 3 display connections:
*
* o sel_dpy (aka prop_dpy)
* - always active. If this display connection goes down,
* then the dtpdmd will not be able to service any more
* pdm requests.
*
* o print_dpy (usually equal to sel_dpy)
* - within the pdm, on a per client basis, only active
* long enough to 1) fetch the dt-pdm-command attribute,
* and to 2) send the final ClientMessage with OK/Cancel.
*
* XIO strategy: wrap setjmp/longjmp around the usages
* of XOpenDisplay on print_dpy.
*
* XIO result: For case #1, set dt-pdm-command using
* built in defaults, thus ignoring XpGetOneAttribute.
*
* For case #2, the best that can be done is to log
* a message to the errorlog.
*
* o video_dpy
* - within the pdm, on a per client basis, only active
* long enough to 1) run a test connection to verify
* authorization.
*
* XIO strategy: wrap setjmp/longjmp around the one
* XOpenDisplay of video_dpy.
*
* XIO result: act as if authorization failed.
*/
#define DTPDMD_DOT_C
#include "dtpdmdP.h"
#include "nlmsg.h"
/********************************************************************
*
* Globals.
*/
XpPdmGlobals g; /* global to all modules */
static int xtkick_pipeG[2]; /* global to this module */
/********************************************************************
*
* pusage
*/
static void pusage( char *prog_name )
{
fprintf(stderr, "\n");
fprintf( stderr, PDMD_MSG_1, prog_name, "PDM_MANAGER", DEFAULT_PDM_EXECUTABLE );
fprintf(stderr, "\n");
fprintf(stderr, "\n");
}
/******************************************************************************
*
* generic_error_handler
*
*****************************************************************************/
static int generic_error_handler( edpy, eevent )
Display *edpy;
XErrorEvent *eevent;
{
g.xerrno = eevent->error_code;
g.xerrreq = eevent->request_code;
g.xerrmin = eevent->minor_code;
}
/******************************************************************************
*
* handle_SIGCLD
*
*****************************************************************************/
static void
#if defined(__aix)
handle_SIGCLD(int sigNum)
#else
handle_SIGCLD(void)
#endif /* __aix */
{
int exitStatus, i;
pid_t pid;
/*
* Query why the SIGCLD happened - a true termination or just
* a stopage. We only care about terminations.
*/
pid = wait(&exitStatus);
if (pid == -1) {
/*
* No specific child found with wait() - punt.
*/
}
else if (!WIFSTOPPED(exitStatus)) {
/*
* The SIGCLD was *not* the result of being stopped, so the child
* has indeed terminated. Look for its tracking record and mark
* accordingly for later shutdown.
*/
for ( i = 0; i < g.serviceRecNum; i++ ) {
if ( g.serviceRecs[i]->pid == pid ) {
/*
* Update tracking record.
*/
g.serviceRecs[i]->exit_received = True;
g.serviceRecs[i]->exit_code = (int) WEXITSTATUS(exitStatus);
/*
* Figure out who will deliver the "tickle" to XtAppNextEvent
* that will allow this child's status to be rediscovered
* so that a subsequent shutdown can be done.
*
* - if the child's message_pipe is still up,
* let its upcoming disconnection be the tickle.
*
* - if the child's message pipe is aleady down,
* then this is our last event related to the
* child, so tickle the "Xt Signal Pipe" we
* installed.
*
* - if the Xt Signal Pipe is down, then we'll have
* to rely upon a 3rd party to deliver an event
* that will reactivate the Xt Main Loop.
*/
if ( g.serviceRecs[i]->message_pipe[0] == -1 ) {
/*
* Tickle our "Xt Signal Pipe".
*/
write( xtkick_pipeG[1], (char *) "", 1 );
}
break;
}
}
}
}
static void xtkick_proc( XtPointer w, int *source, XtInputId *id)
{
char buffer[128];
/*
* Drain off the kicker bytes. Don't care how many, since
* we'll look at all client records.
*/
if ( read(*source, buffer, sizeof (buffer) - 1) <= 0 ) {
close (*source); /* aka xtkick_pipeG[0] */
XtRemoveInput (*id);
xtkick_pipeG[0] = -1; /* mark the pipe as invalid */
xtkick_pipeG[1] = -1;
}
/*
* Scan client records and see who is ready to be
* shut down.
*/
mgr_shutdown_scan();
}
/******************************************************************************
*
* main
*/
main( argc, argv )
int argc;
char **argv;
{
int tscreen;
XtInputId xtid;
Window sel_window;
Display *sel_display;
char *display_str, *auth_file;
Bool security_flag;
XEvent report;
struct sigaction svec;
g.serviceRecNum = 0;
g.maxServiceRecNum = 0;
g.prog_name = argv[0];
g.alt_selection = "PDM_MANAGER";
g.default_pdm = DEFAULT_PDM_EXECUTABLE;
g.override_pdm = (char *) NULL;
display_str = getenv("DISPLAY");
auth_file = (char *) NULL;
g.log_file = (char *) NULL;
security_flag = False;
/*
* Parse command line arguments.
*/
while (*++argv) {
if (!strcmp (*argv, "-a")) {
g.alt_selection = *++argv;
}
else if (!strncmp (*argv, "-d", 2)) {
display_str = *++argv;
}
else if (!strcmp (*argv, "-p")) {
g.default_pdm = *++argv;
}
else if (!strcmp (*argv, "-P")) {
g.override_pdm = *++argv;
}
else if (!strcmp (*argv, "-s")) {
security_flag = True;
}
else if (!strcmp (*argv, "-f")) {
auth_file = *++argv;
}
else if (!strcmp (*argv, "-l")) {
g.log_file = *++argv;
}
else if (!strncmp (*argv, "-h", 2)) {
pusage( g.prog_name );
exit(1);
}
else {
/*
* Ignore unknown options.
*/
}
}
/*
* Open a connection to the X-Server.
*/
XtToolkitInitialize ();
g.context = XtCreateApplicationContext();
if ( (sel_display = XtOpenDisplay( g.context, display_str,
"dtpdmd", "Dtpdmd",
0, 0, &argc, argv )) == NULL ) {
fprintf( stderr , "\n" );
fprintf( stderr , PDMD_MSG_2, g.prog_name, display_str );
fprintf( stderr , "\n" );
fprintf( stderr , "\n" );
exit(0);
}
/*
* Create master PDM window upon which selections
* will be created.
*/
tscreen = DefaultScreen( sel_display );
sel_window = XCreateSimpleWindow( sel_display,
DefaultRootWindow( sel_display ),
0, 0, 1, 1, 1,
BlackPixel(sel_display, tscreen),
WhitePixel(sel_display, tscreen) );
/*
* Setup PDM_MANAGER selection
*/
if ( ! _PdmMgrSetup( sel_display, sel_window, security_flag ) ) {
fprintf( stderr , "\n" );
fprintf( stderr , PDMD_MSG_3, g.prog_name , g.alt_selection );
fprintf( stderr , "\n" );
fprintf( stderr , "\n" );
exit(0);
}
/*
* Install the "Xt Signal Pipe" Kicker handler.
*/
if ( pipe(xtkick_pipeG) == -1 ) {
fprintf( stderr , "\n" );
fprintf( stderr , PDMD_MSG_4, g.prog_name );
fprintf( stderr , "\n" );
fprintf( stderr , "\n" );
exit(0);
}
xtid = XtAppAddInput( g.context, xtkick_pipeG[0],
(XtPointer) XtInputReadMask,
xtkick_proc, (XtPointer) NULL );
/*
* Install signal handers.
*/
sigemptyset(&svec.sa_mask);
svec.sa_flags = 0;
svec.sa_handler = handle_SIGCLD;
(void) sigaction(SIGCLD, &svec, (struct sigaction *) NULL);
/*
* After this point, we need to trap all X and XIO errors.
*
* XIO trap handlers are installed at critical points, and
* the following generic X trap handler is used to set
* globals.
*/
XSetErrorHandler( generic_error_handler );
/*
* MASTER EVENT LOOP
*/
while (1) {
/*
* XtAppNextEvent breaks for several reasons:
* - X event received
*
* XtAppNextEvent will dispatch for several reasons:
* - Alt input occurs on a pdm message pipe
* - Alt input occurs because a pdm message pipe was disconnected
* - Alt input occurs on our "Xt Signal Pipe" and we need to
* rediscover what happened as a result of that signal.
*/
XtAppNextEvent( g.context, &report );
switch (report.type) {
case ClientMessage:
if (report.xclient.message_type == g.pdm_mail) {
dispatch_mbox( &report );
}
else {
/* ignore/pitch the event */
}
break;
case SelectionRequest:
if (report.xselectionrequest.selection == g.pdm_selection) {
if (report.xselectionrequest.target == g.pdm_start) {
dispatch_mgr( &report );
}
else if (report.xselectionrequest.target==g.pdm_targets) {
dispatch_targets( &report );
}
else if (report.xselectionrequest.target==g.pdm_multiple){
dispatch_multiple( &report );
}
else if (report.xselectionrequest.target==g.pdm_timestamp){
dispatch_timestamp( &report );
}
else if (report.xselectionrequest.target==g.pdm_mbox) {
dispatch_mbox( &report );
}
else {
dispatch_not_supported( &report );
}
}
else {
/* ignore/pitch the event */
}
break;
case SelectionNotify:
/* pitch the event */
break;
case SelectionClear:
/*
* Someone is trying to tear away the selection.
* REACT by trying to reclaim it and logging an
* error.
*/
break;
default:
break;
}
/*
* Use the opportunity to check for freshly finished
* PDMs, and close them out.
*/
mgr_shutdown_scan();
}
XDestroyWindow( sel_display, sel_window );
XtCloseDisplay( sel_display );
exit(0);
}

View File

@@ -0,0 +1,128 @@
$ *************************************<+>*************************************
$ *****************************************************************************
$ **
$ ** File: dtpdmd.msg
$ **
$ ** Description:
$ ** -----------
$ ** This file is the source for the message catalog for the Dt Print
$ ** Dialog Manager Daemon.
$ **
$ **
$ *****************************************************************************
$ **
$ ** (c) Copyright 1996 Digital Equipment Corporation.
$ ** (c) Copyright 1996 Hewlett-Packard Company.
$ ** (c) Copyright 1996 International Business Machines Corp.
$ ** (c) Copyright 1996 Sun Microsystems, Inc.
$ ** (c) Copyright 1996 Novell, Inc.
$ ** (c) Copyright 1996 FUJITSU LIMITED.
$ ** (c) Copyright 1996 Hitachi.
$ **
$ *****************************************************************************
$ **
$ **
$ ** $XConsortium: dtpdmd.msg /main/1 1996/10/30 19:19:06 cde-hp $
$ *****************************************************************************
$ *****************************************************************************
$set 1
$ /* NL_COMMENT
$
$ General Translator Comments
$
$ - The acronyms "pdm" and "PDM" are used in several
$ messages, and were derived from the english phrase
$ "Print Dialog Manager". The acronyms should not be
$ localized.
$
$ - The acronym "pdmd" is used in several messages,
$ and was derived from the english phrase "Print
$ Dialog Manager Daemon". The acronym should not be
$ localized.
$
$ */
1 usage: %1$s [options]\n\
\n\
where [options] includes:\n\
-d <display> host:display[.screen] of X Print Server\n\
-a <alt selection> an alternate X-selection name (\"%2$s\" default)\n\
-p <default pdm> a default pdm to launch (\"%3$s\" default)\n\
-P <the pdm> the pdm to launch, overrides all others\n\
-s turn on security protocol\n\
-f <auth file> an initial set of authorization cookies\n\
-l <log file> a file for the logging of errors, etc
2 %1$s: error, cannot open display %2$s\n
3 %1$s: error, another pdm is already running (%2$s)\n
4 %s: error, cannot create Xt signal pipe\n
$ /* NL_COMMENT
$
$ - Do not translate the word "SelectionRequest" in
$ messages 5, 6 and 7.
$
$ - Do not translate the word "XmbTextPropertyToTestList"
$ in message 7.
$
$ */
5 %s: error, unable to get SelectionRequest property\n
6 %s: error, invalid format for SelectionRequest property\n
7 %s: error, XmbTextPropertyToTestList failed on SelectionRequest property\n
8 %s: error, unable to create message pipe\n
$ /* NL_COMMENT
$
$ - Do not translate the word "fork" in message 9.
$
$ */
9 %s: error, unable to fork\n
10 %1$s: error, cannot execute \"%2$s\" \n
$ /* NL_COMMENT
$
$ - Do not translate the word "exec" in message 11.
$
$ - Do not translate the words "-display" or
$ "-vdisplay" in message 11.
$
$ */
11 %1$s: exec message logged at %2$s\n\
exec error message = \"%3$s\"\n\
exec error code = %4$s\n\
pdm = \"%5$s\"\n\
-display = \"%6$s\"\n\
-vdisplay = \"%7$s\" \n
12 %1$s: error, unable to send the final %2$s\n\
message to the requesting client on behalf of\n\
the PDM because of a generated X error\n
13 %1$s: error, unable to send the final %2$s\n\
message to the requesting client on behalf of\n\
the PDM because of an XIO error\n
$ /* NL_COMMENT
$
$ - Do not translate the word "stderr" in message 14.
$
$ - Do not translate the words "-display" or
$ "-vdisplay" in message 14.
$
$ */
14 %1$s: pdm message logged at %2$s\n\
pdm = \"%3$s\"\n\
-display = \"%4$s\"\n\
-vdisplay = \"%5$s\"\n\
exit code = \"%6$d\"\n\
stderr = \"%7$s\" \n
15 attached pdmd error= \n\"%s\" \n
16 %1$s: error, cannot open log file \"%2$s\". Turning off stderr message logging\n

View File

@@ -0,0 +1,223 @@
/* $XConsortium: dtpdmdP.h /main/6 1996/10/30 19:11:15 cde-hp $ */
/******************************************************************************
******************************************************************************
**
** File: dtpdmdP.h
**
** Description: misc header stuff for the dtpdmd
**
** (c) Copyright 1995, 1996, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "X11/Xlibint.h"
#include "X11/Intrinsic.h"
#include "X11/Xatom.h"
#include <X11/extensions/Print.h>
#include <X11/Xauth.h>
/*****************************************************************************
*
* dtpdm/dtpdmd Protocol
*/
#include <Dt/dtpdmd.h>
/******************************************************************************
*
* Child Tracking Record - for each fork/exec'ed child, the following
* structure is added to an array to maintain status on the child.
*/
typedef struct
{
/*
* Manager selection portion.
*/
Bool mgr_flag; /* is MGR tracking portion active */
char *video_display_str; /* Video Server Connection Info */
Window video_window;
char *print_display_str; /* Print Server Connection Info */
Window print_window;
XPContext print_context;
char *locale_hint;
Display *selection_display; /* Selection & Property Connection */
Window requestor;
Atom prop_atom;
Atom selection;
Time time; /* time of selection request */
Bool seldpy_as_printdpy; /* Can the selection display connection
be used in lieu of opening a new
print display connection? */
/*
* fork/exec and SIGCLD tracking portion.
*/
/* pre-exec stage */
int message_pipe[2]; /* pipe fildes, -1 if disconnected */
XtInputId message_xtid; /* XtAddInput id for message handler */
char *message_string; /* child's stderr */
char *message_string2; /* dtpdmd's addition to child's err */
/* exec stage */
char **pdm_exec_argvs; /* PDM exec string in argv[] format */
char *pdm_exec_errormessage; /* exec error message (opt) for log */
Atom pdm_exec_errorcode; /* exec error code */
pid_t pid; /* pid of child */
Bool do_launch_reply; /* can someone call mgr_launch_reply? */
/* shutdown stage */
Bool exit_received; /* child has exited (SIGCLD) */
int exit_code; /* exit code */
/*
* Mailbox selection portion.
*/
Bool mbox_flag; /* do we have valid cookies */
Window mbox_window; /* assigned window serving as mbox */
char *in_buf; /* partial-cookie crumbs received */
int in_sofar; /* - total in so far */
int in_expected; /* - grand total expected */
Xauth **cookies; /* completed cookie collection */
int cookie_cnt; /* cookie cnt - partial & completed */
short cookie_state; /* 0 = NULL term, 1 = non-NULL term,
2 = more to come */
char auth_filename[L_tmpnam];
FILE *auth_file;
} XpPdmServiceRec, *XpPdmServiceList;
/******************************************************************************
*
* Global dtpdmd information. Rather than pass it around in
* parameter lists, clump in all in one global.
*/
typedef struct
{
/*
* Type Atom References
*/
Atom pdm_selection; /* PDM Selection */
Atom pdm_targets; /* - target */
Atom pdm_timestamp; /* - target */
Atom pdm_multiple; /* - target */
Atom pdm_start; /* - target */
Atom pdm_start_ok; /* - status code */
Atom pdm_start_vxauth; /* - status code */
Atom pdm_start_pxauth; /* - status code */
Atom pdm_start_error; /* - status code */
Atom pdm_reply; /* OK/Cancel SendMessage type */
Atom pdm_exit_ok; /* - status code */
Atom pdm_exit_cancel; /* - status code */
Atom pdm_exit_vxauth; /* - status code */
Atom pdm_exit_pxauth; /* - status code */
Atom pdm_exit_error; /* - status code */
Atom pdm_mbox; /* - target */
Atom pdm_mail; /* Cookie-Package SendMessage type */
/*
* X-Selection Information
*/
char *alt_selection;
Time time; /* time selection was owned */
/*
* PDM Information
*/
char *default_pdm, *override_pdm;
/*
* Child Service Tracking Record Information
*/
int serviceRecNum;
int maxServiceRecNum;
XpPdmServiceRec **serviceRecs;
/*
* Xt Information
*/
XtAppContext context;
/*
* Other
*/
char *log_file;
char *prog_name;
unsigned char xerrno;
unsigned char xerrreq;
unsigned char xerrmin;
} XpPdmGlobals, *XpPdmGlobalsP;
/******************************************************************************
*
* Global functions.
*
* In each group, one module will define, and all other modules
* will make extern references to them. Here are the extern
* reference statements.
*/
/* dispatch.c */
extern void dispatch_mgr();
extern void dispatch_mbox();
extern void dispatch_targets();
extern void dispatch_multiple();
extern void dispatch_timestamp();
extern void dispatch_not_supported();
/* dtpdmd.c */
extern XpPdmGlobals g;
/* mailbox.c */
extern void mbox_initialize();
extern void mbox_build();
extern void mbox_reply();
extern void mbox_receive();
/* manager.c */
extern void mgr_initialize();
extern void mgr_launch_pdm();
extern void mgr_fetch_pdm();
extern void mgr_launch_reply();
extern void mgr_shutdown_reply();
extern void mgr_shutdown_scan();
/* records.c */
extern XpPdmServiceRec *find_rec();
extern XpPdmServiceRec *find_rec_by_mbox_win();
extern void delete_rec( XpPdmServiceRec *rec );
/* setup.c */
extern Bool _PdmMgrSetup();
/* util.c */
extern jmp_buf xio_quickie_jmp_buf;
extern int xio_quickie_handler();
extern char *xpstrdup();
extern int xpstrspn();
extern int xpstrcspn();
extern char *xpstrtok();
extern void xp_add_argv();

View File

@@ -0,0 +1,212 @@
/******************************************************************************
******************************************************************************
**
** File: mailbox.c
** RCS: $XConsortium: mailbox.c /main/2 1996/07/18 15:26:34 drk $
**
** Description:
**
** (c) Copyright 1995, 1996, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define MAILBOX_DOT_C
#include "dtpdmdP.h"
#include <setjmp.h>
#include <locale.h>
#include <unistd.h>
/******************************************************************************
*
* Setup a child service record per the selection request.
*/
void mbox_initialize( XEvent *report, XpPdmServiceRec *rec )
{
Display *testdpy;
char buf[1024];
Display *selection_display;
Window requestor;
Atom prop_atom;
unsigned long tafter;
XTextProperty text_prop;
char **list;
int list_cnt;
rec->selection_display = report->xselectionrequest.display;
rec->requestor = report->xselectionrequest.requestor;
rec->prop_atom = report->xselectionrequest.property;
rec->selection = report->xselectionrequest.selection;
rec->time = report->xselectionrequest.time;
rec->mbox_flag = False; /* still need to complete mbox */
}
/******************************************************************************
*
* mbox_build()
*
* Build a window per requestor to serve as a mailbox for
* that requestor.
*
* note: a possible optimization is to have a window or two cached
* that could quickly be assigned as a mailbox. When all the mail
* is sent, the window could be released back to the cache.
*/
void mbox_build( XpPdmServiceRec *rec )
{
int tscreen;
tscreen = DefaultScreen( rec->selection_display );
rec->mbox_window = XCreateSimpleWindow( rec->selection_display,
DefaultRootWindow( rec->selection_display ),
0, 0, 1, 1, 1,
BlackPixel(rec->selection_display, tscreen),
WhitePixel(rec->selection_display, tscreen) );
}
/******************************************************************************
*
* mbox_reply()
*
* Reply to the SelectionRequest.
*/
void mbox_reply( XpPdmServiceRec *rec )
{
XEvent reply;
Status status;
FILE *errlog;
long now;
Atom tmpa;
XChangeProperty( rec->selection_display, rec->requestor,
rec->prop_atom, XA_WINDOW,
32, PropModeReplace,
(unsigned char *) &(rec->mbox_window),
1 );
/*
* Send a SelectionNotify event, which will conclude the
* selection handshake.
*/
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = rec->requestor;
reply.xselection.selection = rec->selection;
reply.xselection.target = g.pdm_mbox;
reply.xselection.property = rec->prop_atom;
reply.xselection.time = rec->time;
status = XSendEvent( rec->selection_display, rec->requestor, True, 0, &reply );
}
/******************************************************************************
*
* mbox_receive()
*
* Pickup the mail pieces that come in, buffer until a complete
* cookie comes in, convert to Xauth format, and eventually mark
* the mailbox done when the last cookie is fully received.
*/
void mbox_receive( XpPdmServiceRec *rec, XEvent *report )
{
XClientMessageEvent *cme;
Xauth *c; /* shorthand pointer */
int maxgrab;
char *tptr;
cme = (XClientMessageEvent *) report;
if ( cme -> format == 16 ) {
/*
* Only the cookie header packet would be format 16.
*/
rec->cookie_state = cme->data.s[0];
if (rec->cookie_state == 0) {
/*
* Terminating cookie.
*/
rec->mbox_flag = True; /* all done */
XDestroyWindow( rec->selection_display, rec->mbox_window );
rec->mbox_window = (Window) NULL;
return;
}
if ( rec->cookie_cnt ) {
rec->cookie_cnt++;
rec->cookies = (Xauth **) Xrealloc( (char *) rec->cookies,
sizeof(Xauth *) * rec->cookie_cnt );
}
else {
rec->cookie_cnt++;
rec->cookies = (Xauth **) Xmalloc( sizeof(Xauth *) );
}
rec->cookies[rec->cookie_cnt-1] = (Xauth *) Xmalloc( sizeof(Xauth) );
c = rec->cookies[rec->cookie_cnt-1];
c->address_length = (unsigned short) cme->data.s[1];
c->number_length = (unsigned short) cme->data.s[2];
c->name_length = (unsigned short) cme->data.s[3];
c->data_length = (unsigned short) cme->data.s[4];
c->family = (unsigned short) cme->data.s[5];
c->address = Xmalloc( c->address_length );
c->number = Xmalloc( c->number_length );
c->name = Xmalloc( c->name_length );
c->data = Xmalloc( c->data_length );
rec->in_sofar = 0;
rec->in_expected = c->address_length + c->number_length +
c->name_length + c->data_length;
rec->in_buf = (char *) Xmalloc( rec->in_expected );
}
else if ( cme -> format == 8 ) {
/*
* A cookie crumb has come in.
*/
c = rec->cookies[rec->cookie_cnt-1];
maxgrab = rec->in_expected - rec->in_sofar;
if ( maxgrab > 20 ) maxgrab = 20;
memcpy( (char *) &(rec->in_buf[rec->in_sofar]), cme->data.b, maxgrab );
rec->in_sofar += maxgrab;
if ( rec->in_sofar == rec->in_expected ) {
tptr = rec->in_buf;
memcpy( c->address, tptr, c->address_length );
tptr += c->address_length;
memcpy( c->number, tptr, c->number_length);
tptr += c->number_length;
memcpy( c->name, tptr, c->name_length );
tptr += c->name_length;
memcpy( c->data, tptr, c->data_length );
Xfree( rec->in_buf ); rec->in_buf = (char *) NULL;
if (rec->cookie_state == 1) {
rec->mbox_flag = True; /* all done */
XDestroyWindow( rec->selection_display, rec->mbox_window );
rec->mbox_window = (Window) NULL;
return;
}
}
}
}

View File

@@ -0,0 +1,949 @@
/******************************************************************************
******************************************************************************
**
** File: manager.c
** RCS: $XConsortium: manager.c /main/8 1996/10/30 19:10:15 cde-hp $
**
** Description:
**
** (c) Copyright 1995, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define MANAGER_DOT_C
#define OPTIONAL_PXAUTH_PRETEST 1
#include "dtpdmdP.h"
#include "nlmsg.h"
#include <locale.h>
#include <unistd.h>
/******************************************************************************
******************************************************************************
*
* The following PDM_MANAGER : PDM_START routines are registered
* per child, and dispatched out of XtAppNextEvent
*/
/********************************************************************
*
* message_pipe_handler()
*
* Takes stderr from the child, via a pipe, and stores the output
* in the client tracking record.
*
*/
static void message_pipe_handler( XtPointer w, int *source, XtInputId *id)
{
int i, inc;
struct stat statBuffer;
int delt_with;
int n, keepon;
/*
* Find out who is generating output.
*/
delt_with = False;
for ( i = 0; i < g.serviceRecNum; i++ ) {
if ( g.serviceRecs[i]->message_pipe[0] == *source ) {
delt_with = True;
/*
* Fetch size and grow message_string to hold more.
*/
if ( fstat(*source, &statBuffer) ) {
/* unable to get size */
statBuffer.st_size = 0; /* bail out below */
}
if ( statBuffer.st_size > 0 ) {
if ( g.serviceRecs[i]->message_string ) {
inc = strlen( g.serviceRecs[i]->message_string );
g.serviceRecs[i]->message_string = Xrealloc(
(char *) g.serviceRecs[i]->message_string,
statBuffer.st_size + inc + 1 );
}
else {
inc = 0;
g.serviceRecs[i]->message_string = Xmalloc(
statBuffer.st_size + 1 );
}
/*
* Read off what we know is there.
*/
keepon = True;
while (keepon) {
n = read( *source, &(g.serviceRecs[i]->message_string[inc]),
statBuffer.st_size );
if ( n == statBuffer.st_size ) {
/* read all there is (per the previous stat) */
keepon = False;
}
else if (( n == -1 ) && ( errno == EINTR )) {
/* an interrupt came in before the read could start */
keepon = True;
}
else if (( n == -1 ) || ( n == 0 )) {
/* problems - bail out */
g.serviceRecs[i]->message_pipe[0] = -1;
close(*source);
XtRemoveInput(*id);
keepon = False;
}
else {
/* only a partial read, probably a sig, try for more */
inc += n;
statBuffer.st_size -= n;
keepon = True;
}
}
/*
* NULL terminate what we have so far to make it look
* like a string.
*/
g.serviceRecs[i]->message_string[statBuffer.st_size+inc] = '\0';
}
else {
/*
* No more to read - this really means the pipe is
* going down.
*/
g.serviceRecs[i]->message_pipe[0] = -1;
close (*source);
XtRemoveInput(*id);
}
}
}
if (!delt_with) {
/*
* Some stray pipe that we no longer have information on.
*/
close(*source);
XtRemoveInput(*id);
}
/*
* Scan client records and see who is ready to be
* shut down.
*/
mgr_shutdown_scan();
}
/******************************************************************************
******************************************************************************
*
* The following PDM_MANAGER : PDM_START routines are called by
* the dispatch routines to service selection requests and
* associated events.
*/
/********************************************************************
*
* Setup a child service record per the selection request.
*/
void mgr_initialize( XEvent *report, XpPdmServiceRec *rec )
{
Display *testdpy;
char buf[1024];
Display *selection_display;
Window requestor;
Atom prop_atom;
unsigned long tafter;
XTextProperty text_prop;
char **list;
int list_cnt;
/*
* Grab the PDM_CLIENT_PROP from which all the juicy
* information is retrieved.
*/
selection_display = report->xselectionrequest.display;
requestor = report->xselectionrequest.requestor;
prop_atom = report->xselectionrequest.property;
if ( XGetWindowProperty( selection_display, requestor, prop_atom,
0, 100000, True, AnyPropertyType,
&text_prop.encoding,
&text_prop.format,
&text_prop.nitems,
&tafter,
&text_prop.value ) != Success ) {
/*
* Error
*/
rec->pdm_exec_errorcode = g.pdm_start_error;
sprintf( buf, PDMD_MSG_5, g.prog_name );
rec->pdm_exec_errormessage = xpstrdup( buf );
return;
}
if ( text_prop.format != 8 ) {
/*
* Error
*/
rec->pdm_exec_errorcode = g.pdm_start_error;
sprintf( buf, PDMD_MSG_6, g.prog_name );
rec->pdm_exec_errormessage = xpstrdup( buf );
return;
}
if ( XmbTextPropertyToTextList( selection_display, &text_prop,
&list, &list_cnt ) < 0 ) {
/*
* Error
*/
rec->pdm_exec_errorcode = g.pdm_start_error;
sprintf( buf, PDMD_MSG_7, g.prog_name );
rec->pdm_exec_errormessage = xpstrdup( buf );
return;
}
/*
* Fill in the PDM_MANAGER portion of the client record.
*/
rec->video_display_str = xpstrdup( list[0] );
rec->video_window = strtol(list[1], (char **)NULL, 16);
rec->print_display_str = xpstrdup( list[2] );
rec->print_window = strtol(list[3], (char **)NULL, 16);
rec->print_context = strtol(list[4], (char **)NULL, 16);
rec->locale_hint = xpstrdup( list[5] );
XFreeStringList( list );
rec->selection_display = selection_display;
rec->requestor = requestor;
rec->prop_atom = prop_atom;
rec->selection = report->xselectionrequest.selection;
rec->time = report->xselectionrequest.time;
rec->mgr_flag = True; /* mgr portion of rec now valid */
/*
* Optimization. The only live display connection, for which we
* need to trap XIO errors, is "selection display". For the
* "video" and "print" displays, we have the display strings and
* can establish connections as we need them. Since they are rarely
* used, and opening them up here would create XIO liability problems
* and a startup performance hit, we won't establish connections now.
*
* One optimization however is to see if the "print" display would
* just happen to be the same at the "selection display" currently
* open.
*/
if ( !strcmp( XDisplayString(rec->selection_display),
rec->print_display_str ) ) {
rec->seldpy_as_printdpy = True;
}
else {
rec->seldpy_as_printdpy = False;
#ifdef OPTIONAL_PXAUTH_PRETEST
/*
* Verify connectability to the Print Server.
*
* Note: once beyond the selection phase, all communication
* will be by way of the Print Server. If we cannot
* connect later, then we will have no way to deliver
* EXIT_PXAUTH, EXIT_VXAUTH, EXIT_ERROR, EXIT_OK or
* EXIT_CANCEL. Real bad news!
*
* It is better to discover now that we don't have
* connection authorization for the print display since
* we can still let the user know of PXAUTH problems
* via the selection display currently open.
*
* Unfortunately, this pre-test is a performance hit in the
* startup phase.
*/
if ( ! (testdpy = XOpenDisplay(rec->print_display_str)) ) {
rec->pdm_exec_errorcode = g.pdm_start_pxauth;
return;
}
XCloseDisplay( testdpy );
#endif /* OPTIONAL_PXAUTH_PRETEST */
}
#ifdef OPTIONAL_VXAUTH_PRETEST
/*
* Verify connectability to the Video Server.
*
* It is better to discover now that we don't have
* connection authorization for the video display since
* we can still let the user know of VXAUTH problems
* via the selection display currently open.
*
* Unfortunately, this pre-test is a performance hit in the
* startup phase.
*/
if ( ! (testdpy = XOpenDisplay(rec->video_display_str)) ) {
rec->pdm_exec_errorcode = g.pdm_start_vxauth;
return;
}
XCloseDisplay( testdpy );
#endif /* OPTIONAL_VXAUTH_PRETEST */
}
/********************************************************************
*
* fork/exec a child pdm after setting up a message pipe.
*/
void mgr_launch_pdm( XpPdmServiceRec *rec )
{
int i;
struct sigaction svec;
char buf[1024];
int original_umask;
char *existing_name;
FILE *existing_file;
Xauth *entry;
char *envstr;
/*
* Setup message pipe.
*/
if ( pipe(rec->message_pipe) == -1 ) {
rec->pdm_exec_errorcode = g.pdm_start_error;
sprintf( buf, PDMD_MSG_8, g.prog_name );
rec->pdm_exec_errormessage = xpstrdup( buf );
return;
}
rec->message_xtid = XtAppAddInput( g.context, rec->message_pipe[0],
(XtPointer) XtInputReadMask,
message_pipe_handler, (XtPointer) NULL );
/*
* See if a cookie file is needed.
*/
if (rec->cookie_cnt) {
/*
* Create new .Xauthority file.
*/
original_umask = umask (0077); /* disallow non-owner access */
tmpnam( rec->auth_filename );
rec->auth_file = fopen( rec->auth_filename, "w" );
if (rec->auth_file) {
/*
* Copy existing .Xauthority entries.
*/
existing_name = XauFileName ();
if (existing_name) {
if (access (existing_name, R_OK) == 0) { /* checks REAL id */
existing_file = fopen (existing_name, "r");
if (existing_file) {
for (;;) {
entry = XauReadAuth (existing_file);
if (!entry)
break;
XauWriteAuth( rec->auth_file, entry );
XauDisposeAuth (entry);
}
fclose (existing_file);
}
}
}
/*
* Merge in cookies recently sent.
*/
for ( i = 0; i < rec->cookie_cnt; i++ ) {
XauWriteAuth( rec->auth_file, rec->cookies[i] );
}
fclose( rec->auth_file );
}
original_umask = umask (original_umask);
}
rec->pid = fork();
if ( rec->pid < 0 ) {
rec->pdm_exec_errorcode = g.pdm_start_error;
sprintf( buf, PDMD_MSG_9, g.prog_name );
rec->pdm_exec_errormessage = xpstrdup( buf );
return;
}
else if ( rec->pid == 0) {
/*
* Child process.
*/
/*
* Hook stderr back to parent via message pipe.
*/
dup2(rec->message_pipe[1], 2);
close(rec->message_pipe[0]);
/*
* The child should have default behavior for all signals.
*/
sigemptyset(&svec.sa_mask);
svec.sa_flags = 0;
svec.sa_handler = SIG_DFL;
(void) sigaction(SIGCLD, &svec, (struct sigaction *) NULL);
for (i=3; i < FOPEN_MAX; i++) {
if ((i != rec->message_pipe[1]) &&
(rec->auth_file && (i != fileno(rec->auth_file))))
{
(void) fcntl (i, F_SETFD, 1);
}
}
/*
* Set the new locale for the child.
*
* note: the locale hint will be of the form:
*
* name_spec[;registry_spec[;ver_spec[;encoding_spec]]]
*
* for now, just pull out the name_spec (e.g. 'C')
* and use it. With a little work, a more complex
* syntax could be understood and the appropriate
* actions taken here rather than just wedging
* name_spec into setlocale() and hoping.
*/
if ( !(rec->locale_hint) ) {
/*
* Leave current locale alone.
*/
}
else if ( strcmp( rec->locale_hint, "" ) ) {
/*
* Leave current locale alone. Note that "" into
* setlocale says to go with default vs leave it alone.
*/
}
else {
char *tptr1, *tptr2;
tptr1 = xpstrdup( rec->locale_hint );
tptr2 = strchr( tptr1, ';' );
if (tptr2) *tptr2 = '\0';
setlocale( LC_ALL, tptr1 );
XFree( tptr1 );
}
/*
* Set XAUTHORITY env var if needed.
*/
if ((rec->cookie_cnt) && (rec->auth_filename) && (rec->auth_file)) {
envstr = Xmalloc( strlen(rec->auth_filename) + 12 );
sprintf( envstr, "XAUTHORITY=%s", rec->auth_filename );
putenv( envstr );
}
/*
* Start the child for real.
*/
(void) execvp(rec->pdm_exec_argvs[0], rec->pdm_exec_argvs);
(void) fprintf (stderr, PDMD_MSG_10, g.prog_name, rec->pdm_exec_argvs[0]);
/*
* tomg - need to deal with failed child start.
*/
exit(PDM_EXIT_ERROR);
}
else {
/*
* Parent process.
*/
/*
* Close the write end of the pipe - only the child needs it.
*/
close(rec->message_pipe[1]);
rec->message_pipe[1] = -1;
}
}
/********************************************************************
*
* Figure out which pdm executable to later fork/exec.
*/
void mgr_fetch_pdm( XpPdmServiceRec *rec )
{
char tstr[1024], *tptr1, *tptr2, *tptr3;
int firstTime;
long now;
Display *tdpy;
int lxerrno;
if ( g.override_pdm ) {
/*
* Override all defaults and other possible settings.
*/
tptr1 = xpstrdup(g.override_pdm);
}
else {
/*
* See if the print context says which pdm to run.
*/
g.xerrno = 0; /* Error Handler */
lxerrno = 0; /* XIO Error Handler */
if ( setjmp( xio_quickie_jmp_buf ) == 0 ) {
XSetIOErrorHandler( xio_quickie_handler );
if ( rec->seldpy_as_printdpy ) {
tptr1 = XpGetOneAttribute( rec->selection_display,
rec->print_context,
XPPrinterAttr, "dt-pdm-command" );
}
else {
tdpy = XOpenDisplay( rec->print_display_str );
if (tdpy) {
tptr1 = XpGetOneAttribute( tdpy,
rec->print_context,
XPPrinterAttr, "dt-pdm-command" );
XCloseDisplay( tdpy );
}
}
XSetIOErrorHandler( NULL );
}
else {
lxerrno = 1;
XSetIOErrorHandler( NULL );
}
/*
* See if we got a useful pdm exec string. Use
* default if not.
*/
if ( g.xerrno || lxerrno ) {
rec->pdm_exec_errorcode = g.pdm_start_error;
return;
}
else if (!tptr1) {
tptr1 = xpstrdup(g.default_pdm);
}
else if (!tptr1[0]) {
tptr1 = xpstrdup(g.default_pdm);
}
}
/*
* Convert pdm-command into argv[] style array.
*
* Note: this parsing code does NOT respect shell
* quotes and other items. --tomg
*/
rec->pdm_exec_argvs = (char **) NULL;
tptr2 = tptr1; /* retain orig pointer for freeing */
firstTime = 1;
while (1) {
if (firstTime) {
tptr3 = xpstrtok( tptr2, " \n\t" );
firstTime = 0;
if (!tptr3) {
/*
* There were NO useful tokens to begin with, so
* we'll have to fall back on the default.
*/
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup( g.default_pdm ));
break;
}
}
else {
tptr3 = xpstrtok( (char *) NULL, " \n\t" );
}
if (tptr3) {
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup( tptr3 ) );
}
else {
break;
}
}
Xfree(tptr1);
/*
* Add standard command line parameters.
*/
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup("-display") );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup(rec->video_display_str) );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup("-window") );
sprintf( tstr, "0x%lx", rec->video_window );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup(tstr) );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup("-pdisplay") );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup(rec->print_display_str) );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup("-pwindow") );
sprintf( tstr, "0x%lx", rec->print_window );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup(tstr) );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup("-pcontext") );
sprintf( tstr, "0x%lx", rec->print_context );
xp_add_argv( &(rec->pdm_exec_argvs), xpstrdup(tstr) );
}
/********************************************************************
*
* Once a pdm has been lauched, reply to the SelectionRequest so that
* the requestors knows.
*/
void mgr_launch_reply( XpPdmServiceRec *rec )
{
XEvent reply;
Status status;
FILE *errlog;
long now;
char *eec;
Atom tmpa;
XChangeProperty( rec->selection_display, rec->requestor,
rec->prop_atom, XA_ATOM,
32, PropModeReplace,
(unsigned char *) &(rec->pdm_exec_errorcode),
1 );
/*
* Write optional error message to log file.
*
* Expected errors like PXAUTH and VXAUTH should not have
* textual descriptions too - they're obvious as is. Only
* real nasty errors should have a message for the log file.
*/
if ((rec->pdm_exec_errormessage) && (g.log_file)) {
if ((errlog = fopen(g.log_file, "a+")) != NULL) {
now = time((time_t)0);
if ( rec->pdm_exec_errorcode == g.pdm_start_ok )
eec = "PDM_START_OK";
else if ( rec->pdm_exec_errorcode == g.pdm_start_vxauth )
eec = "PDM_START_VXAUTH";
else if ( rec->pdm_exec_errorcode == g.pdm_start_pxauth )
eec = "PDM_START_PXAUTH";
else if ( rec->pdm_exec_errorcode == g.pdm_start_error )
eec = "PDM_START_ERROR";
else
eec = "unknown error";
fprintf( errlog, PDMD_MSG_11, g.prog_name, ctime(&now),
rec->pdm_exec_errormessage,
eec,
rec->pdm_exec_argvs[0],
rec->print_display_str,
rec->video_display_str );
fclose(errlog);
}
}
/*
* Send a SelectionNotify event, which will conclude the
* selection handshake.
*/
reply.xselection.type = SelectionNotify;
reply.xselection.requestor = rec->requestor;
reply.xselection.selection = rec->selection;
reply.xselection.target = g.pdm_start;
reply.xselection.property = rec->prop_atom;
reply.xselection.time = rec->time;
status = XSendEvent( rec->selection_display, rec->requestor, True, 0, &reply );
}
/********************************************************************
*
* Send the final OK/CANCEL ClientMessage.
*/
void mgr_shutdown_reply( XpPdmServiceRec *rec )
{
XEvent cme;
Display *pdpy;
char *mess;
int inc;
char buf[2048];
int lxerrno;
/*
* Setup client message event.
*/
cme.xclient.type = ClientMessage;
cme.xclient.window = rec->print_window;
cme.xclient.message_type = g.pdm_reply;
cme.xclient.format = 32;
/*
* Look at the current exit code. Let 'mess' be both a message
* string, and a string we would XInternAtom on if we find out
* that the "Print" X-Server is differnent than the "Selection"
* X-Server. Up till now, we've been using atom constants
* generated via the Selection X-Server.
*/
switch (rec->exit_code) {
case PDM_EXIT_OK:
cme.xclient.data.l[0] = (long) g.pdm_exit_ok;
mess = "PDM_EXIT_OK";
break;
case PDM_EXIT_CANCEL:
cme.xclient.data.l[0] = (long) g.pdm_exit_cancel;
mess = "PDM_EXIT_CANCEL";
break;
case PDM_EXIT_VXAUTH:
cme.xclient.data.l[0] = (long) g.pdm_exit_vxauth;
mess = "PDM_EXIT_VXAUTH";
break;
case PDM_EXIT_PXAUTH:
cme.xclient.data.l[0] = (long) g.pdm_exit_pxauth;
mess = "PDM_EXIT_PXAUTH";
break;
case PDM_EXIT_ERROR:
default:
cme.xclient.data.l[0] = (long) g.pdm_exit_error;
mess = "PDM_EXIT_ERROR";
break;
}
/*
* Try to send ClientMessage that will carry the reply.
*/
g.xerrno = 0; /* Error Handler */
lxerrno = 0; /* XIO Error Handler */
if ( setjmp( xio_quickie_jmp_buf ) == 0 ) {
XSetIOErrorHandler( xio_quickie_handler );
if ( rec->seldpy_as_printdpy ) {
/*
* Since the "Print" X-Server is the same as the
* "Selection" X-Server, against which we have an
* active display connection and atom values, go
* ahead and use it.
*/
XSendEvent( rec->selection_display, rec->print_window, False, 0L, &cme );
}
else {
pdpy = XOpenDisplay( rec->print_display_str );
if (pdpy) {
/*
* The "Print" X-Server is different than the
* "Selection" X-Server. Map values over.
*/
cme.xclient.message_type =
XInternAtom( pdpy, "PDM_REPLY", False );
cme.xclient.data.l[0] =
(long) XInternAtom( pdpy, mess, False );
XSendEvent( pdpy, rec->print_window, False, 0L, &cme );
XCloseDisplay( pdpy );
}
}
XSetIOErrorHandler( NULL );
}
else {
lxerrno = 1;
XSetIOErrorHandler( NULL );
}
if ( g.xerrno || lxerrno ) {
/*
* Problem - we can't get back to the requestor.
*
* This is really a PANIC situation, since the requesting
* client will hang around forever, waiting for this
* final reply. The best we can do it log an error for
* the sys admin, and hope they can notice.
*/
if (g.xerrno)
sprintf( buf, PDMD_MSG_12, g.prog_name, mess );
else
sprintf( buf, PDMD_MSG_13, g.prog_name, mess );
rec->message_string2 = Xmalloc( strlen( buf ) + 1 );
strcpy( rec->message_string2 , buf );
}
}
Bool has_exec_token( XpPdmServiceRec *rec )
{
char *s1, *s2, *s3;
int i1;
s1 = rec->message_string;
if (s1) {
/*
* Look for "PDM_START_*" tokens burried in the
* stderr output of the PDM. If found, react as
* required, and eliminate the token from the
* output.
*/
if ( s2 = strstr( s1, "PDM_START_OK") ) {
rec->pdm_exec_errorcode = g.pdm_start_ok;
i1 = 12;
}
else if ( s2 = strstr( s1, "PDM_START_VXAUTH") ) {
rec->pdm_exec_errorcode = g.pdm_start_vxauth;
i1 = 16;
}
else if ( s2 = strstr( s1, "PDM_START_PXAUTH") ) {
rec->pdm_exec_errorcode = g.pdm_start_pxauth;
i1 = 16;
}
else if ( s2 = strstr( s1, "PDM_START_ERROR") ) {
rec->pdm_exec_errorcode = g.pdm_start_error;
i1 = 15;
}
if (s2) {
/*
* Compress out the token.
*/
s3 = s2 + i1;
while ( *s2++ = *s3++ );
if ( strlen(s1) == 0 ) {
/*
* The token was it - free the buffer now so that
* it appears no stderr was ever generated.
*/
Xfree( rec->message_string );
rec->message_string = (char *) NULL;
}
else if ((strlen(s1) == 1) && (s1[0] == '\n')) {
/*
* All but a \n remains - free the buffer.
*/
Xfree( rec->message_string );
rec->message_string = (char *) NULL;
}
return( True );
}
else {
return( False );
}
}
else {
return( False );
}
}
/********************************************************************
*
* Search through all the child tracking records and see if
* any can be shutdown.
*/
void mgr_shutdown_scan()
{
int i;
long now;
FILE *errlog;
static int errlog_problem_notice = 0;
Bool shutdown_time;
for ( i = 0; i < g.serviceRecNum; i++ ) {
shutdown_time = False;
if ( (g.serviceRecs[i]->do_launch_reply) &&
(has_exec_token(g.serviceRecs[i]) ) ) {
/*
* Need to send our PDM_START fork/exec reply still.
*
* Note that if we send pdm_start_ok, we'll need to send
* a pdm_exit_* code later. If we send pdm_start_vxauth,
* pdm_start_pxauth, or pdm_start_error, it indicates to
* the client a fatal condition, and they will NOT receive
* any more messages, including any pdm_exit_* codes. The
* dtpdmd will hang around however, if for no other reason
* than to capture stderr and log it when the child finally
* goes down.
*/
mgr_launch_reply( g.serviceRecs[i] );
g.serviceRecs[i]->do_launch_reply = False; /* it has been done */
}
if ( (g.serviceRecs[i]->pdm_exec_errorcode == g.pdm_start_ok) &&
(g.serviceRecs[i]->exit_received) &&
(g.serviceRecs[i]->message_pipe[0] == -1) ) {
/*
* Child is down, and since we sent a pdm_start_ok,
* we need to send a PDM_REPLY pdm_exit_* code too.
*/
mgr_shutdown_reply( g.serviceRecs[i] );
}
if ( (g.serviceRecs[i]->exit_received) &&
(g.serviceRecs[i]->message_pipe[0] == -1) ) {
/*
* Child is down. Log any final error messages
* from the child, and from the dtpdmd on behalf of
* the child.
*/
if ( ((g.serviceRecs[i]->message_string) ||
(g.serviceRecs[i]->message_string2)) && (g.log_file) ) {
if ((errlog = fopen(g.log_file, "a+")) != NULL) {
now = time((time_t)0);
fprintf (errlog, PDMD_MSG_14, g.prog_name, ctime(&now),
g.serviceRecs[i]->pdm_exec_argvs[0],
g.serviceRecs[i]->print_display_str,
g.serviceRecs[i]->video_display_str,
g.serviceRecs[i]->exit_code,
g.serviceRecs[i]->message_string);
if (g.serviceRecs[i]->message_string2) {
fprintf (errlog, PDMD_MSG_15, g.serviceRecs[i]->message_string2);
}
fprintf (errlog, "\n");
fclose(errlog);
}
else if (!errlog_problem_notice) {
fprintf (stderr, PDMD_MSG_16, g.prog_name, g.log_file );
fflush (stderr);
errlog_problem_notice = 1;
}
}
/*
* The child is done and can be cleaned up.
*/
delete_rec( g.serviceRecs[i] );
}
}
}

129
cde/programs/dtpdmd/nlmsg.c Normal file
View File

@@ -0,0 +1,129 @@
/* $XConsortium: nlmsg.c /main/1 1996/10/30 19:10:20 cde-hp $ */
/*
* dtpdmd/nlmsg.c
*/
/*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#ifdef I18N_MSG
#include <nl_types.h>
#if !defined(NL_CAT_LOCALE)
#define NL_CAT_LOCALE 0
#endif
#define DTPDMD_CAT_NAME "dtpdmd"
#endif /* I18N_MSG */
/*
* ------------------------------------------------------------------------
* Default message values
*/
/*** dtpdmd.c ***/
const char DtPdmdMsg_0001[] = "\
usage: %1$s [options]\n\
\n\
where [options] includes:\n\
-d <display> host:display[.screen] of X Print Server\n\
-a <alt selection> an alternate selection name (\"%2$s\" default)\n\
-p <default pdm> a default pdm to launch (\"%3$s\" default)\n\
-P <the pdm> the pdm to launch, overrides all others\n\
-s turn on security protocol\n\
-f <auth file> an initial set of authorization cookies\n\
-l <log file> a file for the logging of errors, etc";
const char DtPdmdMsg_0002[] = "%1$s: error, cannot open display %2$s\n";
const char DtPdmdMsg_0003[] = "%1$s: error, cannot acquire selection %2$s\n";
const char DtPdmdMsg_0004[] = "%s: error, cannot create Xt Signal Pipe\n";
/*** manager.c ***/
const char DtPdmdMsg_0005[] = "%s: error, unable to get SelectionRequest property\n";
const char DtPdmdMsg_0006[] = "%s: error, invalid format for SelectionRequest property\n";
const char DtPdmdMsg_0007[] = "%s: error, XmbTextPropertyToTestList failed on SelectionRequest property\n";
const char DtPdmdMsg_0008[] = "%s: error, unable to create message pipe\n";
const char DtPdmdMsg_0009[] = "%s: error, unable to fork\n";
const char DtPdmdMsg_0010[] = "%1$s: error, cannot execute \"%2$s\" \n";
const char DtPdmdMsg_0011[] = "\
%1$s: exec message logged at %2$s\n\
exec error message = \"%3$s\"\n\
exec error code = %4$s\n\
pdm = \"%5$s\"\n\
-display = \"%6$s\"\n\
-vdisplay = \"%7$s\" \n";
const char DtPdmdMsg_0012[] = "\
%1$s: error, unable to send the final %2$s\n\
message to the requesting client on behalf of\n\
the PDM because of a generated X error\n";
const char DtPdmdMsg_0013[] = "\
%1$s: error, unable to send the final %2$s\n\
message to the requesting client on behalf of\n\
the PDM because of an XIO error\n";
const char DtPdmdMsg_0014[] = "\
%1$s: pdm message logged at %2$s\n\
pdm = \"%3$s\"\n\
-display = \"%4$s\"\n\
-vdisplay = \"%5$s\"\n\
exit code = \"%6$d\"\n\
stderr = \"%7$s\" \n";
const char DtPdmdMsg_0015[] = "\
attached pdmd error= \n\"%s\" \n";
const char DtPdmdMsg_0016[] = "%1$s: error, cannot open log file \"%2$s\". Turning off stderr message logging\n";
#ifdef I18N_MSG
/*
* ------------------------------------------------------------------------
* Name: DtPdmdGetMessage
*
* Parameters:
*
* int set - The message catalog set number.
*
* int n - The message number.
*
* char *s - The default message if the message is not
* retrieved from a message catalog.
*
* Returns: the string for set 'set' and number 'n'.
*/
const char *
DtPdmdGetMessage(
int set,
int n,
char * s)
{
char *msg;
nl_catd catopen();
char *catgets();
static int first = 1;
static nl_catd nlmsg_fd;
if(set == -1 || n == -1)
return s;
if(first)
{
first = 0;
nlmsg_fd = catopen(DTPDMD_CAT_NAME, NL_CAT_LOCALE);
}
msg=catgets(nlmsg_fd,set,n,s);
return (msg);
}
#endif /* I18N_MSG */

View File

@@ -0,0 +1,78 @@
/* $XConsortium: nlmsg.h /main/1 1996/10/30 19:10:36 cde-hp $ */
/*
* dtpdmd/nlmsg.h
*/
/*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#ifndef _PdmdMsgs_h
#define _PdmdMsgs_h
#ifdef I18N_MSG
#include <nl_types.h>
#define DTPDMD_GETMESSAGE(set, number, string) \
DtPdmdGetMessage(set, number, string)
#else /* I18N_MSG */
#define DTPDMD_GETMESSAGE(set, number, string) (string)
#endif /* I18N_MSG */
/*** const causes the HP compiler to complain. Remove reference until ***
*** the build and integration people can figure out how to get this to ***
*** work. ***/
/* #define CONST const */
#define CONST
#define PDMD_MSG_1 DTPDMD_GETMESSAGE(1, 1, DtPdmdMsg_0001)
#define PDMD_MSG_2 DTPDMD_GETMESSAGE(1, 2, DtPdmdMsg_0002)
#define PDMD_MSG_3 DTPDMD_GETMESSAGE(1, 3, DtPdmdMsg_0003)
#define PDMD_MSG_4 DTPDMD_GETMESSAGE(1, 4, DtPdmdMsg_0004)
#define PDMD_MSG_5 DTPDMD_GETMESSAGE(1, 5, DtPdmdMsg_0005)
#define PDMD_MSG_6 DTPDMD_GETMESSAGE(1, 6, DtPdmdMsg_0006)
#define PDMD_MSG_7 DTPDMD_GETMESSAGE(1, 7, DtPdmdMsg_0007)
#define PDMD_MSG_8 DTPDMD_GETMESSAGE(1, 8, DtPdmdMsg_0008)
#define PDMD_MSG_9 DTPDMD_GETMESSAGE(1, 9, DtPdmdMsg_0009)
#define PDMD_MSG_10 DTPDMD_GETMESSAGE(1, 10, DtPdmdMsg_0010)
#define PDMD_MSG_11 DTPDMD_GETMESSAGE(1, 11, DtPdmdMsg_0011)
#define PDMD_MSG_12 DTPDMD_GETMESSAGE(1, 12, DtPdmdMsg_0012)
#define PDMD_MSG_13 DTPDMD_GETMESSAGE(1, 13, DtPdmdMsg_0013)
#define PDMD_MSG_14 DTPDMD_GETMESSAGE(1, 14, DtPdmdMsg_0014)
#define PDMD_MSG_15 DTPDMD_GETMESSAGE(1, 15, DtPdmdMsg_0015)
#define PDMD_MSG_16 DTPDMD_GETMESSAGE(1, 16, DtPdmdMsg_0016)
extern CONST char DtPdmdMsg_0001[];
extern CONST char DtPdmdMsg_0002[];
extern CONST char DtPdmdMsg_0003[];
extern CONST char DtPdmdMsg_0004[];
extern CONST char DtPdmdMsg_0005[];
extern CONST char DtPdmdMsg_0006[];
extern CONST char DtPdmdMsg_0007[];
extern CONST char DtPdmdMsg_0008[];
extern CONST char DtPdmdMsg_0009[];
extern CONST char DtPdmdMsg_0010[];
extern CONST char DtPdmdMsg_0011[];
extern CONST char DtPdmdMsg_0012[];
extern CONST char DtPdmdMsg_0013[];
extern CONST char DtPdmdMsg_0014[];
extern CONST char DtPdmdMsg_0015[];
extern CONST char DtPdmdMsg_0016[];
#ifdef I18N_MSG
/* Message IDs */
extern const char * DtPdmGetMessage(
int set,
int n,
const char * s);
#endif /* I18N_MSG */
#endif /* _PdmdMsgs_h */

View File

@@ -0,0 +1,194 @@
/******************************************************************************
******************************************************************************
**
** File: records.c
** RCS: $XConsortium: records.c /main/4 1996/05/28 13:34:16 cde-hp $
**
** Description:
**
** (c) Copyright 1995, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define RECORDS_DOT_C
#include "dtpdmdP.h"
/********************************************************************
*
* Routines to BLOCK and UNBLOCK the signal SIGCLD.
*
* Use whenever modifying the array of client tracking
* records (critical section). If a SIGCLD happens,
* dtpdmd.c:handle_SIGCLD() will be called, and it must
* be able to work on a stable set of client tracking
* records.
*/
static void block_SIGCLD( void )
{
sigset_t newset;
int rtn;
sigemptyset( &newset );
sigaddset( &newset, SIGCLD );
rtn = sigprocmask( SIG_BLOCK, &newset, (sigset_t *) NULL );
}
static void unblock_SIGCLD( void )
{
sigset_t newset;
int rtn;
sigemptyset( &newset );
sigaddset( &newset, SIGCLD );
rtn = sigprocmask( SIG_UNBLOCK, &newset, (sigset_t *) NULL );
}
/********************************************************************
*
* Try to find a service record based on ID. Optionally create a
* new service record if one is not found.
*/
XpPdmServiceRec *find_rec( Window requestor )
{
int i;
XpPdmServiceRec *r;
if (!requestor)
return( (XpPdmServiceRec *) NULL );
/*
* See if the record already exists.
*/
for ( i=0; i < g.serviceRecNum; i++ ) {
if ( g.serviceRecs[i]->requestor == requestor )
return( g.serviceRecs[i] );
}
/*
* Will need to add - see if we need more room in the child
* tracking record array.
*/
block_SIGCLD();
if ( g.serviceRecNum + 1 > g.maxServiceRecNum ) {
g.maxServiceRecNum += 5;
if ( g.maxServiceRecNum == 5 ) {
g.serviceRecs =
(XpPdmServiceRec **) Xmalloc( sizeof(XpPdmServiceRec *) *
g.maxServiceRecNum );
}
else {
g.serviceRecs =
(XpPdmServiceRec **) Xrealloc( (char *) g.serviceRecs,
sizeof(XpPdmServiceRec *) *
g.maxServiceRecNum );
}
}
/*
* Create a new child tracking record and add to array.
*/
r = (XpPdmServiceRec *) Xmalloc( sizeof(XpPdmServiceRec) );
g.serviceRecs[g.serviceRecNum] = r;
memset( (void *) r, NULL, sizeof(XpPdmServiceRec) ); /* cheat NULLing */
r->mgr_flag = False;
r->mbox_flag = False;
r->message_pipe[0] = -1;
r->message_pipe[1] = -1;
g.serviceRecNum++;
unblock_SIGCLD();
return( r );
}
/********************************************************************
*
* Try to find a service record based on previously assigned
* mailbox window ID.
*/
XpPdmServiceRec *find_rec_by_mbox_win( Window window )
{
int i;
XpPdmServiceRec *r;
if (!window)
return( (XpPdmServiceRec *) NULL );
/*
* See if the record already exists.
*/
for ( i=0; i < g.serviceRecNum; i++ ) {
if ( g.serviceRecs[i]->mbox_window == window )
return( g.serviceRecs[i] );
}
return( (XpPdmServiceRec *) NULL );
}
/********************************************************************
*
* Delete the specified service record from global memory.
*/
void delete_rec( XpPdmServiceRec *rec )
{
int i,j;
block_SIGCLD();
for ( i=0; i< g.serviceRecNum; i++ ) {
if ( g.serviceRecs[i] == rec ) {
/*
* Delete memory for current rec
*/
if (rec->mbox_window)
XDestroyWindow( rec->selection_display, rec->mbox_window );
unlink( rec->auth_filename );
Xfree( g.serviceRecs[i]->video_display_str );
Xfree( g.serviceRecs[i]->print_display_str );
Xfree( g.serviceRecs[i]->locale_hint );
for ( j = 0; g.serviceRecs[i]->pdm_exec_argvs[j]; j++ )
Xfree( (char *) g.serviceRecs[i]->pdm_exec_argvs[j] );
Xfree( (char *) g.serviceRecs[i]->pdm_exec_argvs );
Xfree( g.serviceRecs[i]->pdm_exec_errormessage );
Xfree( g.serviceRecs[i]->message_string );
Xfree( g.serviceRecs[i]->message_string2 );
Xfree( g.serviceRecs[i]->in_buf );
for ( j=i; j < g.serviceRecs[i]->cookie_cnt; j++ )
Xfree( (char *) g.serviceRecs[i]->cookies[j] );
Xfree( (char *) g.serviceRecs[i]->cookies );
Xfree( (char *) g.serviceRecs[i] );
/*
* Compress list around defunct entry
*/
for ( j=i; j < g.serviceRecNum-1; j++ ) {
g.serviceRecs[j] = g.serviceRecs[j+1];
}
}
}
g.serviceRecNum--;
unblock_SIGCLD();
}

View File

@@ -0,0 +1,94 @@
/******************************************************************************
******************************************************************************
**
** File: setup.c
** RCS: $TOG: setup.c /main/4 1997/06/18 17:33:23 samborn $
**
** Description:
**
** (c) Copyright 1995, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define SETUP_DOT_C
#include "dtpdmdP.h"
/*********************************************************************
*
* Setup PDM_MANAGER selection and TYPE atoms
*/
Bool _PdmMgrSetup( Display *sel_display, Window sel_window, Bool security_flag )
{
enum { XA_PDM_START, XA_PDM_REPLY, XA_TARGETS, XA_TIMESTAMP,
XA_MULTIPLE, XA_PDM_START_OK, XA_PDM_START_VXAUTH,
XA_PDM_START_PXAUTH, XA_PDM_START_ERROR, XA_PDM_EXIT_OK,
XA_PDM_EXIT_CANCEL, XA_PDM_EXIT_VXAUTH, XA_PDM_EXIT_PXAUTH,
XA_PDM_EXIT_ERROR, XA_PDM_MBOX, XA_PDM_MAIL, NUM_ATOMS };
static char *atom_names[] = {
"PDM_START", "PDM_REPLY", "TARGETS", "TIMESTAMP",
"MULTIPLE", "PDM_START_OK", "PDM_START_VXAUTH",
"PDM_START_PXAUTH", "PDM_START_ERROR", "PDM_EXIT_OK",
"PDM_EXIT_CANCEL", "PDM_EXIT_VXAUTH", "PDM_EXIT_PXAUTH",
"PDM_EXIT_ERROR", "PDM_MBOX", "PDM_MAIL" };
int i;
Atom atoms[XtNumber(atom_names)];
/*
* Create PDM_MANAGER atoms.
*/
XInternAtoms( sel_display, atom_names, XtNumber(atom_names), False, atoms );
g.pdm_selection = XInternAtom( sel_display, g.alt_selection, False );
g.pdm_start = atoms[XA_PDM_START];
g.pdm_reply = atoms[XA_PDM_REPLY];
g.pdm_targets = atoms[XA_TARGETS];
g.pdm_timestamp = atoms[XA_TIMESTAMP];
g.pdm_multiple = atoms[XA_MULTIPLE];
g.pdm_start_ok = atoms[XA_PDM_START_OK];
g.pdm_start_vxauth = atoms[XA_PDM_START_VXAUTH];
g.pdm_start_pxauth = atoms[XA_PDM_START_PXAUTH];
g.pdm_start_error = atoms[XA_PDM_START_ERROR];
g.pdm_exit_ok = atoms[XA_PDM_EXIT_OK];
g.pdm_exit_cancel = atoms[XA_PDM_EXIT_CANCEL];
g.pdm_exit_vxauth = atoms[XA_PDM_EXIT_VXAUTH];
g.pdm_exit_pxauth = atoms[XA_PDM_EXIT_PXAUTH];
g.pdm_exit_error = atoms[XA_PDM_EXIT_ERROR];
if (security_flag){
g.pdm_mbox = atoms[XA_PDM_MBOX];
g.pdm_mail = atoms[XA_PDM_MAIL];
}
else {
g.pdm_mbox = (Atom) 0;
g.pdm_mail = (Atom) 0;
}
if ( XGetSelectionOwner(sel_display, g.pdm_selection) != None ) {
/*
* Someone else already owns the selection.
*/
return( /* cannot become owner */ False );
}
else {
/*
* Claim ownership of the selection.
*/
i=0;
while ((XGetSelectionOwner(sel_display, g.pdm_selection)!=sel_window)) {
if ( i++ > 100 )
return( /* cannot become owner */ False );
XSetSelectionOwner( sel_display, g.pdm_selection, sel_window,
CurrentTime );
}
}
return( /* became owner */ True );
}

252
cde/programs/dtpdmd/util.c Normal file
View File

@@ -0,0 +1,252 @@
/******************************************************************************
******************************************************************************
**
** File: util.c
** RCS: $XConsortium: util.c /main/3 1996/10/30 11:16:26 drk $
**
** Description: Utility code for the dtpdmd
**
** (c) Copyright 1995, 1996, Hewlett-Packard Company, all rights reserved.
**
******************************************************************************
*****************************************************************************/
#define UTIL_DOT_C
#include "dtpdmdP.h"
#include <setjmp.h>
#include <unistd.h>
jmp_buf xio_quickie_jmp_buf;
/******************************************************************************
*
* Misc utility routines.
*/
int xio_quickie_handler( Display *dpy )
{
longjmp( xio_quickie_jmp_buf, 1 );
}
/***************************************
*
* str_dup using Xmalloc
*/
char *xpstrdup(char * str)
{
int len;
char *newstr;
len = strlen(str) + 1;
newstr = (char *) Xmalloc( len );
memcpy( newstr, str, len );
return( newstr );
}
/***************************************
*
* Multi-byte capable version of strspn(s1, s2).
* Returns the span of characters in s1 contained in s2.
* Only s1 can be multibyte.
*/
int
xpstrspn(
char *s1,
char *s2 )
{
#ifdef NLS16
wchar_t s1char, s2char;
int s1len, s2len;
int i;
int count;
char * ptr;
Boolean match;
/* A Null string has no spans */
if (s1 == NULL)
return(0);
count = 0;
while (*s1)
{
/* Extract the next character from s1; may be multibyte */
if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
return(0);
s1 += s1len;
/*
* Compare this character against all the chars in s2. Keep
* working through s1, until a character is found in s1 which
* is not contained in s2.
*/
ptr = s2;
match = False;
while (*ptr)
{
/* Extract the next character from s2; cannot be multibyte */
s2char = *ptr++;
/* If a match is found, keep processing s1 */
if (s1char == s2char)
{
match = True;
count += s1len;
break;
}
}
/*
* If we made it here because all of s2 was searched, and a match
* was not found against s1, then we are done.
*/
if (!match)
return(count);
}
return(count);
#else
return(strspn(s1, s2));
#endif /* NLS16 */
}
/***************************************
*
* Multi-byte capable version of strcspn(s1, s2).
* Returns the span of characters in s1 not contained in s2.
* Only s1 can be multibyte.
*/
int
xpstrcspn(
char *s1,
char *s2 )
{
#ifdef NLS16
wchar_t s1char, s2char;
int s1len, s2len;
int i;
int count;
char * ptr;
/* An empty string has no spans */
if (s1 == NULL)
return(0);
count = 0;
while (*s1)
{
/* Extract the next character from s1; may be multibyte */
if ((s1len = mbtowc(&s1char, s1, MB_CUR_MAX)) < 0)
return(0);
s1 += s1len;
/*
* Compare this character against all the chars in s2. Keep
* working through s1, until a character is found in s1 which
* is contained in s2.
*/
ptr = s2;
while (*ptr)
{
/* Extract the next character from s2; cannot be multibyte */
s2char = *ptr++;
/* If a match occurs, then we are done */
if (s1char == s2char)
return(count);
}
/*
* If we've made it here, then we searched all of s2, and none of
* its components matched s1; continue with the next character
* in s1.
*/
count += s1len;
}
return(count);
#else
return(strcspn(s1, s2));
#endif /* NLS16 */
}
/***************************************
*
* Multi-byte capable version of strtok(s1, s2).
* Returns a pointer to the span of characters in s1 terminated by
* one of the characters in s2. Only s1 can be multibyte.
*/
char *
xpstrtok(
char *s1,
char *s2 )
{
#ifdef NLS16
static char * ptr = NULL;
char * return_ptr;
int len;
int offset;
/*
* If this is the first call, save the string pointer, and bypass
* any leading separators.
*/
if (s1)
ptr = s1 + xpstrspn(s1, s2);
/* A Null string pointer has no tokens */
if (ptr == NULL)
return(NULL);
/* Find out where the first terminator is */
if ((len = xpstrcspn(ptr, s2)) <= 0)
{
/* No tokens left */
return(NULL);
}
/* Keep track of where the token started */
return_ptr = ptr;
/* Null out the terminator; we need to know how many bytes are
* occupied by the terminator, so that we can skip over it to
* the next character.
*/
offset = mblen(ptr + len, MB_CUR_MAX);
*(ptr + len) = '\0';
ptr += (len + offset);
/*
* In preparation for the next pass, skip any other occurrances of
* the terminator characters which were joined with the terminator
* we first encountered.
*/
len = xpstrspn(ptr, s2);
ptr += len;
return(return_ptr);
#else
return(strtok(s1, s2));
#endif /* NLS16 */
}
void xp_add_argv( char ***argv, char *str )
{
int i;
if ( *argv ) {
for ( i = 0; (*argv)[i]; i++ );
*argv = (char **) Xrealloc( (char *) *argv, sizeof(char *) * (i + 2) );
}
else {
i = 0;
*argv = (char **) Xmalloc( sizeof(char *) * 2 );
}
(*argv)[i] = str;
(*argv)[i+1] = (char *) NULL;
}