/* $Xorg: save.c,v 1.4 2000/08/17 19:55:06 cpqbld Exp $ */ /****************************************************************************** Copyright 1993, 1998 The Open Group All Rights Reserved. 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. ******************************************************************************/ /* $XFree86: xc/programs/xsm/save.c,v 3.3 2001/01/17 23:46:30 dawes Exp $ */ #include "xsm.h" #include "save.h" #include "saveutil.h" #include "popup.h" #include "info.h" #include "lock.h" #include "choose.h" #include #include #include #include #include #include Widget savePopup; Widget saveForm; Widget saveMessageLabel; Widget saveName; Widget saveTypeLabel; Widget saveTypeGlobal; Widget saveTypeLocal; Widget saveTypeBoth; Widget interactStyleLabel; Widget interactStyleNone; Widget interactStyleErrors; Widget interactStyleAny; Widget saveOkButton; Widget helpSaveButton; Widget saveCancelButton; Widget helpPopup; Widget helpForm; Widget helpSaveText; Widget helpSaveOkButton; Widget nameInUsePopup; Widget nameInUseForm; Widget nameInUseLabel; Widget nameInUseOverwriteButton; Widget nameInUseCancelButton; Widget badSavePopup; Widget badSaveForm; Widget badSaveLabel; Widget badSaveOkButton; Widget badSaveCancelButton; Widget badSaveListWidget; extern Widget clientInfoPopup; extern Widget clientPropPopup; extern Widget nameSessionPopup; extern int checkpoint_from_signal; static int saveTypeData[] = { SmSaveLocal, SmSaveGlobal, SmSaveBoth }; static int interactStyleData[] = { SmInteractStyleNone, SmInteractStyleErrors, SmInteractStyleAny }; static String *failedNames = NULL; static int numFailedNames = 0; static Bool help_visible = False; static String name_in_use = NULL; static Bool name_locked = False; static void MakeCurrentSession(String new_name, Bool name_changed) { char title[256]; List *cl; if (session_name) { /* * In the old session, for any client that was not restarted by the * session manager (previous ID was NULL), if we did not issue a * checkpoint to this client after the initial startup, remove the * client's checkpoint file using the discard command. */ for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { ClientRec *client = (ClientRec *) cl->thing; if (!client->restarted && !client->userIssuedCheckpoint && client->discardCommand) { execute_system_command (client->discardCommand); XtFree (client->discardCommand); client->discardCommand = NULL; } } /* * Unlock the old session. */ if (!need_to_name_session) UnlockSession (session_name); } if (name_changed) { if (session_name) XtFree (session_name); session_name = XtNewString (new_name); } LockSession (session_name, True); sprintf (title, "xsm: %s", session_name); XtVaSetValues (topLevel, XtNtitle, title, NULL); set_session_save_file_name (session_name); /* * For each client, set the DiscardCommand ptr to NULL. * This is so when we do a checkpoint with the new session * name, we don't wipe out the checkpoint files needed by * the previous session. We also set the userIssuedCheckpoint * flag to false for each client in the new session. */ for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { ClientRec *client = (ClientRec *) cl->thing; client->userIssuedCheckpoint = False; if (client->discardCommand) { XtFree (client->discardCommand); client->discardCommand = NULL; } } need_to_name_session = False; } #define NAME_OK 0 #define NAME_EMPTY 1 #define NAME_EXISTS 2 #define NAME_LOCKED 3 static int GetSaveName(String *nameRet) { String new_name = NULL; Bool name_changed; /* * Get the name of the session for the save */ XtVaGetValues (saveName, XtNstring, &new_name, NULL); *nameRet = new_name; if (!new_name || *new_name == '\0') return (NAME_EMPTY); /* * See if this is a new session. If not return. */ name_changed = !session_name || (session_name && strcmp (session_name, new_name) != 0); if (!need_to_name_session && !name_changed) return (NAME_OK); /* * Make sure the session name is unique. */ if (GetSessionNames (&sessionNameCount, &sessionNamesShort, NULL, &sessionsLocked)) { int i, no_good = 0, locked = 0; for (i = 0; i < sessionNameCount; i++) if (strcmp (new_name, sessionNamesShort[i]) == 0) { no_good = 1; locked = sessionsLocked[i]; break; } FreeSessionNames (sessionNameCount, sessionNamesShort, NULL, sessionsLocked); if (no_good) return (locked ? NAME_LOCKED : NAME_EXISTS); } MakeCurrentSession (new_name, name_changed); return (NAME_OK); } static void GetSaveOptions(int *saveType, int *interactStyle, Bool *fast) { XtPointer ptr; if (help_visible) { XtPopdown (helpPopup); help_visible = 0; } ptr = XawToggleGetCurrent (saveTypeLocal /* just 1 of the group */); *saveType = *((int *) ptr); ptr = XawToggleGetCurrent (interactStyleNone /* just 1 of the group */); *interactStyle = *((int *) ptr); *fast = False; } void DoSave(int saveType, int interactStyle, Bool fast) { ClientRec *client; List *cl; char *_saveType; char *_shutdown; char *_interactStyle; if (saveType == SmSaveLocal) _saveType = "Local"; else if (saveType == SmSaveGlobal) _saveType = "Global"; else _saveType = "Both"; if (wantShutdown) _shutdown = "True"; else _shutdown = "False"; if (interactStyle == SmInteractStyleNone) _interactStyle = "None"; else if (interactStyle == SmInteractStyleErrors) _interactStyle = "Errors"; else _interactStyle = "Any"; SetSaveSensitivity (False); saveInProgress = True; shutdownCancelled = False; phase2InProgress = False; if (ListCount (RunningList) == 0) FinishUpSave (); for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; SmsSaveYourself (client->smsConn, saveType, wantShutdown, interactStyle, fast); ListAddLast (WaitForSaveDoneList, (char *) client); client->userIssuedCheckpoint = True; client->receivedDiscardCommand = False; if (verbose) { printf ("Client Id = %s, sent SAVE YOURSELF [", client->clientId); printf ("Save Type = %s, Shutdown = %s, ", _saveType, _shutdown); printf ("Interact Style = %s, Fast = False]\n", _interactStyle); } } if (verbose) { printf ("\n"); printf ("Sent SAVE YOURSELF to all clients. Waiting for\n"); printf ("SAVE YOURSELF DONE, INTERACT REQUEST, or\n"); printf ("SAVE YOURSELF PHASE 2 REQUEST from each client.\n"); printf ("\n"); } } static void SaveOkAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XtCallCallbacks (saveOkButton, XtNcallback, NULL); } static void DelSaveWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XtCallCallbacks (saveCancelButton, XtNcallback, NULL); } static void DelNameInUseWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XtCallCallbacks (nameInUseCancelButton, XtNcallback, NULL); } static void DelBadSaveWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { if (XtIsManaged (badSaveCancelButton)) XtCallCallbacks (badSaveCancelButton, XtNcallback, NULL); else XtCallCallbacks (badSaveOkButton, XtNcallback, NULL); } static void DelSaveHelpWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XtCallCallbacks (helpSaveOkButton, XtNcallback, NULL); } static void SaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) { String name = NULL; char label[256]; int status; static int first_time = 1; int saveType; int interactStyle; Bool fast; if ((status = GetSaveName (&name)) != NAME_OK) { #ifdef XKB XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue); #else XBell (XtDisplay (topLevel), 0); #endif if (status == NAME_EXISTS || status == NAME_LOCKED) { name_in_use = name; if (status == NAME_LOCKED) { name_locked = True; sprintf (label, "Another session by the name '%s' is active.\nChoose another name for the session.", name); XtUnmanageChild (nameInUseOverwriteButton); XtVaSetValues (nameInUseCancelButton, XtNlabel, "OK", XtNfromHoriz, NULL, NULL); } else { name_locked = False; sprintf (label, "Another session by the name '%s' already exists.\nWould you like to overwrite it?", name); XtManageChild (nameInUseOverwriteButton); XtVaSetValues (nameInUseCancelButton, XtNlabel, "Cancel", XtNfromHoriz, nameInUseOverwriteButton, NULL); } XtVaSetValues (nameInUseLabel, XtNlabel, label, NULL); XtPopdown (savePopup); PopupPopup (mainWindow, nameInUsePopup, True, first_time, 25, 100, "DelNameInUseWinAction()"); if (first_time) first_time = 0; } return; } GetSaveOptions (&saveType, &interactStyle, &fast); DoSave (saveType, interactStyle, fast); } void LetClientInteract(List *cl) { ClientRec *client = (ClientRec *) cl->thing; SmsInteract (client->smsConn); ListSearchAndFreeOne (WaitForInteractList, (char *) client); if (verbose) { printf ("Client Id = %s, sent INTERACT\n", client->clientId); } } void StartPhase2(void) { List *cl; if (verbose) { printf ("\n"); printf ("Starting PHASE 2 of SAVE YOURSELF\n"); printf ("\n"); } for (cl = ListFirst (WaitForPhase2List); cl; cl = ListNext (cl)) { ClientRec *client = (ClientRec *) cl->thing; SmsSaveYourselfPhase2 (client->smsConn); if (verbose) { printf ("Client Id = %s, sent SAVE YOURSELF PHASE 2", client->clientId); } } ListFreeAllButHead (WaitForPhase2List); phase2InProgress = True; } void FinishUpSave(void) { ClientRec *client; List *cl; if (verbose) { printf ("\n"); printf ("All clients issued SAVE YOURSELF DONE\n"); printf ("\n"); } saveInProgress = False; phase2InProgress = False; /* * Now execute discard commands */ for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; if (!client->receivedDiscardCommand) continue; if (client->discardCommand) { execute_system_command (client->discardCommand); XtFree (client->discardCommand); client->discardCommand = NULL; } if (client->saveDiscardCommand) { client->discardCommand = client->saveDiscardCommand; client->saveDiscardCommand = NULL; } } /* * Write the save file */ WriteSave (sm_id); if (wantShutdown && shutdownCancelled) { shutdownCancelled = False; } else if (wantShutdown) { if (ListCount (RunningList) == 0) EndSession (0); shutdownInProgress = True; for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; SmsDie (client->smsConn); if (verbose) { printf ("Client Id = %s, sent DIE\n", client->clientId); } } } else { for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; SmsSaveComplete (client->smsConn); if (verbose) { printf ("Client Id = %s, sent SAVE COMPLETE\n", client->clientId); } } } if (!shutdownInProgress) { XtPopdown (savePopup); SetAllSensitive (1); if (checkpoint_from_signal) checkpoint_from_signal = False; } } static void SaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) { XtPopdown (savePopup); if (help_visible) { XtPopdown (helpPopup); help_visible = 0; } SetAllSensitive (1); } /* * Add toggle button */ static Widget AddToggle(char *widgetName, Widget parent, int state, Widget radioGroup, XtPointer radioData, Widget fromHoriz, Widget fromVert) { Widget toggle; toggle = XtVaCreateManagedWidget ( widgetName, toggleWidgetClass, parent, XtNstate, state, XtNradioGroup, radioGroup, XtNradioData, radioData, XtNfromHoriz, fromHoriz, XtNfromVert, fromVert, NULL); return (toggle); } void SetSaveSensitivity(Bool on) { XtSetSensitive (savePopup, on); #if 0 /* * When we turn of sensitivity in the save dialog, we want to keep * the cancel button sensitive (so the user can cancel in case of * a problem). Unfortunately, we can not turn off the sensitivity on * the save popup, and then just turn on sensitivity for the cancel * button. We must do each widget individually. */ XtSetSensitive (saveTypeLabel, on); XtSetSensitive (saveTypeGlobal, on); XtSetSensitive (saveTypeLocal, on); XtSetSensitive (saveTypeBoth, on); XtSetSensitive (interactStyleLabel, on); XtSetSensitive (interactStyleNone, on); XtSetSensitive (interactStyleErrors, on); XtSetSensitive (interactStyleAny, on); XtSetSensitive (saveOkButton, on); #endif } void SavePopupStructureNotifyXtHandler(Widget w, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch) { if (event->type == MapNotify) { /* * Now that the Save Dialog is back up, we can do the save. */ int saveType; int interactStyle; Bool fast; if (name_locked) { /* Force shutdown */ } DeleteSession (name_in_use); MakeCurrentSession (name_in_use, True); name_in_use = NULL; GetSaveOptions (&saveType, &interactStyle, &fast); DoSave (saveType, interactStyle, fast); XtRemoveEventHandler (savePopup, StructureNotifyMask, False, SavePopupStructureNotifyXtHandler, NULL); } } static void NameInUseOverwriteXtProc(Widget w, XtPointer client_data, XtPointer callData) { if (name_locked) { /* force shutdown not implemented yet */ return; } XtPopdown (nameInUsePopup); /* * We want to popup the Save dialog again. In order to avoid a race * condition with the BadSave handler trying to pop down the Save Dialog, * we wait for the MapNotify on the Save dialog, and then do the save. */ XtAddEventHandler (savePopup, StructureNotifyMask, False, SavePopupStructureNotifyXtHandler, NULL); XtPopup (savePopup, XtGrabNone); } static void NameInUseCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) { XtPopdown (nameInUsePopup); XtPopup (savePopup, XtGrabNone); name_in_use = NULL; } static void BadSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) { ListFreeAllButHead (FailedSaveList); XtPopdown (badSavePopup); FinishUpSave (); } static void BadSaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) { ListFreeAllButHead (FailedSaveList); XtPopdown (badSavePopup); if (wantShutdown) { List *cl; shutdownCancelled = True; for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { ClientRec *client = (ClientRec *) cl->thing; SmsShutdownCancelled (client->smsConn); if (verbose) { printf ("Client Id = %s, sent SHUTDOWN CANCELLED\n", client->clientId); } } } FinishUpSave (); } static void BadSaveListXtProc(Widget w, XtPointer client_data, XtPointer callData) { } static void HelpSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) { static int first_time = 1; if (help_visible) { /* Make sure it is visible */ XMapRaised (XtDisplay (topLevel), XtWindow (helpPopup)); } else { PopupPopup (savePopup, helpPopup, True, first_time, 50, 50, "DelSaveHelpWinAction()"); help_visible = 1; if (first_time) first_time = 0; } } static void HelpSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) { XtPopdown (helpPopup); help_visible = 0; } void create_save_popup(void) { XtTranslations translations; static XtActionsRec actions[] = { {"SaveOkAction", SaveOkAction}, {"DelSaveWinAction", DelSaveWinAction}, {"DelNameInUseWinAction", DelNameInUseWinAction}, {"DelBadSaveWinAction", DelBadSaveWinAction}, {"DelSaveHelpWinAction", DelSaveHelpWinAction} }; /* * Pop up for Save Yourself button. */ savePopup = XtVaCreatePopupShell ( "savePopup", transientShellWidgetClass, topLevel, XtNallowShellResize, True, NULL); saveForm = XtCreateManagedWidget ( "saveForm", formWidgetClass, savePopup, NULL, 0); saveMessageLabel = XtVaCreateManagedWidget ( "saveMessageLabel", labelWidgetClass, saveForm, XtNfromHoriz, NULL, XtNfromVert, NULL, XtNborderWidth, 0, NULL); saveName = XtVaCreateManagedWidget ( "saveName", asciiTextWidgetClass, saveForm, XtNfromVert, NULL, XtNeditType, XawtextEdit, XtNresizable, True, XtNresize, XawtextResizeWidth, NULL); saveTypeLabel = XtVaCreateManagedWidget ( "saveTypeLabel", labelWidgetClass, saveForm, XtNfromHoriz, NULL, XtNfromVert, saveMessageLabel, XtNborderWidth, 0, XtNvertDistance, 20, NULL); saveTypeLocal = AddToggle ( "saveTypeLocal", /* widgetName */ saveForm, /* parent */ 0, /* state */ NULL, /* radioGroup */ (XtPointer) &saveTypeData[0], /* radioData */ saveTypeLabel, /* fromHoriz */ saveMessageLabel /* fromVert */ ); saveTypeGlobal = AddToggle ( "saveTypeGlobal", /* widgetName */ saveForm, /* parent */ 0, /* state */ saveTypeLocal, /* radioGroup */ (XtPointer) &saveTypeData[1], /* radioData */ saveTypeLocal, /* fromHoriz */ saveMessageLabel /* fromVert */ ); saveTypeBoth = AddToggle ( "saveTypeBoth", /* widgetName */ saveForm, /* parent */ 1, /* state */ saveTypeLocal, /* radioGroup */ (XtPointer) &saveTypeData[2], /* radioData */ saveTypeGlobal, /* fromHoriz */ saveMessageLabel /* fromVert */ ); XtVaSetValues (saveName, XtNfromHoriz, saveTypeLabel, NULL); XtVaSetValues (saveTypeLocal, XtNvertDistance, 20, NULL); XtVaSetValues (saveTypeGlobal, XtNvertDistance, 20, NULL); XtVaSetValues (saveTypeBoth, XtNvertDistance, 20, NULL); interactStyleLabel = XtVaCreateManagedWidget ( "interactStyleLabel", labelWidgetClass, saveForm, XtNfromHoriz, NULL, XtNfromVert, saveTypeLabel, XtNborderWidth, 0, NULL); interactStyleNone = AddToggle ( "interactStyleNone", /* widgetName */ saveForm, /* parent */ 0, /* state */ NULL, /* radioGroup */ (XtPointer) &interactStyleData[0], /* radioData */ saveTypeLabel, /* fromHoriz */ saveTypeLabel /* fromVert */ ); interactStyleErrors = AddToggle ( "interactStyleErrors", /* widgetName */ saveForm, /* parent */ 0, /* state */ interactStyleNone, /* radioGroup */ (XtPointer) &interactStyleData[1], /* radioData */ interactStyleNone, /* fromHoriz */ saveTypeLabel /* fromVert */ ); interactStyleAny = AddToggle ( "interactStyleAny", /* widgetName */ saveForm, /* parent */ 1, /* state */ interactStyleNone, /* radioGroup */ (XtPointer) &interactStyleData[2], /* radioData */ interactStyleErrors, /* fromHoriz */ saveTypeLabel /* fromVert */ ); saveOkButton = XtVaCreateManagedWidget ( "saveOkButton", commandWidgetClass, saveForm, XtNfromHoriz, NULL, XtNfromVert, interactStyleLabel, XtNvertDistance, 20, XtNresizable, True, NULL); XtAddCallback (saveOkButton, XtNcallback, SaveOkXtProc, 0); helpSaveButton = XtVaCreateManagedWidget ( "helpSaveButton", commandWidgetClass, saveForm, XtNfromHoriz, saveOkButton, XtNfromVert, interactStyleLabel, XtNvertDistance, 20, NULL); XtAddCallback (helpSaveButton, XtNcallback, HelpSaveXtProc, 0); saveCancelButton = XtVaCreateManagedWidget ( "saveCancelButton", commandWidgetClass, saveForm, XtNfromHoriz, helpSaveButton, XtNfromVert, interactStyleLabel, XtNvertDistance, 20, NULL); XtAddCallback (saveCancelButton, XtNcallback, SaveCancelXtProc, 0); XtSetKeyboardFocus (saveForm, saveName); XtAppAddActions (appContext, actions, XtNumber (actions)); translations = XtParseTranslationTable ("Return: SaveOkAction()\n"); XtOverrideTranslations(saveName, translations); XtInstallAllAccelerators (saveForm, saveForm); /* * Pop up when user tries to save the session under an * already used name. */ nameInUsePopup = XtVaCreatePopupShell ( "nameInUsePopup", transientShellWidgetClass, topLevel, XtNallowShellResize, True, NULL); nameInUseForm = XtVaCreateManagedWidget ( "nameInUseForm", formWidgetClass, nameInUsePopup, NULL); nameInUseLabel = XtVaCreateManagedWidget ( "nameInUseLabel", labelWidgetClass, nameInUseForm, XtNresizable, True, XtNfromHoriz, NULL, XtNfromVert, NULL, XtNborderWidth, 0, XtNtop, XawChainTop, XtNbottom, XawChainTop, NULL); nameInUseOverwriteButton = XtVaCreateManagedWidget ( "nameInUseOverwriteButton", commandWidgetClass, nameInUseForm, XtNfromHoriz, NULL, XtNfromVert, nameInUseLabel, XtNtop, XawChainBottom, XtNbottom, XawChainBottom, NULL); XtAddCallback (nameInUseOverwriteButton, XtNcallback, NameInUseOverwriteXtProc, 0); nameInUseCancelButton = XtVaCreateManagedWidget ( "nameInUseCancelButton", commandWidgetClass, nameInUseForm, XtNresizable, True, XtNfromHoriz, nameInUseOverwriteButton, XtNfromVert, nameInUseLabel, XtNtop, XawChainBottom, XtNbottom, XawChainBottom, NULL); XtAddCallback (nameInUseCancelButton, XtNcallback, NameInUseCancelXtProc, 0); /* * Pop up for help. */ helpPopup = XtVaCreatePopupShell ( "helpPopup", transientShellWidgetClass, topLevel, NULL); helpForm = XtVaCreateManagedWidget ( "helpForm", formWidgetClass, helpPopup, NULL); helpSaveText = XtVaCreateManagedWidget ( "helpSaveText", labelWidgetClass, helpForm, XtNfromHoriz, NULL, XtNfromVert, NULL, XtNtop, XawChainTop, XtNbottom, XawChainTop, NULL); helpSaveOkButton = XtVaCreateManagedWidget ( "helpSaveOkButton", commandWidgetClass, helpForm, XtNfromHoriz, NULL, XtNfromVert, helpSaveText, XtNtop, XawChainBottom, XtNbottom, XawChainBottom, XtNvertDistance, 20, NULL); XtAddCallback (helpSaveOkButton, XtNcallback, HelpSaveOkXtProc, 0); /* * Pop up when not all clients returned SaveSuccess */ badSavePopup = XtVaCreatePopupShell ( "badSavePopup", transientShellWidgetClass, topLevel, XtNallowShellResize, True, NULL); badSaveForm = XtVaCreateManagedWidget ( "badSaveForm", formWidgetClass, badSavePopup, NULL); badSaveLabel = XtVaCreateManagedWidget ( "badSaveLabel", labelWidgetClass, badSaveForm, XtNfromHoriz, NULL, XtNfromVert, NULL, XtNborderWidth, 0, XtNtop, XawChainTop, XtNbottom, XawChainTop, NULL); badSaveListWidget = XtVaCreateManagedWidget ( "badSaveListWidget", listWidgetClass, badSaveForm, XtNresizable, True, XtNdefaultColumns, 1, XtNforceColumns, True, XtNfromHoriz, NULL, XtNfromVert, badSaveLabel, XtNtop, XawChainTop, XtNbottom, XawChainBottom, NULL); XtAddCallback (badSaveListWidget, XtNcallback, BadSaveListXtProc, 0); badSaveOkButton = XtVaCreateManagedWidget ( "badSaveOkButton", commandWidgetClass, badSaveForm, XtNfromHoriz, NULL, XtNfromVert, badSaveListWidget, XtNtop, XawChainBottom, XtNbottom, XawChainBottom, NULL); XtAddCallback (badSaveOkButton, XtNcallback, BadSaveOkXtProc, 0); badSaveCancelButton = XtVaCreateManagedWidget ( "badSaveCancelButton", commandWidgetClass, badSaveForm, XtNfromHoriz, badSaveOkButton, XtNfromVert, badSaveListWidget, XtNtop, XawChainBottom, XtNbottom, XawChainBottom, NULL); XtAddCallback (badSaveCancelButton, XtNcallback, BadSaveCancelXtProc, 0); XtInstallAllAccelerators (badSaveForm, badSaveForm); } void PopupSaveDialog(void) { static int first_time = 1; XtSetSensitive (mainWindow, 0); XtSetSensitive (clientInfoPopup, 0); XtSetSensitive (clientPropPopup, 0); XawToggleSetCurrent (saveTypeBoth, (XtPointer) &saveTypeData[2]); XawToggleSetCurrent (interactStyleAny, (XtPointer) &interactStyleData[2]); XtVaSetValues (savePopup, XtNtitle, wantShutdown ? "Shutdown" : "Checkpoint", NULL); XtVaSetValues (saveName, XtNstring, need_to_name_session ? "" : session_name, NULL); XtVaSetValues (saveOkButton, XtNlabel, wantShutdown ? "Shutdown" : "Checkpoint", NULL); PopupPopup (mainWindow, savePopup, True, first_time, 25, 100, "DelSaveWinAction()"); if (first_time) first_time = 0; } void CheckPointXtProc(Widget w, XtPointer client_data, XtPointer callData) { wantShutdown = False; PopupSaveDialog (); } void ShutdownSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) { wantShutdown = True; PopupSaveDialog (); } void PopupBadSave(void) { ClientRec *client; char *progName, *hostname, *tmp1, *tmp2; String clientInfo; int maxlen1, maxlen2; char extraBuf1[80], extraBuf2[80]; char *restart_service_prop; List *cl, *pl; int i, k; static int first_time = 1; if (failedNames) { /* * Free the previous list of names. Xaw doesn't make a copy of * our list, so we need to keep it around. */ for (i = 0; i < numFailedNames; i++) XtFree (failedNames[i]); XtFree ((char *) failedNames); failedNames = NULL; } maxlen1 = maxlen2 = 0; numFailedNames = 0; for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; progName = NULL; restart_service_prop = NULL; for (pl = ListFirst (client->props); pl; pl = ListNext (pl)) { Prop *pprop = (Prop *) pl->thing; List *vl = ListFirst (pprop->values); PropValue *pval = (PropValue *) vl->thing; if (strcmp (pprop->name, SmProgram) == 0) { progName = GetProgramName ((char *) pval->value); if ((int) strlen (progName) > maxlen1) maxlen1 = strlen (progName); } else if (strcmp (pprop->name, "_XC_RestartService") == 0) { restart_service_prop = (char *) pval->value; } } if (!progName) continue; if (restart_service_prop) tmp1 = restart_service_prop; else if (client->clientHostname) tmp1 = client->clientHostname; else continue; if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL) hostname = tmp1; else hostname = tmp2 + 1; if ((int) strlen (hostname) > maxlen2) maxlen2 = strlen (hostname); numFailedNames++; } failedNames = (String *) XtMalloc ( numFailedNames * sizeof (String)); i = 0; for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl)) { ClientRec *client = (ClientRec *) cl->thing; int extra1, extra2; progName = NULL; restart_service_prop = NULL; for (pl = ListFirst (client->props); pl; pl = ListNext (pl)) { Prop *pprop = (Prop *) pl->thing; List *vl = ListFirst (pprop->values); PropValue *pval = (PropValue *) vl->thing; if (strcmp (pprop->name, SmProgram) == 0) { progName = GetProgramName ((char *) pval->value); } else if (strcmp (pprop->name, "_XC_RestartService") == 0) { restart_service_prop = (char *) pval->value; } } if (!progName) continue; if (restart_service_prop) tmp1 = restart_service_prop; else if (client->clientHostname) tmp1 = client->clientHostname; else continue; if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL) hostname = tmp1; else hostname = tmp2 + 1; extra1 = maxlen1 - strlen (progName) + 5; extra2 = maxlen2 - strlen (hostname); clientInfo = (String) XtMalloc (strlen (progName) + extra1 + extra2 + 3 + strlen (hostname) + 1); for (k = 0; k < extra1; k++) extraBuf1[k] = ' '; extraBuf1[extra1] = '\0'; for (k = 0; k < extra2; k++) extraBuf2[k] = ' '; extraBuf2[extra2] = '\0'; sprintf (clientInfo, "%s%s (%s%s)", progName, extraBuf1, hostname, extraBuf2); failedNames[i++] = clientInfo; if (client->freeAfterBadSavePopup) { FreeClient (client, True /* free props */); } } XawListChange (badSaveListWidget, failedNames, numFailedNames, 0, True); XtPopdown (savePopup); if (wantShutdown && !shutdownCancelled) XtManageChild (badSaveCancelButton); else XtUnmanageChild (badSaveCancelButton); PopupPopup (mainWindow, badSavePopup, True, first_time, 25, 100, "DelBadSaveWinAction()"); if (first_time) first_time = 0; } void ShutdownDontSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) { List *cl; ClientRec *client; if (ListCount (RunningList) == 0) EndSession (0); /* * For any client that was not restarted by the session * manager (previous ID was NULL), if we did not issue a * checkpoint to this client, remove the client's checkpoint * file using the discard command. */ for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; if (!client->restarted && !client->userIssuedCheckpoint && client->discardCommand) { execute_system_command (client->discardCommand); XtFree (client->discardCommand); client->discardCommand = NULL; } } shutdownInProgress = True; for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) { client = (ClientRec *) cl->thing; SmsDie (client->smsConn); if (verbose) { printf ("Client Id = %s, sent DIE\n", client->clientId); } } }