Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
40
cde/programs/dtpdmd/Imakefile
Normal file
40
cde/programs/dtpdmd/Imakefile
Normal 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)
|
||||
|
||||
243
cde/programs/dtpdmd/dispatch.c
Normal file
243
cde/programs/dtpdmd/dispatch.c
Normal 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 );
|
||||
}
|
||||
|
||||
456
cde/programs/dtpdmd/dtpdmd.c
Normal file
456
cde/programs/dtpdmd/dtpdmd.c
Normal 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);
|
||||
}
|
||||
|
||||
128
cde/programs/dtpdmd/dtpdmd.msg
Normal file
128
cde/programs/dtpdmd/dtpdmd.msg
Normal 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
|
||||
|
||||
223
cde/programs/dtpdmd/dtpdmdP.h
Normal file
223
cde/programs/dtpdmd/dtpdmdP.h
Normal 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();
|
||||
|
||||
212
cde/programs/dtpdmd/mailbox.c
Normal file
212
cde/programs/dtpdmd/mailbox.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
949
cde/programs/dtpdmd/manager.c
Normal file
949
cde/programs/dtpdmd/manager.c
Normal 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
129
cde/programs/dtpdmd/nlmsg.c
Normal 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 */
|
||||
78
cde/programs/dtpdmd/nlmsg.h
Normal file
78
cde/programs/dtpdmd/nlmsg.h
Normal 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 */
|
||||
194
cde/programs/dtpdmd/records.c
Normal file
194
cde/programs/dtpdmd/records.c
Normal 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();
|
||||
}
|
||||
|
||||
94
cde/programs/dtpdmd/setup.c
Normal file
94
cde/programs/dtpdmd/setup.c
Normal 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
252
cde/programs/dtpdmd/util.c
Normal 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user