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