2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: dtpdmd.c /main/9 1996/10/30 19:10:08 cde-hp $ */
25 /******************************************************************************
26 ******************************************************************************
30 ** Description: main file for the implementation of the dtpdmd.
32 ** (c) Copyright 1995, 1996 Hewlett-Packard Company, all rights reserved.
34 ******************************************************************************
35 *****************************************************************************/
37 /******************************************************************************
41 * Other than setup, one event loop runs the show.
45 * -> means XtAppNextEvent breaks out with an event, and a
46 * case statement figures out where the event should go.
48 * => means XtAppNextEvent dispatches the handler for
55 * o mgr_initialize } mgr_launch_reply and delete_rec
56 * o mgr_fetch_pdm } called as soon as any errors occur
58 * o mgr_shutdown_scan }
62 * o mbox_initialize } request for
63 * o mbox_build } mailbox
65 * o mgr_shutdown_scan }
67 * o find_rec_by_mbox_win } receive incoming
68 * o mbox_receive } mail
69 * o mgr_shutdown_scan }
71 * => xtkick_proc (SIGCLD write to pipe handler causes this)
74 * => message_pipe_handler
75 * o child's stderr to pipe to malloc'ed buffer
79 * ~> SIGCLD (not really dispatched)
80 * o the handler notes which child, and exit status,
81 * then writes a byte to tickle the xtkick_proc
83 * Note the final usage of:
86 * o possibly pdm_launch_reply
87 * o possibly pdm_shutdown_reply
88 * o as appropriate, delete_rec
91 /******************************************************************************
93 * XIO Error Handling Strategy:
95 * XIO errors can occur from up to 3 display connections:
97 * o sel_dpy (aka prop_dpy)
98 * - always active. If this display connection goes down,
99 * then the dtpdmd will not be able to service any more
102 * o print_dpy (usually equal to sel_dpy)
103 * - within the pdm, on a per client basis, only active
104 * long enough to 1) fetch the dt-pdm-command attribute,
105 * and to 2) send the final ClientMessage with OK/Cancel.
107 * XIO strategy: wrap setjmp/longjmp around the usages
108 * of XOpenDisplay on print_dpy.
110 * XIO result: For case #1, set dt-pdm-command using
111 * built in defaults, thus ignoring XpGetOneAttribute.
113 * For case #2, the best that can be done is to log
114 * a message to the errorlog.
117 * - within the pdm, on a per client basis, only active
118 * long enough to 1) run a test connection to verify
121 * XIO strategy: wrap setjmp/longjmp around the one
122 * XOpenDisplay of video_dpy.
124 * XIO result: act as if authorization failed.
131 /********************************************************************
135 XpPdmGlobals g; /* global to all modules */
137 static int xtkick_pipeG[2]; /* global to this module */
139 /********************************************************************
143 static void pusage( char *prog_name )
145 fprintf(stderr, "\n");
146 fprintf( stderr, PDMD_MSG_1, prog_name, "PDM_MANAGER", DEFAULT_PDM_EXECUTABLE );
147 fprintf(stderr, "\n");
148 fprintf(stderr, "\n");
152 /******************************************************************************
154 * generic_error_handler
156 *****************************************************************************/
158 static int generic_error_handler( edpy, eevent )
162 g.xerrno = eevent->error_code;
163 g.xerrreq = eevent->request_code;
164 g.xerrmin = eevent->minor_code;
167 /******************************************************************************
171 *****************************************************************************/
173 #if defined(__aix) || defined(linux)
174 handle_SIGCLD(int sigNum)
183 * Query why the SIGCLD happened - a true termination or just
184 * a stopage. We only care about terminations.
186 pid = wait(&exitStatus);
190 * No specific child found with wait() - punt.
193 else if (!WIFSTOPPED(exitStatus)) {
195 * The SIGCLD was *not* the result of being stopped, so the child
196 * has indeed terminated. Look for its tracking record and mark
197 * accordingly for later shutdown.
199 for ( i = 0; i < g.serviceRecNum; i++ ) {
200 if ( g.serviceRecs[i]->pid == pid ) {
202 * Update tracking record.
204 g.serviceRecs[i]->exit_received = True;
205 g.serviceRecs[i]->exit_code = (int) WEXITSTATUS(exitStatus);
208 * Figure out who will deliver the "tickle" to XtAppNextEvent
209 * that will allow this child's status to be rediscovered
210 * so that a subsequent shutdown can be done.
212 * - if the child's message_pipe is still up,
213 * let its upcoming disconnection be the tickle.
215 * - if the child's message pipe is aleady down,
216 * then this is our last event related to the
217 * child, so tickle the "Xt Signal Pipe" we
220 * - if the Xt Signal Pipe is down, then we'll have
221 * to rely upon a 3rd party to deliver an event
222 * that will reactivate the Xt Main Loop.
224 if ( g.serviceRecs[i]->message_pipe[0] == -1 ) {
226 * Tickle our "Xt Signal Pipe".
228 write( xtkick_pipeG[1], (char *) "", 1 );
237 static void xtkick_proc( XtPointer w, int *source, XtInputId *id)
242 * Drain off the kicker bytes. Don't care how many, since
243 * we'll look at all client records.
245 if ( read(*source, buffer, sizeof (buffer) - 1) <= 0 ) {
246 close (*source); /* aka xtkick_pipeG[0] */
249 xtkick_pipeG[0] = -1; /* mark the pipe as invalid */
250 xtkick_pipeG[1] = -1;
254 * Scan client records and see who is ready to be
260 /******************************************************************************
272 Display *sel_display;
273 char *display_str, *auth_file;
276 struct sigaction svec;
280 g.maxServiceRecNum = 0;
282 g.prog_name = argv[0];
283 g.alt_selection = "PDM_MANAGER";
284 g.default_pdm = DEFAULT_PDM_EXECUTABLE;
285 g.override_pdm = (char *) NULL;
286 display_str = getenv("DISPLAY");
287 auth_file = (char *) NULL;
288 g.log_file = (char *) NULL;
289 security_flag = False;
292 * Parse command line arguments.
295 if (!strcmp (*argv, "-a")) {
296 g.alt_selection = *++argv;
298 else if (!strncmp (*argv, "-d", 2)) {
299 display_str = *++argv;
301 else if (!strcmp (*argv, "-p")) {
302 g.default_pdm = *++argv;
304 else if (!strcmp (*argv, "-P")) {
305 g.override_pdm = *++argv;
307 else if (!strcmp (*argv, "-s")) {
308 security_flag = True;
310 else if (!strcmp (*argv, "-f")) {
313 else if (!strcmp (*argv, "-l")) {
314 g.log_file = *++argv;
316 else if (!strncmp (*argv, "-h", 2)) {
317 pusage( g.prog_name );
322 * Ignore unknown options.
329 * Open a connection to the X-Server.
331 XtToolkitInitialize ();
332 g.context = XtCreateApplicationContext();
333 if ( (sel_display = XtOpenDisplay( g.context, display_str,
335 0, 0, &argc, argv )) == NULL ) {
336 fprintf( stderr , "\n" );
337 fprintf( stderr , PDMD_MSG_2, g.prog_name, display_str );
338 fprintf( stderr , "\n" );
339 fprintf( stderr , "\n" );
344 * Create master PDM window upon which selections
347 tscreen = DefaultScreen( sel_display );
349 sel_window = XCreateSimpleWindow( sel_display,
350 DefaultRootWindow( sel_display ),
352 BlackPixel(sel_display, tscreen),
353 WhitePixel(sel_display, tscreen) );
356 * Setup PDM_MANAGER selection
358 if ( ! _PdmMgrSetup( sel_display, sel_window, security_flag ) ) {
359 fprintf( stderr , "\n" );
360 fprintf( stderr , PDMD_MSG_3, g.prog_name , g.alt_selection );
361 fprintf( stderr , "\n" );
362 fprintf( stderr , "\n" );
368 * Install the "Xt Signal Pipe" Kicker handler.
370 if ( pipe(xtkick_pipeG) == -1 ) {
371 fprintf( stderr , "\n" );
372 fprintf( stderr , PDMD_MSG_4, g.prog_name );
373 fprintf( stderr , "\n" );
374 fprintf( stderr , "\n" );
377 xtid = XtAppAddInput( g.context, xtkick_pipeG[0],
378 (XtPointer) XtInputReadMask,
379 xtkick_proc, (XtPointer) NULL );
382 * Install signal handers.
384 sigemptyset(&svec.sa_mask);
386 svec.sa_handler = handle_SIGCLD;
387 (void) sigaction(SIGCHLD, &svec, (struct sigaction *) NULL);
390 * After this point, we need to trap all X and XIO errors.
392 * XIO trap handlers are installed at critical points, and
393 * the following generic X trap handler is used to set
396 XSetErrorHandler( generic_error_handler );
403 * XtAppNextEvent breaks for several reasons:
406 * XtAppNextEvent will dispatch for several reasons:
407 * - Alt input occurs on a pdm message pipe
408 * - Alt input occurs because a pdm message pipe was disconnected
409 * - Alt input occurs on our "Xt Signal Pipe" and we need to
410 * rediscover what happened as a result of that signal.
412 XtAppNextEvent( g.context, &report );
413 switch (report.type) {
416 if (report.xclient.message_type == g.pdm_mail) {
417 dispatch_mbox( &report );
420 /* ignore/pitch the event */
424 case SelectionRequest:
425 if (report.xselectionrequest.selection == g.pdm_selection) {
426 if (report.xselectionrequest.target == g.pdm_start) {
427 dispatch_mgr( &report );
429 else if (report.xselectionrequest.target==g.pdm_targets) {
430 dispatch_targets( &report );
432 else if (report.xselectionrequest.target==g.pdm_multiple){
433 dispatch_multiple( &report );
435 else if (report.xselectionrequest.target==g.pdm_timestamp){
436 dispatch_timestamp( &report );
438 else if (report.xselectionrequest.target==g.pdm_mbox) {
439 dispatch_mbox( &report );
442 dispatch_not_supported( &report );
446 /* ignore/pitch the event */
450 case SelectionNotify:
451 /* pitch the event */
456 * Someone is trying to tear away the selection.
457 * REACT by trying to reclaim it and logging an
467 * Use the opportunity to check for freshly finished
468 * PDMs, and close them out.
473 XDestroyWindow( sel_display, sel_window );
475 XtCloseDisplay( sel_display );