1408 lines
31 KiB
C
1408 lines
31 KiB
C
/* $Xorg: save.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
|
||
/******************************************************************************
|
||
|
||
Copyright 1993, 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.
|
||
******************************************************************************/
|
||
/* $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 <X11/Shell.h>
|
||
#include <X11/Xaw/Form.h>
|
||
#include <X11/Xaw/List.h>
|
||
#include <X11/Xaw/Command.h>
|
||
#include <X11/Xaw/Toggle.h>
|
||
#include <X11/Xaw/AsciiText.h>
|
||
|
||
|
||
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
|
||
("<Key>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);
|
||
}
|
||
}
|
||
}
|