save.c revision 99c4c48a
1/* $Xorg: save.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */ 2/****************************************************************************** 3 4Copyright 1993, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25******************************************************************************/ 26/* $XFree86: xc/programs/xsm/save.c,v 3.3 2001/01/17 23:46:30 dawes Exp $ */ 27 28#include "xsm.h" 29#include "save.h" 30#include "saveutil.h" 31#include "popup.h" 32#include "info.h" 33#include "lock.h" 34#include "choose.h" 35 36#include <X11/Shell.h> 37#include <X11/Xaw/Form.h> 38#include <X11/Xaw/List.h> 39#include <X11/Xaw/Command.h> 40#include <X11/Xaw/Toggle.h> 41#include <X11/Xaw/AsciiText.h> 42 43 44static Widget savePopup; 45static Widget saveForm; 46static Widget saveMessageLabel; 47static Widget saveName; 48static Widget saveTypeLabel; 49static Widget saveTypeGlobal; 50static Widget saveTypeLocal; 51static Widget saveTypeBoth; 52static Widget interactStyleLabel; 53static Widget interactStyleNone; 54static Widget interactStyleErrors; 55static Widget interactStyleAny; 56static Widget saveOkButton; 57static Widget helpSaveButton; 58static Widget saveCancelButton; 59static Widget helpPopup; 60static Widget helpForm; 61static Widget helpSaveText; 62static Widget helpSaveOkButton; 63static Widget nameInUsePopup; 64static Widget nameInUseForm; 65static Widget nameInUseLabel; 66static Widget nameInUseOverwriteButton; 67static Widget nameInUseCancelButton; 68static Widget badSavePopup; 69static Widget badSaveForm; 70static Widget badSaveLabel; 71static Widget badSaveOkButton; 72static Widget badSaveCancelButton; 73static Widget badSaveListWidget; 74 75static int saveTypeData[] = { 76 SmSaveLocal, 77 SmSaveGlobal, 78 SmSaveBoth 79}; 80 81static int interactStyleData[] = { 82 SmInteractStyleNone, 83 SmInteractStyleErrors, 84 SmInteractStyleAny 85}; 86 87static String *failedNames = NULL; 88static int numFailedNames = 0; 89 90static Bool help_visible = False; 91 92static String name_in_use = NULL; 93static Bool name_locked = False; 94 95 96 97static void 98MakeCurrentSession(String new_name, Bool name_changed) 99{ 100 char title[256]; 101 List *cl; 102 103 if (session_name) 104 { 105 /* 106 * In the old session, for any client that was not restarted by the 107 * session manager (previous ID was NULL), if we did not issue a 108 * checkpoint to this client after the initial startup, remove the 109 * client's checkpoint file using the discard command. 110 */ 111 112 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 113 { 114 ClientRec *client = (ClientRec *) cl->thing; 115 116 if (!client->restarted && 117 !client->userIssuedCheckpoint && 118 client->discardCommand) 119 { 120 execute_system_command (client->discardCommand); 121 XtFree (client->discardCommand); 122 client->discardCommand = NULL; 123 } 124 } 125 126 /* 127 * Unlock the old session. 128 */ 129 130 if (!need_to_name_session) 131 UnlockSession (session_name); 132 } 133 134 if (name_changed) 135 { 136 if (session_name) 137 XtFree (session_name); 138 139 session_name = XtNewString (new_name); 140 } 141 142 LockSession (session_name, True); 143 144 snprintf (title, sizeof(title), "xsm: %s", session_name); 145 146 XtVaSetValues (topLevel, 147 XtNtitle, title, 148 NULL); 149 150 set_session_save_file_name (session_name); 151 152 153 /* 154 * For each client, set the DiscardCommand ptr to NULL. 155 * This is so when we do a checkpoint with the new session 156 * name, we don't wipe out the checkpoint files needed by 157 * the previous session. We also set the userIssuedCheckpoint 158 * flag to false for each client in the new session. 159 */ 160 161 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 162 { 163 ClientRec *client = (ClientRec *) cl->thing; 164 165 client->userIssuedCheckpoint = False; 166 167 if (client->discardCommand) 168 { 169 XtFree (client->discardCommand); 170 client->discardCommand = NULL; 171 } 172 } 173 174 need_to_name_session = False; 175} 176 177 178 179 180#define NAME_OK 0 181#define NAME_EMPTY 1 182#define NAME_EXISTS 2 183#define NAME_LOCKED 3 184 185static int 186GetSaveName(String *nameRet) 187{ 188 String new_name = NULL; 189 Bool name_changed; 190 191 /* 192 * Get the name of the session for the save 193 */ 194 195 XtVaGetValues (saveName, 196 XtNstring, &new_name, 197 NULL); 198 199 *nameRet = new_name; 200 201 if (!new_name || *new_name == '\0') 202 return (NAME_EMPTY); 203 204 /* 205 * See if this is a new session. If not return. 206 */ 207 208 name_changed = !session_name || 209 (session_name && strcmp (session_name, new_name) != 0); 210 211 if (!need_to_name_session && !name_changed) 212 return (NAME_OK); 213 214 215 /* 216 * Make sure the session name is unique. 217 */ 218 219 if (GetSessionNames (&sessionNameCount, 220 &sessionNamesShort, NULL, &sessionsLocked)) 221 { 222 int i, no_good = 0, locked = 0; 223 224 for (i = 0; i < sessionNameCount; i++) 225 if (strcmp (new_name, sessionNamesShort[i]) == 0) 226 { 227 no_good = 1; 228 locked = sessionsLocked[i]; 229 break; 230 } 231 232 FreeSessionNames (sessionNameCount, 233 sessionNamesShort, NULL, sessionsLocked); 234 235 if (no_good) 236 return (locked ? NAME_LOCKED : NAME_EXISTS); 237 } 238 239 MakeCurrentSession (new_name, name_changed); 240 241 return (NAME_OK); 242} 243 244 245static void 246GetSaveOptions(int *saveType, int *interactStyle, Bool *fast) 247{ 248 XtPointer ptr; 249 250 if (help_visible) 251 { 252 XtPopdown (helpPopup); 253 help_visible = 0; 254 } 255 256 ptr = XawToggleGetCurrent (saveTypeLocal /* just 1 of the group */); 257 *saveType = *((int *) ptr); 258 259 ptr = XawToggleGetCurrent (interactStyleNone /* just 1 of the group */); 260 *interactStyle = *((int *) ptr); 261 262 *fast = False; 263} 264 265 266 267void 268DoSave(int saveType, int interactStyle, Bool fast) 269{ 270 ClientRec *client; 271 List *cl; 272 const char *_saveType; 273 const char *_shutdown; 274 const char *_interactStyle; 275 276 if (saveType == SmSaveLocal) 277 _saveType = "Local"; 278 else if (saveType == SmSaveGlobal) 279 _saveType = "Global"; 280 else 281 _saveType = "Both"; 282 283 if (wantShutdown) 284 _shutdown = "True"; 285 else 286 _shutdown = "False"; 287 288 if (interactStyle == SmInteractStyleNone) 289 _interactStyle = "None"; 290 else if (interactStyle == SmInteractStyleErrors) 291 _interactStyle = "Errors"; 292 else 293 _interactStyle = "Any"; 294 295 SetSaveSensitivity (False); 296 297 saveInProgress = True; 298 299 shutdownCancelled = False; 300 phase2InProgress = False; 301 302 if (ListCount (RunningList) == 0) 303 FinishUpSave (); 304 305 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 306 { 307 client = (ClientRec *) cl->thing; 308 309 SmsSaveYourself (client->smsConn, 310 saveType, wantShutdown, interactStyle, fast); 311 312 ListAddLast (WaitForSaveDoneList, (char *) client); 313 314 client->userIssuedCheckpoint = True; 315 client->receivedDiscardCommand = False; 316 317 if (verbose) 318 { 319 printf ("Client Id = %s, sent SAVE YOURSELF [", client->clientId); 320 printf ("Save Type = %s, Shutdown = %s, ", _saveType, _shutdown); 321 printf ("Interact Style = %s, Fast = False]\n", _interactStyle); 322 } 323 } 324 325 if (verbose) 326 { 327 printf ("\n"); 328 printf ("Sent SAVE YOURSELF to all clients. Waiting for\n"); 329 printf ("SAVE YOURSELF DONE, INTERACT REQUEST, or\n"); 330 printf ("SAVE YOURSELF PHASE 2 REQUEST from each client.\n"); 331 printf ("\n"); 332 } 333} 334 335 336 337static void 338SaveOkAction(Widget w, XEvent *event, String *params, Cardinal *num_params) 339{ 340 XtCallCallbacks (saveOkButton, XtNcallback, NULL); 341} 342 343 344 345static void 346DelSaveWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params) 347{ 348 XtCallCallbacks (saveCancelButton, XtNcallback, NULL); 349} 350 351 352 353static void 354DelNameInUseWinAction(Widget w, XEvent *event, String *params, 355 Cardinal *num_params) 356{ 357 XtCallCallbacks (nameInUseCancelButton, XtNcallback, NULL); 358} 359 360 361 362static void 363DelBadSaveWinAction(Widget w, XEvent *event, String *params, 364 Cardinal *num_params) 365{ 366 if (XtIsManaged (badSaveCancelButton)) 367 XtCallCallbacks (badSaveCancelButton, XtNcallback, NULL); 368 else 369 XtCallCallbacks (badSaveOkButton, XtNcallback, NULL); 370} 371 372 373 374static void 375DelSaveHelpWinAction(Widget w, XEvent *event, String *params, 376 Cardinal *num_params) 377{ 378 XtCallCallbacks (helpSaveOkButton, XtNcallback, NULL); 379} 380 381 382 383static void 384SaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) 385{ 386 String name = NULL; 387 char label[256]; 388 int status; 389 static int first_time = 1; 390 int saveType; 391 int interactStyle; 392 Bool fast; 393 394 if ((status = GetSaveName (&name)) != NAME_OK) 395 { 396#ifdef XKB 397 XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue); 398#else 399 XBell (XtDisplay (topLevel), 0); 400#endif 401 402 if (status == NAME_EXISTS || status == NAME_LOCKED) 403 { 404 name_in_use = name; 405 406 if (status == NAME_LOCKED) 407 { 408 name_locked = True; 409 410 snprintf (label, sizeof(label), "Another session by the name '%s' is active.\nChoose another name for the session.", name); 411 412 XtUnmanageChild (nameInUseOverwriteButton); 413 414 XtVaSetValues (nameInUseCancelButton, 415 XtNlabel, "OK", 416 XtNfromHoriz, NULL, 417 NULL); 418 } 419 else 420 { 421 name_locked = False; 422 423 snprintf (label, sizeof(label), "Another session by the name '%s' already exists.\nWould you like to overwrite it?", name); 424 425 XtManageChild (nameInUseOverwriteButton); 426 427 XtVaSetValues (nameInUseCancelButton, 428 XtNlabel, "Cancel", 429 XtNfromHoriz, nameInUseOverwriteButton, 430 NULL); 431 } 432 433 XtVaSetValues (nameInUseLabel, 434 XtNlabel, label, 435 NULL); 436 437 XtPopdown (savePopup); 438 439 PopupPopup (mainWindow, nameInUsePopup, 440 True, first_time, 25, 100, "DelNameInUseWinAction()"); 441 442 if (first_time) 443 first_time = 0; 444 } 445 446 return; 447 } 448 449 GetSaveOptions (&saveType, &interactStyle, &fast); 450 DoSave (saveType, interactStyle, fast); 451} 452 453 454 455void 456LetClientInteract(List *cl) 457{ 458 ClientRec *client = (ClientRec *) cl->thing; 459 460 SmsInteract (client->smsConn); 461 462 ListSearchAndFreeOne (WaitForInteractList, (char *) client); 463 464 if (verbose) 465 { 466 printf ("Client Id = %s, sent INTERACT\n", client->clientId); 467 } 468} 469 470 471 472void 473StartPhase2(void) 474{ 475 List *cl; 476 477 if (verbose) 478 { 479 printf ("\n"); 480 printf ("Starting PHASE 2 of SAVE YOURSELF\n"); 481 printf ("\n"); 482 } 483 484 for (cl = ListFirst (WaitForPhase2List); cl; cl = ListNext (cl)) 485 { 486 ClientRec *client = (ClientRec *) cl->thing; 487 488 SmsSaveYourselfPhase2 (client->smsConn); 489 490 if (verbose) 491 { 492 printf ("Client Id = %s, sent SAVE YOURSELF PHASE 2", 493 client->clientId); 494 } 495 } 496 497 ListFreeAllButHead (WaitForPhase2List); 498 499 phase2InProgress = True; 500} 501 502 503void 504FinishUpSave(void) 505{ 506 ClientRec *client; 507 List *cl; 508 509 if (verbose) 510 { 511 printf ("\n"); 512 printf ("All clients issued SAVE YOURSELF DONE\n"); 513 printf ("\n"); 514 } 515 516 saveInProgress = False; 517 phase2InProgress = False; 518 519 /* 520 * Now execute discard commands 521 */ 522 523 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 524 { 525 client = (ClientRec *) cl->thing; 526 527 if (!client->receivedDiscardCommand) 528 continue; 529 530 if (client->discardCommand) 531 { 532 execute_system_command (client->discardCommand); 533 XtFree (client->discardCommand); 534 client->discardCommand = NULL; 535 } 536 537 if (client->saveDiscardCommand) 538 { 539 client->discardCommand = client->saveDiscardCommand; 540 client->saveDiscardCommand = NULL; 541 } 542 } 543 544 545 /* 546 * Write the save file 547 */ 548 549 WriteSave (sm_id); 550 551 552 if (wantShutdown && shutdownCancelled) 553 { 554 shutdownCancelled = False; 555 } 556 else if (wantShutdown) 557 { 558 if (ListCount (RunningList) == 0) 559 EndSession (0); 560 561 shutdownInProgress = True; 562 563 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 564 { 565 client = (ClientRec *) cl->thing; 566 567 SmsDie (client->smsConn); 568 569 if (verbose) 570 { 571 printf ("Client Id = %s, sent DIE\n", client->clientId); 572 } 573 } 574 } 575 else 576 { 577 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 578 { 579 client = (ClientRec *) cl->thing; 580 581 SmsSaveComplete (client->smsConn); 582 583 if (verbose) 584 { 585 printf ("Client Id = %s, sent SAVE COMPLETE\n", 586 client->clientId); 587 } 588 } 589 } 590 591 if (!shutdownInProgress) 592 { 593 XtPopdown (savePopup); 594 SetAllSensitive (1); 595 if (checkpoint_from_signal) 596 checkpoint_from_signal = False; 597 } 598} 599 600 601 602static void 603SaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) 604{ 605 XtPopdown (savePopup); 606 607 if (help_visible) 608 { 609 XtPopdown (helpPopup); 610 help_visible = 0; 611 } 612 613 SetAllSensitive (1); 614} 615 616 617 618/* 619 * Add toggle button 620 */ 621 622static Widget 623AddToggle(String widgetName, Widget parent, int state, Widget radioGroup, 624 XtPointer radioData, Widget fromHoriz, Widget fromVert) 625{ 626 Widget toggle; 627 628 toggle = XtVaCreateManagedWidget ( 629 widgetName, toggleWidgetClass, parent, 630 XtNstate, state, 631 XtNradioGroup, radioGroup, 632 XtNradioData, radioData, 633 XtNfromHoriz, fromHoriz, 634 XtNfromVert, fromVert, 635 NULL); 636 637 return (toggle); 638} 639 640 641 642void 643SetSaveSensitivity(Bool on) 644{ 645 XtSetSensitive (savePopup, on); 646 647#if 0 648 /* 649 * When we turn of sensitivity in the save dialog, we want to keep 650 * the cancel button sensitive (so the user can cancel in case of 651 * a problem). Unfortunately, we can not turn off the sensitivity on 652 * the save popup, and then just turn on sensitivity for the cancel 653 * button. We must do each widget individually. 654 */ 655 656 XtSetSensitive (saveTypeLabel, on); 657 XtSetSensitive (saveTypeGlobal, on); 658 XtSetSensitive (saveTypeLocal, on); 659 XtSetSensitive (saveTypeBoth, on); 660 XtSetSensitive (interactStyleLabel, on); 661 XtSetSensitive (interactStyleNone, on); 662 XtSetSensitive (interactStyleErrors, on); 663 XtSetSensitive (interactStyleAny, on); 664 XtSetSensitive (saveOkButton, on); 665#endif 666} 667 668 669 670void 671SavePopupStructureNotifyXtHandler(Widget w, XtPointer closure, XEvent *event, 672 Boolean *continue_to_dispatch) 673{ 674 if (event->type == MapNotify) 675 { 676 /* 677 * Now that the Save Dialog is back up, we can do the save. 678 */ 679 680 int saveType; 681 int interactStyle; 682 Bool fast; 683 684 if (name_locked) 685 { 686 /* Force shutdown */ 687 } 688 689 DeleteSession (name_in_use); 690 691 MakeCurrentSession (name_in_use, True); 692 693 name_in_use = NULL; 694 695 GetSaveOptions (&saveType, &interactStyle, &fast); 696 DoSave (saveType, interactStyle, fast); 697 698 XtRemoveEventHandler (savePopup, StructureNotifyMask, False, 699 SavePopupStructureNotifyXtHandler, NULL); 700 } 701} 702 703 704 705static void 706NameInUseOverwriteXtProc(Widget w, XtPointer client_data, XtPointer callData) 707{ 708 if (name_locked) 709 { 710 /* force shutdown not implemented yet */ 711 712 return; 713 } 714 715 XtPopdown (nameInUsePopup); 716 717 /* 718 * We want to popup the Save dialog again. In order to avoid a race 719 * condition with the BadSave handler trying to pop down the Save Dialog, 720 * we wait for the MapNotify on the Save dialog, and then do the save. 721 */ 722 723 XtAddEventHandler (savePopup, StructureNotifyMask, False, 724 SavePopupStructureNotifyXtHandler, NULL); 725 726 XtPopup (savePopup, XtGrabNone); 727} 728 729 730 731static void 732NameInUseCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) 733{ 734 XtPopdown (nameInUsePopup); 735 XtPopup (savePopup, XtGrabNone); 736 737 name_in_use = NULL; 738} 739 740 741 742static void 743BadSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) 744{ 745 ListFreeAllButHead (FailedSaveList); 746 XtPopdown (badSavePopup); 747 FinishUpSave (); 748} 749 750 751 752static void 753BadSaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) 754{ 755 ListFreeAllButHead (FailedSaveList); 756 XtPopdown (badSavePopup); 757 758 if (wantShutdown) 759 { 760 List *cl; 761 762 shutdownCancelled = True; 763 764 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 765 { 766 ClientRec *client = (ClientRec *) cl->thing; 767 768 SmsShutdownCancelled (client->smsConn); 769 770 if (verbose) 771 { 772 printf ("Client Id = %s, sent SHUTDOWN CANCELLED\n", 773 client->clientId); 774 } 775 } 776 } 777 778 FinishUpSave (); 779} 780 781 782 783static void 784BadSaveListXtProc(Widget w, XtPointer client_data, XtPointer callData) 785{ 786 787} 788 789 790 791static void 792HelpSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) 793{ 794 static int first_time = 1; 795 796 if (help_visible) 797 { 798 /* Make sure it is visible */ 799 800 XMapRaised (XtDisplay (topLevel), XtWindow (helpPopup)); 801 } 802 else 803 { 804 PopupPopup (savePopup, helpPopup, 805 True, first_time, 50, 50, "DelSaveHelpWinAction()"); 806 807 help_visible = 1; 808 809 if (first_time) 810 first_time = 0; 811 } 812} 813 814 815 816static void 817HelpSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData) 818{ 819 XtPopdown (helpPopup); 820 help_visible = 0; 821} 822 823 824 825void 826create_save_popup(void) 827 828{ 829 XtTranslations translations; 830 831 static XtActionsRec actions[] = { 832 {"SaveOkAction", SaveOkAction}, 833 {"DelSaveWinAction", DelSaveWinAction}, 834 {"DelNameInUseWinAction", DelNameInUseWinAction}, 835 {"DelBadSaveWinAction", DelBadSaveWinAction}, 836 {"DelSaveHelpWinAction", DelSaveHelpWinAction} 837 }; 838 839 840 /* 841 * Pop up for Save Yourself button. 842 */ 843 844 savePopup = XtVaCreatePopupShell ( 845 "savePopup", transientShellWidgetClass, topLevel, 846 XtNallowShellResize, True, 847 NULL); 848 849 saveForm = XtCreateManagedWidget ( 850 "saveForm", formWidgetClass, savePopup, NULL, 0); 851 852 saveMessageLabel = XtVaCreateManagedWidget ( 853 "saveMessageLabel", labelWidgetClass, saveForm, 854 XtNfromHoriz, NULL, 855 XtNfromVert, NULL, 856 XtNborderWidth, 0, 857 NULL); 858 859 saveName = XtVaCreateManagedWidget ( 860 "saveName", asciiTextWidgetClass, saveForm, 861 XtNfromVert, NULL, 862 XtNeditType, XawtextEdit, 863 XtNresizable, True, 864 XtNresize, XawtextResizeWidth, 865 NULL); 866 867 saveTypeLabel = XtVaCreateManagedWidget ( 868 "saveTypeLabel", labelWidgetClass, saveForm, 869 XtNfromHoriz, NULL, 870 XtNfromVert, saveMessageLabel, 871 XtNborderWidth, 0, 872 XtNvertDistance, 20, 873 NULL); 874 875 saveTypeLocal = AddToggle ( 876 "saveTypeLocal", /* widgetName */ 877 saveForm, /* parent */ 878 0, /* state */ 879 NULL, /* radioGroup */ 880 (XtPointer) &saveTypeData[0], /* radioData */ 881 saveTypeLabel, /* fromHoriz */ 882 saveMessageLabel /* fromVert */ 883 ); 884 885 saveTypeGlobal = AddToggle ( 886 "saveTypeGlobal", /* widgetName */ 887 saveForm, /* parent */ 888 0, /* state */ 889 saveTypeLocal, /* radioGroup */ 890 (XtPointer) &saveTypeData[1], /* radioData */ 891 saveTypeLocal, /* fromHoriz */ 892 saveMessageLabel /* fromVert */ 893 ); 894 895 saveTypeBoth = AddToggle ( 896 "saveTypeBoth", /* widgetName */ 897 saveForm, /* parent */ 898 1, /* state */ 899 saveTypeLocal, /* radioGroup */ 900 (XtPointer) &saveTypeData[2], /* radioData */ 901 saveTypeGlobal, /* fromHoriz */ 902 saveMessageLabel /* fromVert */ 903 ); 904 905 906 XtVaSetValues (saveName, XtNfromHoriz, saveTypeLabel, NULL); 907 XtVaSetValues (saveTypeLocal, XtNvertDistance, 20, NULL); 908 XtVaSetValues (saveTypeGlobal, XtNvertDistance, 20, NULL); 909 XtVaSetValues (saveTypeBoth, XtNvertDistance, 20, NULL); 910 911 interactStyleLabel = XtVaCreateManagedWidget ( 912 "interactStyleLabel", labelWidgetClass, saveForm, 913 XtNfromHoriz, NULL, 914 XtNfromVert, saveTypeLabel, 915 XtNborderWidth, 0, 916 NULL); 917 918 interactStyleNone = AddToggle ( 919 "interactStyleNone", /* widgetName */ 920 saveForm, /* parent */ 921 0, /* state */ 922 NULL, /* radioGroup */ 923 (XtPointer) &interactStyleData[0], /* radioData */ 924 saveTypeLabel, /* fromHoriz */ 925 saveTypeLabel /* fromVert */ 926 ); 927 928 interactStyleErrors = AddToggle ( 929 "interactStyleErrors", /* widgetName */ 930 saveForm, /* parent */ 931 0, /* state */ 932 interactStyleNone, /* radioGroup */ 933 (XtPointer) &interactStyleData[1], /* radioData */ 934 interactStyleNone, /* fromHoriz */ 935 saveTypeLabel /* fromVert */ 936 ); 937 938 interactStyleAny = AddToggle ( 939 "interactStyleAny", /* widgetName */ 940 saveForm, /* parent */ 941 1, /* state */ 942 interactStyleNone, /* radioGroup */ 943 (XtPointer) &interactStyleData[2], /* radioData */ 944 interactStyleErrors, /* fromHoriz */ 945 saveTypeLabel /* fromVert */ 946 ); 947 948 949 saveOkButton = XtVaCreateManagedWidget ( 950 "saveOkButton", commandWidgetClass, saveForm, 951 XtNfromHoriz, NULL, 952 XtNfromVert, interactStyleLabel, 953 XtNvertDistance, 20, 954 XtNresizable, True, 955 NULL); 956 957 XtAddCallback (saveOkButton, XtNcallback, SaveOkXtProc, NULL); 958 959 960 helpSaveButton = XtVaCreateManagedWidget ( 961 "helpSaveButton", commandWidgetClass, saveForm, 962 XtNfromHoriz, saveOkButton, 963 XtNfromVert, interactStyleLabel, 964 XtNvertDistance, 20, 965 NULL); 966 967 XtAddCallback (helpSaveButton, XtNcallback, HelpSaveXtProc, NULL); 968 969 970 saveCancelButton = XtVaCreateManagedWidget ( 971 "saveCancelButton", commandWidgetClass, saveForm, 972 XtNfromHoriz, helpSaveButton, 973 XtNfromVert, interactStyleLabel, 974 XtNvertDistance, 20, 975 NULL); 976 977 XtAddCallback (saveCancelButton, XtNcallback, SaveCancelXtProc, NULL); 978 979 XtSetKeyboardFocus (saveForm, saveName); 980 981 XtAppAddActions (appContext, actions, XtNumber (actions)); 982 983 translations = XtParseTranslationTable 984 ("<Key>Return: SaveOkAction()\n"); 985 XtOverrideTranslations(saveName, translations); 986 987 XtInstallAllAccelerators (saveForm, saveForm); 988 989 990 /* 991 * Pop up when user tries to save the session under an 992 * already used name. 993 */ 994 995 nameInUsePopup = XtVaCreatePopupShell ( 996 "nameInUsePopup", transientShellWidgetClass, topLevel, 997 XtNallowShellResize, True, 998 NULL); 999 1000 1001 nameInUseForm = XtVaCreateManagedWidget ( 1002 "nameInUseForm", formWidgetClass, nameInUsePopup, 1003 NULL); 1004 1005 nameInUseLabel = XtVaCreateManagedWidget ( 1006 "nameInUseLabel", labelWidgetClass, nameInUseForm, 1007 XtNresizable, True, 1008 XtNfromHoriz, NULL, 1009 XtNfromVert, NULL, 1010 XtNborderWidth, 0, 1011 XtNtop, XawChainTop, 1012 XtNbottom, XawChainTop, 1013 NULL); 1014 1015 nameInUseOverwriteButton = XtVaCreateManagedWidget ( 1016 "nameInUseOverwriteButton", commandWidgetClass, nameInUseForm, 1017 XtNfromHoriz, NULL, 1018 XtNfromVert, nameInUseLabel, 1019 XtNtop, XawChainBottom, 1020 XtNbottom, XawChainBottom, 1021 NULL); 1022 1023 XtAddCallback (nameInUseOverwriteButton, XtNcallback, 1024 NameInUseOverwriteXtProc, NULL); 1025 1026 1027 nameInUseCancelButton = XtVaCreateManagedWidget ( 1028 "nameInUseCancelButton", commandWidgetClass, nameInUseForm, 1029 XtNresizable, True, 1030 XtNfromHoriz, nameInUseOverwriteButton, 1031 XtNfromVert, nameInUseLabel, 1032 XtNtop, XawChainBottom, 1033 XtNbottom, XawChainBottom, 1034 NULL); 1035 1036 XtAddCallback (nameInUseCancelButton, XtNcallback, 1037 NameInUseCancelXtProc, NULL); 1038 1039 1040 /* 1041 * Pop up for help. 1042 */ 1043 1044 helpPopup = XtVaCreatePopupShell ( 1045 "helpPopup", transientShellWidgetClass, topLevel, 1046 NULL); 1047 1048 1049 helpForm = XtVaCreateManagedWidget ( 1050 "helpForm", formWidgetClass, helpPopup, 1051 NULL); 1052 1053 helpSaveText = XtVaCreateManagedWidget ( 1054 "helpSaveText", labelWidgetClass, helpForm, 1055 XtNfromHoriz, NULL, 1056 XtNfromVert, NULL, 1057 XtNtop, XawChainTop, 1058 XtNbottom, XawChainTop, 1059 NULL); 1060 1061 helpSaveOkButton = XtVaCreateManagedWidget ( 1062 "helpSaveOkButton", commandWidgetClass, helpForm, 1063 XtNfromHoriz, NULL, 1064 XtNfromVert, helpSaveText, 1065 XtNtop, XawChainBottom, 1066 XtNbottom, XawChainBottom, 1067 XtNvertDistance, 20, 1068 NULL); 1069 1070 XtAddCallback (helpSaveOkButton, XtNcallback, 1071 HelpSaveOkXtProc, NULL); 1072 1073 1074 /* 1075 * Pop up when not all clients returned SaveSuccess 1076 */ 1077 1078 badSavePopup = XtVaCreatePopupShell ( 1079 "badSavePopup", transientShellWidgetClass, topLevel, 1080 XtNallowShellResize, True, 1081 NULL); 1082 1083 1084 badSaveForm = XtVaCreateManagedWidget ( 1085 "badSaveForm", formWidgetClass, badSavePopup, 1086 NULL); 1087 1088 badSaveLabel = XtVaCreateManagedWidget ( 1089 "badSaveLabel", labelWidgetClass, badSaveForm, 1090 XtNfromHoriz, NULL, 1091 XtNfromVert, NULL, 1092 XtNborderWidth, 0, 1093 XtNtop, XawChainTop, 1094 XtNbottom, XawChainTop, 1095 NULL); 1096 1097 badSaveListWidget = XtVaCreateManagedWidget ( 1098 "badSaveListWidget", listWidgetClass, badSaveForm, 1099 XtNresizable, True, 1100 XtNdefaultColumns, 1, 1101 XtNforceColumns, True, 1102 XtNfromHoriz, NULL, 1103 XtNfromVert, badSaveLabel, 1104 XtNtop, XawChainTop, 1105 XtNbottom, XawChainBottom, 1106 NULL); 1107 1108 XtAddCallback (badSaveListWidget, XtNcallback, BadSaveListXtProc, NULL); 1109 1110 badSaveOkButton = XtVaCreateManagedWidget ( 1111 "badSaveOkButton", commandWidgetClass, badSaveForm, 1112 XtNfromHoriz, NULL, 1113 XtNfromVert, badSaveListWidget, 1114 XtNtop, XawChainBottom, 1115 XtNbottom, XawChainBottom, 1116 NULL); 1117 1118 XtAddCallback (badSaveOkButton, XtNcallback, BadSaveOkXtProc, NULL); 1119 1120 1121 badSaveCancelButton = XtVaCreateManagedWidget ( 1122 "badSaveCancelButton", commandWidgetClass, badSaveForm, 1123 XtNfromHoriz, badSaveOkButton, 1124 XtNfromVert, badSaveListWidget, 1125 XtNtop, XawChainBottom, 1126 XtNbottom, XawChainBottom, 1127 NULL); 1128 1129 XtAddCallback (badSaveCancelButton, XtNcallback, BadSaveCancelXtProc, NULL); 1130 1131 XtInstallAllAccelerators (badSaveForm, badSaveForm); 1132} 1133 1134 1135 1136void 1137PopupSaveDialog(void) 1138 1139{ 1140 static int first_time = 1; 1141 1142 XtSetSensitive (mainWindow, 0); 1143 XtSetSensitive (clientInfoPopup, 0); 1144 XtSetSensitive (clientPropPopup, 0); 1145 1146 XawToggleSetCurrent (saveTypeBoth, 1147 (XtPointer) &saveTypeData[2]); 1148 XawToggleSetCurrent (interactStyleAny, 1149 (XtPointer) &interactStyleData[2]); 1150 1151 XtVaSetValues (savePopup, 1152 XtNtitle, wantShutdown ? "Shutdown" : "Checkpoint", 1153 NULL); 1154 1155 XtVaSetValues (saveName, 1156 XtNstring, need_to_name_session ? "" : session_name, 1157 NULL); 1158 1159 XtVaSetValues (saveOkButton, 1160 XtNlabel, wantShutdown ? "Shutdown" : "Checkpoint", 1161 NULL); 1162 1163 PopupPopup (mainWindow, savePopup, 1164 True, first_time, 25, 100, "DelSaveWinAction()"); 1165 1166 if (first_time) 1167 first_time = 0; 1168} 1169 1170 1171 1172 1173void 1174CheckPointXtProc(Widget w, XtPointer client_data, XtPointer callData) 1175{ 1176 wantShutdown = False; 1177 PopupSaveDialog (); 1178} 1179 1180 1181 1182 1183void 1184ShutdownSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) 1185{ 1186 wantShutdown = True; 1187 PopupSaveDialog (); 1188} 1189 1190 1191 1192void 1193PopupBadSave(void) 1194 1195{ 1196 ClientRec *client; 1197 char *progName, *hostname, *tmp1, *tmp2; 1198 char *clientInfo; 1199 int maxlen1, maxlen2; 1200 char extraBuf1[80], extraBuf2[80]; 1201 char *restart_service_prop; 1202 List *cl, *pl; 1203 int i, k; 1204 static int first_time = 1; 1205 1206 if (failedNames) 1207 { 1208 /* 1209 * Free the previous list of names. Xaw doesn't make a copy of 1210 * our list, so we need to keep it around. 1211 */ 1212 1213 for (i = 0; i < numFailedNames; i++) 1214 XtFree ((char *) failedNames[i]); 1215 1216 XtFree ((char *) failedNames); 1217 1218 failedNames = NULL; 1219 } 1220 1221 maxlen1 = maxlen2 = 0; 1222 numFailedNames = 0; 1223 1224 for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl)) 1225 { 1226 client = (ClientRec *) cl->thing; 1227 1228 progName = NULL; 1229 restart_service_prop = NULL; 1230 1231 for (pl = ListFirst (client->props); pl; pl = ListNext (pl)) 1232 { 1233 Prop *pprop = (Prop *) pl->thing; 1234 List *vl = ListFirst (pprop->values); 1235 PropValue *pval = (PropValue *) vl->thing; 1236 1237 if (strcmp (pprop->name, SmProgram) == 0) 1238 { 1239 progName = GetProgramName ((char *) pval->value); 1240 1241 if ((int) strlen (progName) > maxlen1) 1242 maxlen1 = strlen (progName); 1243 } 1244 else if (strcmp (pprop->name, "_XC_RestartService") == 0) 1245 { 1246 restart_service_prop = (char *) pval->value; 1247 } 1248 } 1249 1250 if (!progName) 1251 continue; 1252 1253 if (restart_service_prop) 1254 tmp1 = restart_service_prop; 1255 else if (client->clientHostname) 1256 tmp1 = client->clientHostname; 1257 else 1258 continue; 1259 1260 if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL) 1261 hostname = tmp1; 1262 else 1263 hostname = tmp2 + 1; 1264 1265 if ((int) strlen (hostname) > maxlen2) 1266 maxlen2 = strlen (hostname); 1267 1268 numFailedNames++; 1269 } 1270 1271 failedNames = (String *) XtMalloc ( 1272 numFailedNames * sizeof (String)); 1273 1274 i = 0; 1275 for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl)) 1276 { 1277 ClientRec *client = (ClientRec *) cl->thing; 1278 int extra1, extra2; 1279 1280 progName = NULL; 1281 restart_service_prop = NULL; 1282 1283 for (pl = ListFirst (client->props); pl; pl = ListNext (pl)) 1284 { 1285 Prop *pprop = (Prop *) pl->thing; 1286 List *vl = ListFirst (pprop->values); 1287 PropValue *pval = (PropValue *) vl->thing; 1288 1289 if (strcmp (pprop->name, SmProgram) == 0) 1290 { 1291 progName = GetProgramName ((char *) pval->value); 1292 } 1293 else if (strcmp (pprop->name, "_XC_RestartService") == 0) 1294 { 1295 restart_service_prop = (char *) pval->value; 1296 } 1297 } 1298 1299 if (!progName) 1300 continue; 1301 1302 if (restart_service_prop) 1303 tmp1 = restart_service_prop; 1304 else if (client->clientHostname) 1305 tmp1 = client->clientHostname; 1306 else 1307 continue; 1308 1309 if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL) 1310 hostname = tmp1; 1311 else 1312 hostname = tmp2 + 1; 1313 1314 extra1 = maxlen1 - strlen (progName) + 5; 1315 extra2 = maxlen2 - strlen (hostname); 1316 1317 for (k = 0; k < extra1; k++) 1318 extraBuf1[k] = ' '; 1319 extraBuf1[extra1] = '\0'; 1320 1321 for (k = 0; k < extra2; k++) 1322 extraBuf2[k] = ' '; 1323 extraBuf2[extra2] = '\0'; 1324 1325 XtAsprintf (&clientInfo, "%s%s (%s%s)", progName, extraBuf1, 1326 hostname, extraBuf2); 1327 1328 failedNames[i++] = clientInfo; 1329 1330 if (client->freeAfterBadSavePopup) 1331 { 1332 FreeClient (client, True /* free props */); 1333 } 1334 } 1335 1336 XawListChange (badSaveListWidget, 1337 failedNames, numFailedNames, 0, True); 1338 1339 XtPopdown (savePopup); 1340 1341 if (wantShutdown && !shutdownCancelled) 1342 XtManageChild (badSaveCancelButton); 1343 else 1344 XtUnmanageChild (badSaveCancelButton); 1345 1346 PopupPopup (mainWindow, badSavePopup, 1347 True, first_time, 25, 100, "DelBadSaveWinAction()"); 1348 1349 if (first_time) 1350 first_time = 0; 1351} 1352 1353 1354 1355void 1356ShutdownDontSaveXtProc(Widget w, XtPointer client_data, XtPointer callData) 1357{ 1358 List *cl; 1359 ClientRec *client; 1360 1361 if (ListCount (RunningList) == 0) 1362 EndSession (0); 1363 1364 /* 1365 * For any client that was not restarted by the session 1366 * manager (previous ID was NULL), if we did not issue a 1367 * checkpoint to this client, remove the client's checkpoint 1368 * file using the discard command. 1369 */ 1370 1371 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 1372 { 1373 client = (ClientRec *) cl->thing; 1374 1375 if (!client->restarted && 1376 !client->userIssuedCheckpoint && 1377 client->discardCommand) 1378 { 1379 execute_system_command (client->discardCommand); 1380 XtFree (client->discardCommand); 1381 client->discardCommand = NULL; 1382 } 1383 } 1384 1385 shutdownInProgress = True; 1386 1387 for (cl = ListFirst (RunningList); cl; cl = ListNext (cl)) 1388 { 1389 client = (ClientRec *) cl->thing; 1390 1391 SmsDie (client->smsConn); 1392 1393 if (verbose) 1394 { 1395 printf ("Client Id = %s, sent DIE\n", client->clientId); 1396 } 1397 } 1398} 1399