123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * (c) Copyright 1995 Digital Equipment Corporation.
- * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
- * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
- * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
- * (c) Copyright 1993, 1994, 1995 Novell, Inc.
- * (c) Copyright 1995 FUJITSU LIMITED.
- * (c) Copyright 1995 Hitachi.
- *
- * $TOG: SmXSMP.c /main/40 1999/01/18 15:42:07 samborn $
- */
- /*************************************<+>*************************************
- *****************************************************************************
- **
- ** File: SmXSMP.c
- **
- ** Project: DT Session Manager (dtsession)
- **
- *****************************************************************************
- *************************************<+>*************************************/
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include "SmXSMP.h"
- #include "SmAuth.h"
- #include "SmWatch.h"
- #include "SmProp.h"
- #include "Sm.h"
- #include "SmUI.h"
- #include "SmSave.h"
- #include "SmRestore.h"
- #include "SmGlobals.h"
- #include <X11/Xlib.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xatom.h>
- #include <X11/SM/SMlib.h>
- #include <Dt/MsgLog.h>
- #include <Dt/Lock.h>
- #include <Dt/Wsm.h>
- #include <Tt/tt_c.h>
- /*
- * Private constants
- */
- #define ERRORMSGLEN 256
- #define GET_CLIENT_WORKSPACE_MSG "GetWsmClients"
- /*
- * Private variables
- */
- static Boolean authenticationInitialized = False;
- static char * networkIds;
- /*
- * Private functions
- */
- static void InitializeXSMPGlobals ();
- static void PutSessionManagerOnRootWindow (
- char *networkIds);
- static void InitializeSaveState (
- Boolean startUp);
- static Boolean SendGetWsmClientsMessage ();
- static int GetCurrentWorkspaceNumber ();
- static void ProcessInteract (
- ClientRecPtr client,
- Boolean getWsmClientOK);
- static void CancelShutdown ();
- static void FreeProps (
- PropertyRecPtr pProp);
- static void ProcessSaveYourselfResponses ();
- /*
- * Public variables
- */
- XSMPSettings smXSMP;
- ClientRecPtr connectedList;
- Atom XaSmClientId;
- /*
- * Public functins
- */
- void InstallIOErrorHandler ();
- Status NewClientProc (
- SmsConn smsConn,
- SmPointer managerData,
- unsigned long *maskRet,
- SmsCallbacks *callbacksRet,
- char **failureReasonRet);
- void NewConnectionXtProc (
- XtPointer client_data,
- int *source,
- XtInputId *id);
- Status RegisterClientProc (
- SmsConn smsConn,
- SmPointer managerData,
- char *previousId);
- void InteractRequestProc (
- SmsConn smsConn,
- SmPointer managerData,
- int dialogType);
- void InteractDoneProc (
- SmsConn smsConn,
- SmPointer managerData,
- Bool cancelShutdown);
- void SaveYourselfReqProc (
- SmsConn smsConn,
- SmPointer managerData,
- int saveType,
- Bool shutdown,
- int interactStyle,
- Bool fast,
- Bool global);
- void SaveYourselfPhase2ReqProc (
- SmsConn smsConn,
- SmPointer managerData);
- void SaveYourselfDoneProc (
- SmsConn smsConn,
- SmPointer managerData,
- Bool success);
- void CloseConnectionProc (
- SmsConn smsConn,
- SmPointer managerData,
- int count,
- char **reasonMsgs);
- void CompleteXSMPSave ();
- void CloseDownClient (
- ClientRecPtr client );
- /*
- * List manipulation functions
- */
- void AddClient (
- ClientRecPtr newClient);
- /*
- * Functions
- */
- Boolean InitXSMP (void)
- {
- char errorMsg[ERRORMSGLEN];
- char *env;
- int i;
- InitializeXSMPGlobals ();
- InstallIOErrorHandler ();
- if (!SmsInitialize (SM_VENDOR_NAME, SM_RELEASE_NAME,
- NewClientProc, NULL,
- HostBasedAuthProc,
- ERRORMSGLEN, errorMsg)) {
- DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMsg);
- PostXSMPFailureDialog (XSMP_FAILURE_SMS_INITIALIZE, True);
- }
- if (!IceListenForConnections (&smXSMP.numTransports,
- &smXSMP.listenObjs,
- ERRORMSGLEN, errorMsg)) {
- DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMsg);
- PostXSMPFailureDialog (XSMP_FAILURE_ICE_LISTEN, True);
- }
- if (!SetAuthentication (smXSMP.numTransports,
- smXSMP.listenObjs,
- &smXSMP.authDataEntries))
- PostXSMPFailureDialog (XSMP_FAILURE_AUTHENTICATION, False);
- authenticationInitialized = True;
- if (!InitWatchProcs (smGD.appCon))
- PostXSMPFailureDialog (XSMP_FAILURE_ICE_ADD_WATCH, False);
- for (i = 0; i < smXSMP.numTransports; i++) {
- XtAppAddInput (smGD.appCon,
- IceGetListenConnectionNumber (smXSMP.listenObjs[i]),
- (XtPointer) XtInputReadMask,
- NewConnectionXtProc, (XtPointer) smXSMP.listenObjs[i]);
- }
- networkIds = IceComposeNetworkIdList (smXSMP.numTransports,
- smXSMP.listenObjs);
- if (!networkIds)
- PostXSMPFailureDialog (XSMP_FAILURE_ICE_COMPOSE_IDS, False);
- env = (char *) XtMalloc (strlen (SM_SESSION_MANAGER) +
- strlen (networkIds) + 2);
- if (!env) {
- free (networkIds);
- PostXSMPFailureDialog (XSMP_FAILURE_MALLOC, False);
- } else {
- (void) sprintf (env, "%s=%s", SM_SESSION_MANAGER, networkIds);
- (void) putenv (env);
- }
- PutSessionManagerOnRootWindow (networkIds);
- XaSmClientId = XInternAtom(smGD.display, SM_CLIENT_ID, False);
- #ifdef DEBUG
- printf ("%s\n", env);
- #endif /* DEBUG */
- return (True);
- }
- static void
- PutSessionManagerOnRootWindow (
- char *networkIds)
- {
- Atom sessionManager;
- sessionManager = XInternAtom(smGD.display, SM_SESSION_MANAGER, False);
- XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
- sessionManager, XA_STRING, 8, PropModeReplace,
- (unsigned char *) networkIds, strlen((char *)networkIds));
- }
- static void
- InitializeSaveState (
- Boolean startUp)
- {
- smXSMP.saveState.global = False;
- smXSMP.saveState.shutdown = False;
- smXSMP.saveState.interactStyle = SmInteractStyleAny;
- smXSMP.saveState.clientInteracting = False;
- smXSMP.saveState.inProgress = False;
- smXSMP.saveState.doneSuccess = True;
- smXSMP.saveState.saveComplete = False;
- smXSMP.saveState.interactCount = 0;
- smXSMP.saveState.numClientIds = 0;
- smXSMP.saveState.interactClient = NULL;
- if (startUp) {
- smXSMP.saveState.clientIds = NULL;
- smXSMP.saveState.workspaceNums = NULL;
- } else {
- if (smXSMP.saveState.clientIds) {
- free (smXSMP.saveState.clientIds);
- smXSMP.saveState.clientIds = NULL;
- }
- if (smXSMP.saveState.workspaceNums) {
- free (smXSMP.saveState.workspaceNums);
- smXSMP.saveState.workspaceNums = NULL;
- }
- }
- }
- static void
- InitializeXSMPGlobals (void)
- {
- smXSMP.authDataEntries = NULL;
- connectedList = NULL;
- smXSMP.xsmpDbList = NULL;
-
- smXSMP.dbVersion = SM_VENDOR_NAME;
- smXSMP.dbSessionId = SM_RELEASE_NAME;
- InitializeSaveState (True);
- }
- /*ARGSUSED*/
- Status
- NewClientProc (
- SmsConn smsConn,
- SmPointer managerData,
- unsigned long *maskRet,
- SmsCallbacks *callbacksRet,
- char **failureReasonRet)
- {
- ClientRecPtr newClient;
-
- #ifdef DEBUG
- (void) printf ("\nNewClientProc: IceConn fd = %d\n",
- IceConnectionNumber (SmsGetIceConnection (smsConn)));
- #endif /* DEBUG */
- newClient = (ClientRecPtr) XtMalloc (sizeof (ClientRec));
- if (!newClient) {
- char *str;
- str = strdup ((char *) GETMESSAGE (4, 5,
- "Unable to malloc memory for operation."));
- if (str) {
- if ((*failureReasonRet = (char *)
- XtMalloc ( strlen (str) + 1)) != NULL)
- strcpy (*failureReasonRet, str);
-
- DtMsgLogMessage (smGD.programName, DtMsgLogError, str);
- free (str);
- }
- return (0);
- }
- *maskRet = 0;
- newClient->smConn = smsConn;
- newClient->iceConn = SmsGetIceConnection (smsConn);
- newClient->clientId = NULL;
- newClient->clientHost = NULL;
- newClient->screenNum = 0;
- newClient->restartHint = SmRestartIfRunning;
- newClient->props = NULL;
- newClient->active = False;
- newClient->saveYourselfDone = False;
- newClient->saveYourselfP2Requested = False;
- newClient->interactRequested = False;
- newClient->next = NULL;
- AddClient (newClient);
- *maskRet |= SmsRegisterClientProcMask;
- callbacksRet->register_client.callback = RegisterClientProc;
- callbacksRet->register_client.manager_data = (SmPointer) newClient;
- *maskRet |= SmsInteractRequestProcMask;
- callbacksRet->interact_request.callback = InteractRequestProc;
- callbacksRet->interact_request.manager_data = (SmPointer) newClient;
- *maskRet |= SmsInteractDoneProcMask;
- callbacksRet->interact_done.callback = InteractDoneProc;
- callbacksRet->interact_done.manager_data = (SmPointer) newClient;
- *maskRet |= SmsSaveYourselfRequestProcMask;
- callbacksRet->save_yourself_request.callback = SaveYourselfReqProc;
- callbacksRet->save_yourself_request.manager_data =
- (SmPointer) newClient;
- *maskRet |= SmsSaveYourselfP2RequestProcMask;
- callbacksRet->save_yourself_phase2_request.callback =
- SaveYourselfPhase2ReqProc;
- callbacksRet->save_yourself_phase2_request.manager_data =
- (SmPointer) newClient;
- *maskRet |= SmsSaveYourselfDoneProcMask;
- callbacksRet->save_yourself_done.callback = SaveYourselfDoneProc;
- callbacksRet->save_yourself_done.manager_data = (SmPointer) newClient;
- *maskRet |= SmsCloseConnectionProcMask;
- callbacksRet->close_connection.callback = CloseConnectionProc;
- callbacksRet->close_connection.manager_data = (SmPointer) newClient;
- *maskRet |= SmsSetPropertiesProcMask;
- callbacksRet->set_properties.callback = SetPropertiesProc;
- callbacksRet->set_properties.manager_data = (SmPointer) newClient;
- *maskRet |= SmsDeletePropertiesProcMask;
- callbacksRet->delete_properties.callback = DeletePropertiesProc;
- callbacksRet->delete_properties.manager_data = (SmPointer) newClient;
- *maskRet |= SmsGetPropertiesProcMask;
- callbacksRet->get_properties.callback = GetPropertiesProc;
- callbacksRet->get_properties.manager_data = (SmPointer) newClient;
- return (True);
- }
- /*ARGSUSED*/
- void
- NewConnectionXtProc (
- XtPointer client_data,
- int *source,
- XtInputId *id)
- {
- IceConn ice_conn;
- IceAcceptStatus status;
- #ifdef DEBUG
- (void) printf ("NewConnectionXtProc [fd = %d]\n", *source);
- #endif /* DEBUG */
- if (smXSMP.saveState.shutdown == True)
- {
- /*
- * Don't accept new connections if we are in the middle
- * of a shutdown.
- */
- return;
- }
- ice_conn = IceAcceptConnection((IceListenObj) client_data, &status);
- if (!ice_conn) {
- char *message;
- message = strdup ((char *) GETMESSAGE (40, 20,
- "IceAcceptConnection failed."));
-
- if (message) {
- DtMsgLogMessage (smGD.programName, DtMsgLogError,
- message);
- free (message);
- }
- } else {
- IceConnectStatus cstatus;
- while ((cstatus = IceConnectionStatus (ice_conn)) ==
- IceConnectPending) {
- XtAppProcessEvent (smGD.appCon, XtIMAll);
- }
- if (cstatus == IceConnectAccepted) {
- #ifdef DEBUG
- char *connstr;
- printf ("ICE Connection opened IceConn fd = %d, ",
- IceConnectionNumber (ice_conn));
- connstr = IceConnectionString (ice_conn);
- printf ("\tAccept at networkId %s\n\n", connstr);
- free (connstr);
- #else
- return;
- #endif /* DEBUG */
- } else {
- #ifdef DEBUG
- if (cstatus == IceConnectIOError)
- printf ("IO error opening ICE Connection!\n");
- else
- printf ("ICE Connection rejected!\n");
- #endif /* DEBUG */
- }
- }
- }
- Status
- RegisterClientProc (
- SmsConn smsConn,
- SmPointer managerData,
- char *previousId)
- {
- ClientRec *client = (ClientRec *) managerData;
- char *id = previousId;
- Boolean sendSave = False;
- char *pchar;
- #ifdef DEBUG
- int i;
- #endif /* DEBUG */
- #ifdef DEBUG
- (void) printf ("Received REGISTER CLIENT [%d] - id = %s\n",
- smsConn, previousId ? previousId : "New Client");
- #endif /* DEBUG */
- if (!previousId) {
- id = SmsGenerateClientID (smsConn);
- sendSave = True;
- }
- else {
- ClientRecPtr pClientRec;
- XSMPClientDBRecPtr pDbRec;
- Boolean found = False;
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (!strcmp (pClientRec->clientId, previousId)) {
- #ifdef DEBUG
- (void) printf ("\tAlready connected.\n");
- #endif /* DEBUG */
- if (!pClientRec->active)
- /*
- * A client that terminated is
- * re-using its id
- */
- found = True;
- break;
- }
- }
- for (pDbRec = smXSMP.xsmpDbList;
- pDbRec != NULL && found == False;
- pDbRec = pDbRec->next) {
- if (!strcmp (pDbRec->clientId, previousId)) {
- #ifdef DEBUG
- (void) printf ("\tClient in DB.\n");
- #endif /* DEBUG */
- found = True;
- }
- }
- if (!found) {
- /*
- * The client is using an invalid id or
- * this clientID is already being used.
- * Reject the connection.
- */
- #ifdef DEBUG
- (void) printf ("\tID is NOT valid.\n");
- #endif /* DEBUG */
- free (previousId);
- return (0);
- }
- }
- client->clientId = strdup (id);
- pchar = SmsClientHostName (smsConn);
- if (pchar)
- client->clientHost = (strchr (pchar, '/')) + 1;
- else
- client->clientHost = pchar;
- client->active = True;
- SmsRegisterClientReply (smsConn, id);
- if (sendSave)
- SmsSaveYourself (smsConn, SmSaveLocal, False,
- SmInteractStyleNone, False);
- #ifdef DEBUG
- (void) printf ("CLIENTS REGISTERED:\n");
- for (i = 1, client = connectedList;
- client != NULL;
- i++, client = client->next) {
- if (client->active)
- (void) printf ("\t[%2d] = %s\n", i, client->clientId);
- }
- #endif /* DEBUG */
- return (1);
- }
- /*ARGSUSED*/
- void
- InteractRequestProc (
- SmsConn smsConn,
- SmPointer managerData,
- int dialogType)
- {
- ClientRecPtr client = (ClientRecPtr) managerData;
- Boolean getWsmClientOK = True;
- #ifdef DEBUG
- (void) printf ("Received INTERACT REQUEST [%d]\n", smsConn);
- if (dialogType == SmDialogError)
- (void) printf ("\tSmDialogError\n");
- else if (dialogType == SmDialogNormal)
- (void) printf ("\tSmDialogNormal\n");
- else
- (void) printf ("\tSMlib Error: should have checked for bad value\n");
- #endif /* DEBUG */
- client->interactRequested = True;
- if (smXSMP.saveState.interactCount == 0) {
- /*
- * Only need to get the Wkspace list once for a save
- */
- smXSMP.saveState.interactCount++;
- if (!SendGetWsmClientsMessage ()) {
- char *pch;
- pch = strdup ((char *) GETMESSAGE (40, 17,
- "An attempt to get a client list from the 'Window Manager' failed."));
- if (pch) {
- DtMsgLogMessage (smGD.programName,
- DtMsgLogWarning, pch);
- free (pch);
- }
- getWsmClientOK = False;
- } else {
- /*
- * Cann't do anything else until the GetWsmClients
- * message handler is invoked.
- *
- * Must cache this client because it is needed in the
- * GetWsmClients callback and ToolTalk apparently
- * doesn't allow 'client_data' to be assigned to its
- * callback funtions.
- */
- smXSMP.saveState.interactClient = client;
- return;
- }
- }
- ProcessInteract (client, getWsmClientOK);
- }
- /*ARGSUSED*/
- void
- InteractDoneProc (
- SmsConn smsConn,
- SmPointer managerData,
- Bool cancelShutdown)
- {
- ClientRecPtr client = (ClientRecPtr) managerData;
- #ifdef DEBUG
- (void) printf ("Received INTERACT DONE [%d] - Cancel Shutdown = %s\n",
- smsConn, cancelShutdown ? "True" : "False");
- #endif /* DEBUG */
- client->interactRequested = False;
- smXSMP.saveState.clientInteracting = False;
- if (cancelShutdown)
- smXSMP.saveState.shutdownCanceled = True;
- if (cancelShutdown &&
- smXSMP.saveState.shutdown == True &&
- (smXSMP.saveState.interactStyle == SmInteractStyleErrors ||
- (smXSMP.saveState.interactStyle == SmInteractStyleAny))) {
-
- ClientRecPtr pClientRec;
- char *pch;
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- SmsShutdownCancelled (pClientRec->smConn);
- #ifdef DEBUG
- (void) printf ("Sent ShutdownCancelled to %d\n",
- pClientRec->smConn);
- #endif /* DEBUG */
- }
- pch = strdup ((char *) GETMESSAGE (40, 22, "A session shutdown was cancelled by the application '%s'."));
- if (pch) {
- DtMsgLogMessage (smGD.programName,
- DtMsgLogInformation,
- pch,
- GetArrayPropertyValue (client,
- SmProgram));
- free (pch);
- }
- return;
- }
- ProcessInteract (client, True);
- }
- /*ARGSUSED*/
- void
- SaveYourselfReqProc (
- SmsConn smsConn,
- SmPointer managerData,
- int saveType,
- Bool shutdown,
- int interactStyle,
- Bool fast,
- Bool global)
- {
- ClientRecPtr tmpClient;
- ClientRecPtr pClientRec;
- Boolean notify = True;
- #ifdef DEBUG
- (void) printf ("Received SAVE YOURSELF REQUEST [%d].\n", smsConn);
- (void) printf ("\tglobal = %s\n", global ? "True" : "False");
- (void) printf ("\tshutdown = %s\n", shutdown ? "True" : "False");
- (void) printf ("\tfast = %s\n", fast ? "True" : "False");
- (void) printf ("\tsaveType = ");
- switch (saveType) {
- case SmSaveLocal: printf ("SmSaveLocal\n"); break;
- case SmSaveGlobal: printf ("SmSaveGlobal\n"); break;
- case SmSaveBoth: printf ("SmSaveBoth\n"); break;
- default: printf ("save type NOT supported\n");
- }
- (void) printf ("\tinteractStyle = ");
- switch (saveType) {
- case SmInteractStyleNone: printf ("SmInteractStyleNone\n");
- break;
- case SmInteractStyleErrors: printf ("SmInteractStyleErrors\n");
- break;
- case SmInteractStyleAny: printf ("SmInteractStyleAny\n");
- break;
- default: printf ("interact style NOT supported\n");
- }
- #endif /* DEBUG */
- if (smXSMP.saveState.inProgress) {
- char *pch;
- pch = strdup ((char *) GETMESSAGE (40, 21, "The session will not be saved because a Save Session is in progress."));
- if (pch) {
- DtMsgLogMessage (smGD.programName, DtMsgLogError, pch);
- free (pch);
- }
- return;
- }
- if (!global) {
- /*
- * The client wants to be told to save itself but
- * no other clients should be notified. [smsConn
- * will be NULL if this non-global save came from
- * a non-XSMP client (e.g via a ToolTalk message).
- */
- if (smsConn) {
- SmsSaveYourself (smsConn, saveType, shutdown,
- interactStyle, fast);
- #ifdef DEBUG
- (void) printf ("\tSent SaveYourself to %d\n", smsConn);
- #endif /* DEBUG */
- }
- return;
- }
- smXSMP.saveState.inProgress = True;
- smXSMP.saveState.shutdown = shutdown;
- smXSMP.saveState.shutdownCanceled = False;
- smXSMP.saveState.interactStyle = interactStyle;
- smXSMP.saveState.global = global;
- /*
- * Before notifying the clients, setup a directory
- * for them to save their state.
- */
- if (smGD.homeSave || (smGD.sessionType == HOME_SESSION &&
- smSettings.startState == DtSM_HOME_STATE)) {
- if (smXSMP.saveState.shutdown)
- /*
- * Leave the old session dir in place. It
- * will only be used by XSMP apps.
- */
- notify = False;
- else
- SetupSaveState (True, DtSM_HOME_STATE);
- } else {
- if (smGD.sessionType == CURRENT_SESSION ||
- smGD.sessionType == DEFAULT_SESSION)
- SetupSaveState (False, DtSM_CURRENT_STATE);
- else if (smGD.sessionType == HOME_SESSION &&
- smSettings.startState == DtSM_CURRENT_STATE)
- SetupSaveState (False, DtSM_HOME_STATE);
- else
- SetupSaveState (False, DtSM_HOME_STATE);
- }
- /*
- * Before the XSMP clients are saved, the ICCC apps must be
- * sent a WM_SAVE_YOURSELF message. This needs to be done because some
- * apps do not update their geometry information until they
- * get this message. If an ICCC app doesn't update their geometry,
- * then an XSMP-based Window Manager will not have the appropriate
- * geometry information and the app will not be restore in the
- * appropriate location.
- */
- if (notify) {
- ShowWaitState(True);
- NotifyProxyClients ();
- ShowWaitState(False);
- }
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- SmsSaveYourself (pClientRec->smConn, saveType,
- shutdown, interactStyle, fast);
- #ifdef DEBUG
- (void) printf ("\tSent saveyourself to %d\n",
- pClientRec->smConn);
- #endif /* DEBUG */
- }
- }
- /*
- * If all of the clients are P2 clients, then process
- * the save now because these clients won't send a
- * SaveYourselfDone msg until after they have processed
- * a P2 message.
- */
- tmpClient = NULL;
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- if (pClientRec->saveYourselfP2Requested)
- tmpClient = pClientRec;
- else
- return;
- }
- }
- if (tmpClient) {
- SmsSaveYourselfPhase2 (tmpClient->smConn);
- #ifdef DEBUG
- (void) printf ("\tSent SaveYourselfPhase2 to %d\n",
- pClientRec->smConn);
- #endif /* DEBUG */
- }
- }
- /*ARGSUSED*/
- void
- SaveYourselfPhase2ReqProc (
- SmsConn smsConn,
- SmPointer managerData)
- {
- ClientRecPtr client = (ClientRecPtr) managerData;
- #ifdef DEBUG
- (void) printf ("Received SAVE YOURSELF PHASE 2 REQUEST [%d]\n",
- smsConn);
- #endif /* DEBUG */
- client->saveYourselfP2Requested = True;
- /*
- * A client may have sent this message in response to
- * the SM's start-up SaveYourself message. So if
- * a session isn't currently being saved, return.
- */
- if (!smXSMP.saveState.inProgress) {
- /*
- * The client is responding to the start-up SaveYourself
- * message - this isn't a user-initiated save.
- */
-
- SmsSaveComplete (smsConn);
- return;
- }
- ProcessSaveYourselfResponses ();
- }
- /*ARGSUSED*/
- void
- SaveYourselfDoneProc (
- SmsConn smsConn,
- SmPointer managerData,
- Bool success)
- {
- ClientRecPtr pClientRec = (ClientRec *) managerData;
- #ifdef DEBUG
- (void) printf ("Received SAVE YOURSELF DONE [%d] - Success = %s\n",
- smsConn, success ? "True" : "False");
- #endif /* DEBUG */
- if (!smXSMP.saveState.inProgress) {
- /*
- * The client is responding to the start-up SaveYourself
- * message - this isn't a user-initiated save.
- */
- SmsSaveComplete (smsConn);
- return;
- }
- /*
- * Cache success if it is a failure - it will be needed later
- */
- if (success == False)
- smXSMP.saveState.doneSuccess = False;
-
- pClientRec->saveYourselfDone = True;
- ProcessSaveYourselfResponses ();
- }
- static void
- ProcessSaveYourselfResponses (void)
- {
- ClientRecPtr pClientRec;
- Boolean done = False;
- /*
- * If all clients are marked as saveYourselfDone, complete
- * the save.
- */
- for (done = True, pClientRec = connectedList;
- pClientRec != NULL; pClientRec = pClientRec->next) {
- if (pClientRec->active &&
- pClientRec->saveYourselfDone == False) {
- done = False;
- break;
- }
- }
- if (done) {
- if (smXSMP.saveState.shutdownCanceled)
- CancelShutdown ();
- else
- CompleteXSMPSave ();
- return;
- }
-
- /*
- * If any client is marked as not having sent a
- * SaveYourselfDone message and it is has not been
- * marked as having requested a SaveYourselfP2,
- * then return.
- */
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active &&
- pClientRec->saveYourselfDone == False &&
- pClientRec->saveYourselfP2Requested == False)
- return;
- }
- /*
- * Only clients which requested a SaveYourselfP2 have not
- * responded with a SaveYourselfDone message.
- *
- * Tell the P2 clients to save themselves.
- */
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- if (pClientRec->saveYourselfP2Requested &&
- !pClientRec->saveYourselfDone) {
- #ifdef DEBUG
- (void) printf ("\tSent SaveYourselfPhase2 to %d\n",
- pClientRec->smConn);
- #endif /* DEBUG */
- SmsSaveYourselfPhase2 (pClientRec->smConn);
- }
- }
- }
- }
- /*ARGSUSED*/
- void
- CloseConnectionProc (
- SmsConn smsConn,
- SmPointer managerData,
- int count,
- char **reasonMsgs)
- {
- ClientRecPtr pClientRec = (ClientRec *) managerData;
- ClientRecPtr tmp = pClientRec;
- #ifdef DEBUG
- int i;
- (void) printf ("Received CONNECTION CLOSED [%d]\n", smsConn);
- for (i = 0; i < count; i++)
- (void) printf ("\tReason [%2d]: %s\n", i+1, reasonMsgs[i]);
- #endif /* DEBUG */
- if (count > 0) {
- PostReasonsDialog (GetArrayPropertyValue (tmp, SmProgram), count, reasonMsgs, True);
- SmFreeReasons (count, reasonMsgs);
- }
- CloseDownClient (pClientRec);
- }
- void
- CompleteXSMPSave (void)
- {
- ClientRecPtr pClientRec;
- /*
- * Save the XSMP clients' state and the Proxy clients' state
- * and save the rest of the settings, resources, etc.
- */
- CompleteSave ();
- /*
- * If this isn't a shutdown, tell the clients that the save
- * is complete.
- */
- if (!smXSMP.saveState.shutdown) {
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- SmsSaveComplete (pClientRec->smConn);
- #ifdef DEBUG
- printf ("SENT SmsSaveComplete to: %d\n",
- pClientRec->smConn);
- #endif
- }
- }
- }
- if (!smXSMP.saveState.shutdown) {
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- pClientRec->saveYourselfDone = False;
- pClientRec->saveYourselfP2Requested = False;
- pClientRec->interactRequested = False;
- }
- }
- InitializeSaveState (False);
- } else {
- int restartHint;
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- SmsDie (pClientRec->smConn);
- #ifdef DEBUG
- printf ("SENT SmsDie to: %d\n",
- pClientRec->smConn);
- #endif
- }
- if (!GetCardPropertyValue (pClientRec,
- SmRestartStyleHint,
- &restartHint))
- restartHint = pClientRec->restartHint;
- if (restartHint == SmRestartAnyway)
- ExecuteCommandProperty (SmShutdownCommand,
- pClientRec);
- }
- /*
- * Cannot exit until all of the clients go away.
- */
- smXSMP.saveState.saveComplete = True;
- return;
- }
- }
- static
- void FreeProps (
- PropertyRecPtr pProp)
- {
- PropertyRecPtr tmp;
- PropertyRecPtr trail;
- int i;
- for (tmp = pProp; tmp != NULL; ) {
- for (i = 0; i < tmp->prop.num_vals; i++)
- XtFree (tmp->prop.vals[i].value);
- if (tmp->prop.num_vals > 0)
- XtFree ((char *) tmp->prop.vals);
- trail = tmp;
- tmp = tmp->next;
- XtFree ((char *) trail);
- }
- }
- void CloseDownClient (
- ClientRecPtr pClientRec )
- {
- int restartHint;
- ClientRecPtr tmp, trail;
- SmsConn oldConn;
- SmsCleanUp (pClientRec->smConn);
- IceSetShutdownNegotiation (pClientRec->iceConn, False);
- IceCloseConnection (pClientRec->iceConn);
- /* save connection information for later compare */
- oldConn = pClientRec->smConn;
- pClientRec->iceConn = NULL;
- pClientRec->smConn = NULL;
- pClientRec->active = False;
- if (!GetCardPropertyValue (pClientRec, SmRestartStyleHint,
- &restartHint))
- restartHint = pClientRec->restartHint;
- if (!smXSMP.saveState.inProgress && restartHint == SmRestartImmediately)
- ExecuteCommandProperty (SmRestartCommand, pClientRec);
- if (restartHint == SmRestartAnyway)
- ExecuteCommandProperty (SmResignCommand, pClientRec);
- if (restartHint == SmRestartNever) {
- /*
- * Remove the client from the list
- */
- for (tmp = trail = connectedList; tmp != NULL;
- trail = tmp, tmp = tmp->next) {
- if (tmp->smConn == oldConn) {
- FreeProps (pClientRec->props);
- if (tmp == connectedList)
- connectedList = tmp->next;
- trail->next = tmp->next;
- XtFree ((char *) tmp);
- break;
- }
- }
- }
- /*
- * If a shutdown is occurring and all of the clients
- * are inactive, exit.
- */
- if (smXSMP.saveState.shutdown) {
- /*
- * Return if any clients are still active
- */
- for (tmp = connectedList; tmp != NULL; tmp = tmp->next) {
- if (tmp->active) {
- return;
- }
- }
- /*
- * All clients are inactive - its time to exit
- */
- _DtReleaseLock (smGD.display, SM_RUNNING_LOCK);
- SM_EXIT (0);
- }
- }
- /*ARGSUSED*/
- static
- Tt_callback_action GetWsmClientsHandler(
- Tt_message message,
- Tt_pattern pattern)
- {
- int lenClientIds;
- int num_args = tt_message_args_count (message);
- #ifdef DEBUG
- char * pchar;
- int i;
- #endif
- if (num_args != 3) {
- smXSMP.saveState.numClientIds = 0;
- smXSMP.saveState.clientIds = NULL;
- smXSMP.saveState.workspaceNums = NULL;
- ProcessInteract (smXSMP.saveState.interactClient, False);
- return (TT_CALLBACK_PROCESSED);
- }
- /*
- * Before extracting the new values from this message, free any
- * old values.
- */
- if (smXSMP.saveState.clientIds)
- free (smXSMP.saveState.clientIds);
- if (smXSMP.saveState.workspaceNums)
- free (smXSMP.saveState.workspaceNums);
- tt_message_arg_ival (message, 0,
- &smXSMP.saveState.numClientIds);
- tt_message_arg_bval (message, 1,
- (unsigned char **) &smXSMP.saveState.clientIds,
- &lenClientIds);
- tt_message_arg_bval (message, 2,
- (unsigned char **) &smXSMP.saveState.workspaceNums,
- &lenClientIds);
- tt_message_reply (message);
- tt_message_destroy (message);
- #ifdef DEBUG
- (void) printf("GetWsmClientsHandler: num clients = %d\n",
- smXSMP.saveState.numClientIds);
- for (i = 0, pchar = smXSMP.saveState.clientIds;
- i < smXSMP.saveState.numClientIds;
- i++, pchar += strlen (pchar) + 1) {
- (void) printf("\tclient [%2d]: workspace = %2d, id = %s\n",
- i+1, smXSMP.saveState.workspaceNums[i], pchar);
- }
- #endif
- ProcessInteract (smXSMP.saveState.interactClient, True);
- return (TT_CALLBACK_PROCESSED);
- }
- static
- Boolean SendGetWsmClientsMessage (void)
- {
- Tt_message message;
- Tt_status status;
- message = tt_message_create ();
- status = tt_ptr_error (message);
- if (status != TT_OK)
- return (False);
- tt_message_class_set (message, TT_REQUEST);
- tt_message_scope_set (message, TT_SESSION);
- tt_message_address_set (message, TT_PROCEDURE);
- tt_message_session_set (message, tt_default_session());
- tt_message_op_set (message, GET_CLIENT_WORKSPACE_MSG);
- tt_message_callback_add (message, GetWsmClientsHandler);
- /*
- * Three arguments are expected in the reply so apparently
- * they must be accounted for now.
- */
- tt_message_iarg_add (message, TT_OUT, "integer", 0);
- tt_message_barg_add (message, TT_OUT, "stringlist", 0, 0);
- tt_message_barg_add (message, TT_OUT, "intlist", 0, 0);
- status = tt_message_send (message);
- if (status != TT_OK)
- return (False);
- return (True);
- }
- static
- int GetCurrentWorkspaceNumber (void)
- {
- Atom currentWorkspace;
- Atom *workspaceList;
- Window root;
- int rval;
- int numWorkspaces;
- int i;
- root = XDefaultRootWindow (smGD.display);
- rval = DtWsmGetCurrentWorkspace(smGD.display, root, ¤tWorkspace);
- if (rval != Success)
- return (-1);
- rval = DtWsmGetWorkspaceList (smGD.display, root, &workspaceList,
- (int *) &numWorkspaces);
- if (rval != Success)
- return (-1);
- for (i = 0; i < numWorkspaces; i++) {
- if (currentWorkspace == workspaceList[i])
- return (currentWorkspace);
- }
- return (-1);
- }
- static
- void CancelShutdown (void)
- {
- ClientRecPtr pClientRec;
- char *pch;
- for (pClientRec = connectedList; pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->active) {
- ExecuteCommandProperty (SmDiscardCommand, pClientRec);
- pClientRec->saveYourselfDone = False;
- pClientRec->saveYourselfP2Requested = False;
- pClientRec->interactRequested = False;
- }
- }
- UndoSetSavePath ();
- InitializeSaveState (False);
- }
- /*
- * This function can be invoked via different paths:
- *
- * 1. From the InteractRequest callback
- * 2. From the InteractDone callback
- * 3. From the GetWsmClients message callback
- */
- static
- void ProcessInteract (
- ClientRecPtr client,
- Boolean getWsmClientOK)
- {
- int currentWorkspace;
- int i;
- ClientRecPtr pClientRec;
- ClientRecPtr tmp = NULL;
- char *pchar;
- if (!getWsmClientOK) {
- smXSMP.saveState.clientInteracting = True;
- SmsInteract (client->smConn);
- return;
- }
- /*
- * If a client wants to interact and its workspace matches
- * the current workspace, then let it interact.
- */
- currentWorkspace = GetCurrentWorkspaceNumber ();
- for (pClientRec = connectedList;
- pClientRec != NULL;
- pClientRec = pClientRec->next) {
- if (pClientRec->interactRequested) {
- tmp = pClientRec;
- for (i = 0, pchar = smXSMP.saveState.clientIds;
- i < smXSMP.saveState.numClientIds;
- i++, pchar += strlen (pchar) + 1) {
- if ((currentWorkspace ==
- smXSMP.saveState.workspaceNums[i]) &&
- (!strcmp (pchar, pClientRec->clientId))) {
- smXSMP.saveState.clientInteracting =
- True;
- SmsInteract (pClientRec->smConn);
- return;
- }
- }
- }
- }
- /*
- * Tmp didn't meet all of the requirements but it does
- * want to interact so let it.
- */
- if (tmp) {
- smXSMP.saveState.clientInteracting = True;
- SmsInteract (tmp->smConn);
- }
- }
- /*
- * List manipulation functions
- */
- void AddClient (
- ClientRecPtr newClient)
- {
- ClientRecPtr pClient;
- if (!connectedList) {
- connectedList = newClient;
- return;
- }
- /*
- * Find the end of the list
- */
- for (pClient = connectedList; pClient->next != NULL;
- pClient = pClient->next);
- pClient->next = newClient;
- }
- /*
- * The real way to handle IO errors is to check the return status
- * of IceProcessMessages. dtsession properly does this.
- *
- * Unfortunately, a design flaw exists in the ICE library in which
- * a default IO error handler is invoked if no IO error handler is
- * installed. This default handler exits. We must avoid this.
- *
- * To get around this problem, we install an IO error handler that
- * does a little magic. Since a previous IO handler might have been
- * installed, when we install our IO error handler, we do a little
- * trick to get both the previous IO error handler and the default
- * IO error handler. When our IO error handler is called, if the
- * previous handler is not the default handler, we call it. This
- * way, everyone's IO error handler gets called except the stupid
- * default one which does an exit!
- */
- static IceIOErrorHandler prev_handler;
- void
- MyIoErrorHandler (
- IceConn ice_conn)
- {
- if (prev_handler)
- (*prev_handler) (ice_conn);
- }
- void
- InstallIOErrorHandler (void)
- {
- IceIOErrorHandler default_handler;
- prev_handler = IceSetIOErrorHandler (NULL);
- default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
- if (prev_handler == default_handler)
- prev_handler = NULL;
- }
- void XSMPExit (void)
- {
- char * pchar;
- if (authenticationInitialized)
- FreeAuthenticationData (smXSMP.numTransports,
- smXSMP.authDataEntries);
- /*
- * If the local socket file exists, remove it.
- *
- * Assume the format of networkIds is:
- *
- * local/<host_name>:/<socket_file_name>,<other_stuff>
- */
- if (!strncmp (networkIds, "local/", 6)) {
- if (pchar = strchr (networkIds, ':')) {
- pchar++;
- if (pchar && *pchar != '\000') {
- char * pchar2;
- if (pchar2 = strchr (pchar, ',')) {
- struct stat buf;
- /*
- * This modifies networkIds but
- * that's OK because an exit is
- * about to happen.
- */
- *pchar2 = '\000';
- if ((stat (pchar, &buf)) == 0) {
- (void) unlink (pchar);
- }
- }
- }
- }
- }
- }
|