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