1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264 |
- /******************************************************************************
- Copyright 1994, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Author: Ralph Mor, X Consortium
- ******************************************************************************/
- #include "smproxy.h"
- #include <unistd.h>
- #include <X11/Xmu/WinUtil.h>
- static XtAppContext appContext;
- static Display *disp;
- static Atom wmProtocolsAtom;
- static Atom wmSaveYourselfAtom;
- static Atom wmStateAtom;
- static Atom smClientIdAtom;
- static Atom wmClientLeaderAtom;
- static Bool debug = 0;
- static SmcConn proxy_smcConn;
- static XtInputId proxy_iceInputId;
- static char *proxy_clientId = NULL;
- WinInfo *win_head = NULL;
- static int proxy_count = 0;
- static int die_count = 0;
- static Bool ok_to_die = 0;
- static Bool caught_error = 0;
- static Bool sent_save_done = 0;
- static int Argc;
- static char **Argv;
- static Bool HasSaveYourself ( Window window );
- static Bool HasXSMPsupport ( Window window );
- static WinInfo * GetClientLeader ( WinInfo *winptr );
- static char * CheckFullyQuantifiedName ( char *name, int *newstring );
- static void FinishSaveYourself ( WinInfo *winInfo, Bool has_WM_SAVEYOURSELF );
- static void SaveYourselfCB ( SmcConn smcConn, SmPointer clientData, int saveType,
- Bool shutdown, int interactStyle, Bool fast );
- static void DieCB ( SmcConn smcConn, SmPointer clientData );
- static void SaveCompleteCB ( SmcConn smcConn, SmPointer clientData );
- static void ShutdownCancelledCB ( SmcConn smcConn, SmPointer clientData );
- static void ProcessIceMsgProc ( XtPointer client_data, int *source, XtInputId *id );
- static void NullIceErrorHandler ( IceConn iceConn, Bool swap,
- int offendingMinorOpCode,
- unsigned long offendingSequence,
- int errorClass, int severity, IcePointer values );
- static void ConnectClientToSM ( WinInfo *winInfo );
- static int MyErrorHandler ( Display *display, XErrorEvent *event );
- static Bool LookupWindow ( Window window, WinInfo **ptr_ret, WinInfo **prev_ptr_ret );
- static WinInfo * AddNewWindow ( Window window );
- static void RemoveWindow ( WinInfo *winptr );
- static void Got_WM_STATE ( WinInfo *winptr );
- static void HandleCreate ( XCreateWindowEvent *event );
- static void HandleDestroy ( XDestroyWindowEvent *event );
- static void HandleUpdate ( XPropertyEvent *event );
- static void ProxySaveYourselfPhase2CB ( SmcConn smcConn, SmPointer clientData );
- static void ProxySaveYourselfCB ( SmcConn smcConn, SmPointer clientData,
- int saveType, Bool shutdown, int interactStyle,
- Bool fast );
- static void ProxyDieCB ( SmcConn smcConn, SmPointer clientData );
- static void ProxySaveCompleteCB ( SmcConn smcConn, SmPointer clientData );
- static void ProxyShutdownCancelledCB ( SmcConn smcConn, SmPointer clientData );
- static Status ConnectProxyToSM ( char *previous_id );
- static void CheckForExistingWindows ( Window root );
- static Bool
- HasSaveYourself(Window window)
- {
- Atom *protocols;
- int numProtocols;
- int i, found;
- protocols = NULL;
- if (XGetWMProtocols (disp, window, &protocols, &numProtocols) != True)
- return (False);
- found = 0;
- if (protocols != NULL)
- {
- for (i = 0; i < numProtocols; i++)
- if (protocols[i] == wmSaveYourselfAtom)
- found = 1;
- XFree (protocols);
- }
- return (found);
- }
- static Bool
- HasXSMPsupport(Window window)
- {
- XTextProperty tp;
- Bool hasIt = 0;
- if (XGetTextProperty (disp, window, &tp, smClientIdAtom))
- {
- if (tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0)
- hasIt = 1;
- if (tp.value)
- XFree ((char *) tp.value);
- }
- return (hasIt);
- }
- static WinInfo *
- GetClientLeader(WinInfo *winptr)
- {
- Atom actual_type;
- int actual_format;
- unsigned long nitems, bytesafter;
- unsigned long *datap = NULL;
- WinInfo *leader_winptr = NULL;
- Bool failure = 0;
- if (XGetWindowProperty (disp, winptr->window, wmClientLeaderAtom,
- 0L, 1L, False, AnyPropertyType, &actual_type, &actual_format,
- &nitems, &bytesafter, (unsigned char **) &datap) == Success)
- {
- if (actual_type == XA_WINDOW && actual_format == 32 &&
- nitems == 1 && bytesafter == 0)
- {
- Window leader_win = *((Window *) datap);
- if (!LookupWindow (leader_win, &leader_winptr, NULL))
- failure = 1;
- }
- if (datap)
- XFree (datap);
- }
- if (failure)
- {
- /* The client leader was defined, but we couldn't find the window */
- return (NULL);
- }
- else if (leader_winptr)
- {
- /* We found the real client leader */
- return (leader_winptr);
- }
- else
- {
- /* There is no client leader defined, return this window */
- return (winptr);
- }
- }
- static char *
- CheckFullyQuantifiedName(char *name, int *newstring)
- {
- /*
- * Due to a bug in Xlib (for hpux in particular), some clients
- * will have a WM_CLIENT_MACHINE that is not fully quantified.
- * For example, we might get "excon" instead of "excon.x.org".
- * This really stinks. The best we can do is tag on our own
- * domain name.
- */
- if (strchr (name, '.') != NULL)
- {
- *newstring = 0;
- return (name);
- }
- else
- {
- char hostnamebuf[80];
- char *firstDot;
- gethostname (hostnamebuf, sizeof hostnamebuf);
- firstDot = strchr (hostnamebuf, '.');
- if (!firstDot)
- {
- *newstring = 0;
- return (name);
- }
- else
- {
- char *newptr;
- if (asprintf (&newptr, "%s.%s", name, firstDot + 1) == -1) {
- *newstring = 0;
- return NULL;
- }
- *newstring = 1;
- return (newptr);
- }
- }
- }
- static void
- FinishSaveYourself(WinInfo *winInfo, Bool has_WM_SAVEYOURSELF)
- {
- SmProp prop1, prop2, prop3, *props[3];
- SmPropValue prop1val, prop2val, prop3val;
- int i;
- if (!winInfo->got_first_save_yourself)
- {
- char userId[20], restartService[80];
- char *fullyQuantifiedName;
- int newstring;
- prop1.name = SmProgram;
- prop1.type = SmARRAY8;
- prop1.num_vals = 1;
- prop1.vals = &prop1val;
- prop1val.value = (SmPointer) winInfo->wm_command[0];
- prop1val.length = strlen (winInfo->wm_command[0]);
-
- snprintf (userId, sizeof(userId), "%ld", (long)getuid());
- prop2.name = SmUserID;
- prop2.type = SmARRAY8;
- prop2.num_vals = 1;
- prop2.vals = &prop2val;
- prop2val.value = (SmPointer) userId;
- prop2val.length = strlen (userId);
-
- fullyQuantifiedName = CheckFullyQuantifiedName (
- (char *) winInfo->wm_client_machine.value, &newstring);
- snprintf (restartService, sizeof(restartService),
- "rstart-rsh/%s", fullyQuantifiedName);
- if (newstring)
- free (fullyQuantifiedName);
- prop3.name = "_XC_RestartService";
- prop3.type = SmLISTofARRAY8;
- prop3.num_vals = 1;
- prop3.vals = &prop3val;
- prop3val.value = (SmPointer) restartService;
- prop3val.length = strlen (restartService);
- props[0] = &prop1;
- props[1] = &prop2;
- props[2] = &prop3;
-
- SmcSetProperties (winInfo->smc_conn, 3, props);
- winInfo->got_first_save_yourself = 1;
- }
- prop1.name = SmRestartCommand;
- prop1.type = SmLISTofARRAY8;
- prop1.num_vals = winInfo->wm_command_count;
-
- prop1.vals = (SmPropValue *) malloc (
- winInfo->wm_command_count * sizeof (SmPropValue));
-
- if (!prop1.vals)
- {
- SmcSaveYourselfDone (winInfo->smc_conn, False);
- return;
- }
- for (i = 0; i < winInfo->wm_command_count; i++)
- {
- prop1.vals[i].value = (SmPointer) winInfo->wm_command[i];
- prop1.vals[i].length = strlen (winInfo->wm_command[i]);
- }
-
- prop2.name = SmCloneCommand;
- prop2.type = SmLISTofARRAY8;
- prop2.num_vals = winInfo->wm_command_count;
- prop2.vals = prop1.vals;
-
- props[0] = &prop1;
- props[1] = &prop2;
-
- SmcSetProperties (winInfo->smc_conn, 2, props);
-
- free ((char *) prop1.vals);
-
- /*
- * If the client doesn't support WM_SAVE_YOURSELF, we should
- * return failure for the save, since we really don't know if
- * the application needed to save state.
- */
- SmcSaveYourselfDone (winInfo->smc_conn, has_WM_SAVEYOURSELF);
- }
- static void
- SaveYourselfCB(SmcConn smcConn, SmPointer clientData, int saveType,
- Bool shutdown, int interactStyle, Bool fast)
- {
- WinInfo *winInfo = (WinInfo *) clientData;
- if (!winInfo->has_save_yourself)
- {
- FinishSaveYourself (winInfo, False);
- }
- else
- {
- XClientMessageEvent saveYourselfMessage;
- /* Send WM_SAVE_YOURSELF */
- saveYourselfMessage.type = ClientMessage;
- saveYourselfMessage.window = winInfo->window;
- saveYourselfMessage.message_type = wmProtocolsAtom;
- saveYourselfMessage.format = 32;
- saveYourselfMessage.data.l[0] = wmSaveYourselfAtom;
- saveYourselfMessage.data.l[1] = CurrentTime;
- if (XSendEvent (disp, winInfo->window, False, NoEventMask,
- (XEvent *) &saveYourselfMessage))
- {
- winInfo->waiting_for_update = 1;
- if (debug)
- {
- printf ("Sent SAVE YOURSELF to 0x%x\n",
- (unsigned int)winInfo->window);
- printf ("\n");
- }
- }
- else
- {
- if (debug)
- {
- printf ("Failed to send SAVE YOURSELF to 0x%x\n",
- (unsigned int)winInfo->window);
- printf ("\n");
- }
- }
- }
- }
- static void
- DieCB(SmcConn smcConn, SmPointer clientData)
- {
- WinInfo *winInfo = (WinInfo *) clientData;
- SmcCloseConnection (winInfo->smc_conn, 0, NULL);
- winInfo->smc_conn = NULL;
- XtRemoveInput (winInfo->input_id);
- /* Now tell the client to die */
- if (debug)
- printf ("Trying to kill 0x%x\n", (unsigned int)winInfo->window);
- XSync (disp, 0);
- XKillClient (disp, winInfo->window);
- XSync (disp, 0);
- /*
- * Proxy must exit when all clients die, and the proxy itself
- * must have received a Die.
- */
- die_count++;
- if (die_count == proxy_count && ok_to_die)
- {
- exit (0);
- }
- }
- static void
- SaveCompleteCB(SmcConn smcConn, SmPointer clientData)
- {
- /*
- * Nothing to do here.
- */
- }
- static void
- ShutdownCancelledCB(SmcConn smcConn, SmPointer clientData)
- {
- /*
- * Since we did not request to interact or request save yourself
- * phase 2, we know we already sent the save yourself done, so
- * there is nothing to do here.
- */
- }
- static void
- ProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id)
- {
- IceConn ice_conn = (IceConn) client_data;
- IceProcessMessages (ice_conn, NULL, NULL);
- }
- static void
- NullIceErrorHandler(IceConn iceConn, Bool swap, int offendingMinorOpcode,
- unsigned long offendingSequence, int errorClass,
- int severity, IcePointer values)
- {
- return;
- }
- static void
- ConnectClientToSM(WinInfo *winInfo)
- {
- char errorMsg[256];
- unsigned long mask;
- SmcCallbacks callbacks;
- IceConn ice_conn;
- char *prevId;
- mask = SmcSaveYourselfProcMask | SmcDieProcMask |
- SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
- callbacks.save_yourself.callback = SaveYourselfCB;
- callbacks.save_yourself.client_data = (SmPointer) winInfo;
- callbacks.die.callback = DieCB;
- callbacks.die.client_data = (SmPointer) winInfo;
- callbacks.save_complete.callback = SaveCompleteCB;
- callbacks.save_complete.client_data = (SmPointer) winInfo;
- callbacks.shutdown_cancelled.callback = ShutdownCancelledCB;
- callbacks.shutdown_cancelled.client_data = (SmPointer) winInfo;
- prevId = LookupClientID (winInfo);
- /*
- * In case a protocol error occurs when opening the connection,
- * (e.g. an authentication error), we set a null error handler
- * before the open, then restore the default handler after the open.
- */
- IceSetErrorHandler (NullIceErrorHandler);
- winInfo->smc_conn = SmcOpenConnection (
- NULL, /* use SESSION_MANAGER env */
- (SmPointer) winInfo, /* force a new connection */
- SmProtoMajor,
- SmProtoMinor,
- mask,
- &callbacks,
- prevId,
- &winInfo->client_id,
- 256, errorMsg);
- IceSetErrorHandler (NULL);
- if (winInfo->smc_conn == NULL)
- return;
- ice_conn = SmcGetIceConnection (winInfo->smc_conn);
- winInfo->input_id = XtAppAddInput (
- appContext,
- IceConnectionNumber (ice_conn),
- (XtPointer) XtInputReadMask,
- ProcessIceMsgProc,
- (XtPointer) ice_conn);
- if (debug)
- {
- printf ("Connected to SM, window = 0x%x\n",
- (unsigned int)winInfo->window);
- printf ("\n");
- }
- proxy_count++;
- }
- static int
- MyErrorHandler(Display *display, XErrorEvent *event)
- {
- caught_error = 1;
- return 0;
- }
- static Bool
- LookupWindow(Window window, WinInfo **ptr_ret, WinInfo **prev_ptr_ret)
- {
- WinInfo *ptr, *prev;
- ptr = win_head;
- prev = NULL;
- while (ptr)
- {
- if (ptr->window == window)
- break;
- else
- {
- prev = ptr;
- ptr = ptr->next;
- }
- }
- if (ptr)
- {
- if (ptr_ret)
- *ptr_ret = ptr;
- if (prev_ptr_ret)
- *prev_ptr_ret = prev;
- return (1);
- }
- else
- return (0);
- }
- static WinInfo *
- AddNewWindow(Window window)
- {
- WinInfo *newptr;
- if (LookupWindow (window, NULL, NULL))
- return (NULL);
- newptr = (WinInfo *) malloc (sizeof (WinInfo));
- if (newptr == NULL)
- return (NULL);
- newptr->next = win_head;
- win_head = newptr;
- newptr->window = window;
- newptr->smc_conn = NULL;
- newptr->tested_for_sm_client_id = 0;
- newptr->client_id = NULL;
- newptr->wm_command = NULL;
- newptr->wm_command_count = 0;
- newptr->class.res_name = NULL;
- newptr->class.res_class = NULL;
- newptr->wm_name = NULL;
- newptr->wm_client_machine.value = NULL;
- newptr->wm_client_machine.nitems = 0;
- newptr->has_save_yourself = 0;
- newptr->waiting_for_update = 0;
- newptr->got_first_save_yourself = 0;
- return (newptr);
- }
- static void
- RemoveWindow(WinInfo *winptr)
- {
- WinInfo *ptr, *prev;
- if (LookupWindow (winptr->window, &ptr, &prev))
- {
- if (prev == NULL)
- win_head = ptr->next;
- else
- prev->next = ptr->next;
- if (ptr->client_id)
- free (ptr->client_id);
-
- if (ptr->wm_command)
- XFreeStringList (ptr->wm_command);
-
- if (ptr->wm_name)
- XFree (ptr->wm_name);
-
- if (ptr->wm_client_machine.value)
- XFree (ptr->wm_client_machine.value);
-
- if (ptr->class.res_name)
- XFree (ptr->class.res_name);
-
- if (ptr->class.res_class)
- XFree (ptr->class.res_class);
-
- free ((char *) ptr);
- }
- }
- static void
- Got_WM_STATE(WinInfo *winptr)
- {
- WinInfo *leader_winptr;
- /*
- * If we already got WM_STATE and tested for SM_CLIENT_ID, we
- * shouldn't do it again.
- */
- if (winptr->tested_for_sm_client_id)
- {
- return;
- }
- /*
- * Set a null error handler, in case this window goes away
- * behind our back.
- */
- caught_error = 0;
- XSetErrorHandler (MyErrorHandler);
- /*
- * Get the client leader window.
- */
- leader_winptr = GetClientLeader (winptr);
- if (caught_error)
- {
- caught_error = 0;
- RemoveWindow (winptr);
- XSetErrorHandler (NULL);
- return;
- }
- /*
- * If we already checked for SM_CLIENT_ID on the client leader
- * window, don't do it again.
- */
- if (!leader_winptr || leader_winptr->tested_for_sm_client_id)
- {
- caught_error = 0;
- XSetErrorHandler (NULL);
- return;
- }
- leader_winptr->tested_for_sm_client_id = 1;
- if (!HasXSMPsupport (leader_winptr->window))
- {
- XFetchName (disp, leader_winptr->window, &leader_winptr->wm_name);
- XGetCommand (disp, leader_winptr->window,
- &leader_winptr->wm_command,
- &leader_winptr->wm_command_count);
- XGetClassHint (disp, leader_winptr->window, &leader_winptr->class);
- XGetWMClientMachine (disp, leader_winptr->window,
- &leader_winptr->wm_client_machine);
- if (leader_winptr->wm_name != NULL &&
- leader_winptr->wm_command != NULL &&
- leader_winptr->wm_command_count > 0 &&
- leader_winptr->class.res_name != NULL &&
- leader_winptr->class.res_class != NULL &&
- leader_winptr->wm_client_machine.value != NULL &&
- leader_winptr->wm_client_machine.nitems != 0)
- {
- leader_winptr->has_save_yourself =
- HasSaveYourself (leader_winptr->window);
- ConnectClientToSM (leader_winptr);
- }
- }
- XSync (disp, 0);
- XSetErrorHandler (NULL);
- if (caught_error)
- {
- caught_error = 0;
- RemoveWindow (leader_winptr);
- }
- }
- static void
- HandleCreate(XCreateWindowEvent *event)
- {
- Atom actual_type;
- int actual_format;
- unsigned long nitems, bytesafter;
- unsigned long *datap = NULL;
- WinInfo *winptr;
- Bool got_wm_state = 0;
- /*
- * We are waiting for all proxy connections to close so we can die.
- * Don't handle new connections.
- */
- if (ok_to_die)
- return;
- /*
- * Add the new window
- */
- if ((winptr = AddNewWindow (event->window)) == NULL)
- return;
- /*
- * Right after the window was created, it might have been destroyed,
- * so the following Xlib calls might fail. Need to catch the error
- * by installing an error handler.
- */
- caught_error = 0;
- XSetErrorHandler (MyErrorHandler);
- /*
- * Select for Property Notify on the window so we can determine
- * when WM_STATE is defined. To avoid a race condition, we must
- * do this _before_ we check for WM_STATE right now.
- *
- * Select for Substructure Notify so we can determine when the
- * window is destroyed.
- */
- XSelectInput (disp, event->window,
- SubstructureNotifyMask | PropertyChangeMask);
- /*
- * WM_STATE may already be there. Check now.
- */
- if (XGetWindowProperty (disp, event->window, wmStateAtom,
- 0L, 2L, False, AnyPropertyType,
- &actual_type, &actual_format, &nitems, &bytesafter,
- (unsigned char **) &datap) == Success && datap)
- {
- if (nitems > 0)
- got_wm_state = 1;
- if (datap)
- XFree ((char *) datap);
- }
- XSync (disp, 0);
- XSetErrorHandler (NULL);
- if (caught_error)
- {
- caught_error = 0;
- RemoveWindow (winptr);
- }
- else if (got_wm_state)
- {
- Got_WM_STATE (winptr);
- }
- }
- static void
- HandleDestroy(XDestroyWindowEvent *event)
- {
- WinInfo *winptr;
- if (LookupWindow (event->window, &winptr, NULL))
- {
- if (winptr->smc_conn)
- {
- SmcCloseConnection (winptr->smc_conn, 0, NULL);
- XtRemoveInput (winptr->input_id);
- proxy_count--;
- }
- if (debug)
- {
- printf ("Removed window (window = 0x%x)\n",
- (unsigned int)winptr->window);
- printf ("\n");
- }
- RemoveWindow (winptr);
- }
- }
- static void
- HandleUpdate(XPropertyEvent *event)
- {
- Window window = event->window;
- WinInfo *winptr;
- if (!LookupWindow (window, &winptr, NULL))
- return;
- if (event->atom == wmStateAtom)
- {
- Got_WM_STATE (winptr);
- }
- else if (event->atom == XA_WM_COMMAND && winptr->waiting_for_update)
- {
- /* Finish off the Save Yourself */
- if (winptr->wm_command)
- {
- XFreeStringList (winptr->wm_command);
- winptr->wm_command = NULL;
- winptr->wm_command_count = 0;
- }
- XGetCommand (disp, window,
- &winptr->wm_command,
- &winptr->wm_command_count);
- winptr->waiting_for_update = 0;
- FinishSaveYourself (winptr, True);
- }
- }
- static void
- ProxySaveYourselfPhase2CB(SmcConn smcConn, SmPointer clientData)
- {
- char *filename;
- Bool success = True;
- SmProp prop1, prop2, prop3, *props[3];
- SmPropValue prop1val, prop2val, prop3val;
- char *discardCommand;
- int numVals, i;
- static int first_time = 1;
- if (first_time)
- {
- char userId[20];
- char hint = SmRestartIfRunning;
- prop1.name = SmProgram;
- prop1.type = SmARRAY8;
- prop1.num_vals = 1;
- prop1.vals = &prop1val;
- prop1val.value = Argv[0];
- prop1val.length = strlen (Argv[0]);
- snprintf (userId, sizeof(userId), "%ld", (long)getuid());
- prop2.name = SmUserID;
- prop2.type = SmARRAY8;
- prop2.num_vals = 1;
- prop2.vals = &prop2val;
- prop2val.value = (SmPointer) userId;
- prop2val.length = strlen (userId);
-
- prop3.name = SmRestartStyleHint;
- prop3.type = SmCARD8;
- prop3.num_vals = 1;
- prop3.vals = &prop3val;
- prop3val.value = (SmPointer) &hint;
- prop3val.length = 1;
-
- props[0] = &prop1;
- props[1] = &prop2;
- props[2] = &prop3;
- SmcSetProperties (smcConn, 3, props);
- first_time = 0;
- }
- if ((filename = WriteProxyFile ()) == NULL)
- {
- success = False;
- goto finishUp;
- }
- prop1.name = SmRestartCommand;
- prop1.type = SmLISTofARRAY8;
- prop1.vals = (SmPropValue *) malloc (
- (Argc + 4) * sizeof (SmPropValue));
- if (!prop1.vals)
- {
- success = False;
- goto finishUp;
- }
- numVals = 0;
- for (i = 0; i < Argc; i++)
- {
- if (strcmp (Argv[i], "-clientId") == 0 ||
- strcmp (Argv[i], "-restore") == 0)
- {
- i++;
- }
- else
- {
- prop1.vals[numVals].value = (SmPointer) Argv[i];
- prop1.vals[numVals++].length = strlen (Argv[i]);
- }
- }
- prop1.vals[numVals].value = (SmPointer) "-clientId";
- prop1.vals[numVals++].length = 9;
- prop1.vals[numVals].value = (SmPointer) proxy_clientId;
- prop1.vals[numVals++].length = strlen (proxy_clientId);
- prop1.vals[numVals].value = (SmPointer) "-restore";
- prop1.vals[numVals++].length = 8;
- prop1.vals[numVals].value = (SmPointer) filename;
- prop1.vals[numVals++].length = strlen (filename);
- prop1.num_vals = numVals;
- if (asprintf (&discardCommand, "rm %s", filename) == -1) {
- success = False;
- goto finishUp;
- }
- prop2.name = SmDiscardCommand;
- prop2.type = SmARRAY8;
- prop2.num_vals = 1;
- prop2.vals = &prop2val;
- prop2val.value = (SmPointer) discardCommand;
- prop2val.length = strlen (discardCommand);
- props[0] = &prop1;
- props[1] = &prop2;
- SmcSetProperties (smcConn, 2, props);
- free ((char *) prop1.vals);
- free (discardCommand);
- finishUp:
- SmcSaveYourselfDone (smcConn, success);
- sent_save_done = 1;
- if (filename)
- free (filename);
- }
- static void
- ProxySaveYourselfCB(SmcConn smcConn, SmPointer clientData, int saveType,
- Bool shutdown, int interactStyle, Bool fast)
- {
- /*
- * We want the proxy to respond to the Save Yourself after all
- * the regular XSMP clients have finished with the save (and possibly
- * interacted with the user).
- */
- if (!SmcRequestSaveYourselfPhase2 (smcConn,
- ProxySaveYourselfPhase2CB, NULL))
- {
- SmcSaveYourselfDone (smcConn, False);
- sent_save_done = 1;
- }
- else
- sent_save_done = 0;
- }
- static void
- ProxyDieCB(SmcConn smcConn, SmPointer clientData)
- {
- SmcCloseConnection (proxy_smcConn, 0, NULL);
- XtRemoveInput (proxy_iceInputId);
- if (die_count == proxy_count)
- exit (0);
- else
- ok_to_die = 1;
- }
- static void
- ProxySaveCompleteCB(SmcConn smcConn, SmPointer clientData)
- {
- ;
- }
- static void
- ProxyShutdownCancelledCB(SmcConn smcConn, SmPointer clientData)
- {
- if (!sent_save_done)
- {
- SmcSaveYourselfDone (smcConn, False);
- sent_save_done = 1;
- }
- }
- static Status
- ConnectProxyToSM(char *previous_id)
- {
- char errorMsg[256];
- unsigned long mask;
- SmcCallbacks callbacks;
- IceConn iceConn;
- mask = SmcSaveYourselfProcMask | SmcDieProcMask |
- SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
- callbacks.save_yourself.callback = ProxySaveYourselfCB;
- callbacks.save_yourself.client_data = (SmPointer) NULL;
- callbacks.die.callback = ProxyDieCB;
- callbacks.die.client_data = (SmPointer) NULL;
- callbacks.save_complete.callback = ProxySaveCompleteCB;
- callbacks.save_complete.client_data = (SmPointer) NULL;
- callbacks.shutdown_cancelled.callback = ProxyShutdownCancelledCB;
- callbacks.shutdown_cancelled.client_data = (SmPointer) NULL;
- proxy_smcConn = SmcOpenConnection (
- NULL, /* use SESSION_MANAGER env */
- (SmPointer) appContext,
- SmProtoMajor,
- SmProtoMinor,
- mask,
- &callbacks,
- previous_id,
- &proxy_clientId,
- 256, errorMsg);
- if (proxy_smcConn == NULL)
- return (0);
- iceConn = SmcGetIceConnection (proxy_smcConn);
- proxy_iceInputId = XtAppAddInput (
- appContext,
- IceConnectionNumber (iceConn),
- (XtPointer) XtInputReadMask,
- ProcessIceMsgProc,
- (XtPointer) iceConn);
- return (1);
- }
- static void
- CheckForExistingWindows(Window root)
- {
- Window dontCare1, dontCare2, *children, client_window;
- unsigned int nchildren, i;
- XCreateWindowEvent event;
- /*
- * We query the root tree for all windows created thus far.
- * Note that at any moment after XQueryTree is called, a
- * window may be deleted. So we must take extra care to make
- * sure a window really exists.
- */
- XQueryTree (disp, root, &dontCare1, &dontCare2, &children, &nchildren);
- for (i = 0; i < nchildren; i++)
- {
- event.window = children[i];
- HandleCreate (&event);
- caught_error = 0;
- XSetErrorHandler (MyErrorHandler);
- client_window = XmuClientWindow (disp, children[i]);
- XSetErrorHandler (NULL);
- if (!caught_error && client_window != children[i])
- {
- event.window = client_window;
- HandleCreate (&event);
- }
- }
- }
- int
- main (int argc, char *argv[])
- {
- char *restore_filename = NULL;
- char *client_id = NULL;
- int i, zero = 0;
- Argc = argc;
- Argv = argv;
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] == '-')
- {
- switch (argv[i][1])
- {
- case 'd': /* -debug */
- debug = 1;
- continue;
- case 'c': /* -clientId */
- if (++i >= argc) {
- fprintf (stderr, "%s: -clientId requires an argument\n",
- argv[0]);
- goto usage;
- }
- client_id = argv[i];
- continue;
- case 'r': /* -restore */
- if (++i >= argc) {
- fprintf (stderr, "%s: -restore requires an argument\n",
- argv[0]);
- goto usage;
- }
- restore_filename = argv[i];
- continue;
- case 'v':
- puts (PACKAGE_STRING);
- exit (0);
- }
- }
- fprintf (stderr, "%s: unrecognized argument: %s\n", argv[0], argv[i]);
- usage:
- fprintf (stderr,
- "usage: %s [-clientId id] [-restore file] [-debug] [-version]\n",
- argv[0]);
- exit (1);
- }
- XtToolkitInitialize ();
- appContext = XtCreateApplicationContext ();
- if (!(disp = XtOpenDisplay (appContext, NULL, "SM-PROXY", "SM-PROXY",
- NULL, 0, &zero, NULL)))
- {
- fprintf (stderr, "smproxy: unable to open display\n");
- exit (1);
- }
- if (restore_filename)
- ReadProxyFile (restore_filename);
- if (!ConnectProxyToSM (client_id))
- {
- fprintf (stderr, "smproxy: unable to connect to session manager\n");
- exit (1);
- }
- wmProtocolsAtom = XInternAtom (disp, "WM_PROTOCOLS", False);
- wmSaveYourselfAtom = XInternAtom (disp, "WM_SAVE_YOURSELF", False);
- wmStateAtom = XInternAtom (disp, "WM_STATE", False);
- smClientIdAtom = XInternAtom (disp, "SM_CLIENT_ID", False);
- wmClientLeaderAtom = XInternAtom (disp, "WM_CLIENT_LEADER", False);
- for (i = 0; i < ScreenCount (disp); i++)
- {
- Window root = RootWindow (disp, i);
- XSelectInput (disp, root, SubstructureNotifyMask | PropertyChangeMask);
- CheckForExistingWindows (root);
- }
- while (1)
- {
- XEvent event;
- XtAppNextEvent (appContext, &event);
- switch (event.type)
- {
- case CreateNotify:
- HandleCreate (&event.xcreatewindow);
- break;
- case DestroyNotify:
- HandleDestroy (&event.xdestroywindow);
- break;
- case PropertyNotify:
- HandleUpdate (&event.xproperty);
- break;
- default:
- XtDispatchEvent (&event);
- break;
- }
- }
- exit(0);
- }
|