2a809ee62664bfc42c8fcb7b1952ff8a1c8ea7f6
[oweals/cde.git] / cde / programs / dtsession / SmGlobals.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: SmGlobals.c /main/37 1998/10/26 17:21:18 mgreess $ */
24 /*
25  * (c) Copyright 1995 Digital Equipment Corporation.
26  * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
27  * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
28  * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
29  * (c) Copyright 1993, 1994, 1995 Novell, Inc. 
30  * (c) Copyright 1995 FUJITSU LIMITED.
31  * (c) Copyright 1995 Hitachi.
32  */
33 /*************************************<+>*************************************
34  *****************************************************************************
35  **
36  **  File:        SmGlobals.c
37  **
38  **  Project:     HP DT Session Manager (dtsession)
39  **
40  **  Description:
41  **  -----------
42  **  This file contains all routines in charge of managing all global
43  **  variables used by the session manager.  These variables include
44  **  mostly state and setting information.
45  **
46  **
47  **
48  *******************************************************************
49  **  (c) Copyright Hewlett-Packard Company, 1990.  All rights are  
50  **  reserved.  Copying or other reproduction of this program      
51  **  except for archival purposes is prohibited without prior      
52  **  written consent of Hewlett-Packard Company.                     
53  ********************************************************************
54  **
55  **
56  **
57  *****************************************************************************
58  *************************************<+>*************************************/
59 #include <stdio.h>
60 #include <ctype.h>
61 #include <sys/wait.h>
62 #include <sys/types.h>
63 #include <sys/utsname.h>
64 #include <unistd.h>
65 #ifdef __apollo
66 #include <X11/apollosys.h>      /* for pid_t, in hp-ux sys/types.h */
67 #endif
68 #include <sys/stat.h>
69 #include <sys/param.h>
70 #include <X11/Intrinsic.h>
71 #include <X11/Xutil.h>
72 #include <X11/StringDefs.h>
73 #include <Xm/Xm.h>
74 #include <Dt/DtP.h>
75 #include <Dt/SessionP.h>
76 #include <Dt/Wsm.h>
77 #include <Dt/WsmP.h>
78 #include <Dt/UserMsg.h>
79 #include <Dt/HourGlass.h>
80 #include <Dt/SessionM.h>
81 #include <Dt/EnvControlP.h>
82 #include <Dt/Qualify.h>
83 #include <Dt/MsgLog.h>
84 #include "Sm.h"
85 #include "SmResource.h"
86 #include "SmError.h"
87 #include "SmUI.h"
88 #include "SmGlobals.h"
89 #include "SmLock.h"
90 #include "SmRestore.h"
91 #include "SmProtocol.h"
92 #include "SmXSMP.h"
93
94 /*
95  * Internal Variable Declaraions
96  */
97 static char savedDir    [MAXPATHLEN];
98 static char savedOldDir [MAXPATHLEN];
99 static char savedTmpDir [MAXPATHLEN];
100
101 /*
102  * Internal Function Declaraions
103  */
104
105 static int SetSysDefaults( void ) ;
106 static int SetResSet( void ) ;
107 static void RemoveFiles( char *) ;
108 static void TrimErrorlog(void);
109
110 static void _SmWaitClientTimeoutDefault (
111         Widget widget, 
112        int offset, 
113        XrmValue *value);
114
115 static void _SmWaitWmTimeoutDefault (
116         Widget widget, 
117         int offset, 
118         XrmValue *value);
119
120 void SmCvtStringToContManagement (
121         XrmValue *args, 
122         Cardinal numArgs,
123         XrmValue *fromVal, 
124         XrmValue *toVal);
125
126 unsigned char *_DtNextToken (
127         unsigned char *pchIn, 
128         int *pLen, 
129         unsigned char **ppchNext);
130
131 Boolean _DtWmStringsAreEqual (
132         unsigned char *pch1, 
133         unsigned char *pch2, 
134         int len);
135
136 static Boolean InitializeSpecificSession (
137         char            *session_name,
138         Display         *disp,
139         unsigned int    argc,
140         char            **argv);
141
142 static void InitializeGenericSession (
143         Display         *disp);
144
145 static void InitializePaths (
146         char            *session_option,
147         Display         *disp);
148
149 static Boolean SetAlternateSession (
150         char            * session_dir,
151         char            * alt_dir,
152         Boolean         make_dir);
153
154 /*
155  * Global Data
156  */
157
158 /*
159  * These are the global structures used throughout dtsession
160  * They are defined in Sm.h
161  */
162 SessionResources     smRes;
163 SaverResources       smSaverRes;
164 SettingsSet           smToSet;
165 SettingsCust     smCust;
166 SessionSettings      smSettings;
167 GeneralData          smGD;
168 char SM_SCREEN_SAVER_LOC [MAXPATHLEN + 1];
169
170 /*
171  * Internal Global Data
172  */
173 static char     tmpDisplayName[MAXPATHLEN + 1];
174 int machineType = 0;
175
176 static XtResource sessionResources[]=
177 {
178    {SmNwmStartup, SmCwmStartup, XtRString, sizeof(String),
179         XtOffset(SessionResourcesPtr, wmStartup),
180         XtRImmediate, (XtPointer) NULL},
181    {SmNquerySettings, SmCquerySettings, XtRBoolean, sizeof(Boolean),
182         XtOffset(SessionResourcesPtr, querySettings),
183         XtRImmediate, (XtPointer) False},
184    {SmNkeys, SmCkeys, XtRString, sizeof(String),
185         XtOffset(SessionResourcesPtr, keyholders), XtRString, NULL},
186    {SmNalarmTime, SmCalarmTime, XtRInt, sizeof(int),
187         XtOffset(SessionResourcesPtr, alarmTime), 
188         XtRImmediate, (XtPointer) 10},
189    {SmNmemThreshold, SmCmemThreshold, XtRInt, sizeof(int),
190         XtOffset(SessionResourcesPtr, memThreshold), 
191         XtRImmediate, (XtPointer) 100},
192    {SmNsessionVersion, SmCsessionVersion, XtRString, sizeof(String),
193         XtOffset(SessionResourcesPtr, sessionVersion),
194         XtRImmediate, (XtPointer) NULL},
195    {SmNdisplayResolution, SmCdisplayResolution, XtRInt, sizeof(int),
196         XtOffset(SessionResourcesPtr, displayResolution),
197         XtRImmediate, (XtPointer) 0},
198    {SmNsessionLang, SmCsessionLang, XtRString, sizeof(String),
199         XtOffset(SessionResourcesPtr, sessionLang),
200         XtRImmediate, (XtPointer) ""},
201    {SmNcontManagement, SmCContManagement, SmRContManagement, sizeof(long),
202         XtOffset(SessionResourcesPtr, contManagement),
203         XtRImmediate, (XtPointer) (SM_CM_DEFAULT)},
204    {SmNwaitClientTimeout, SmCWaitClientTimeout, XtRInt, sizeof(int),
205         XtOffset(SessionResourcesPtr, waitClientTimeout),
206         XtRCallProc, (XtPointer)_SmWaitClientTimeoutDefault },
207    {SmNwaitWmTimeout, SmCWaitWmTimeout, XtRInt, sizeof(int),
208         XtOffset(SessionResourcesPtr, waitWmTimeout),
209         XtRCallProc, (XtPointer)_SmWaitWmTimeoutDefault },
210    {SmNuseMessaging, SmCUseMessaging, XtRBoolean, sizeof(Boolean),
211         XtOffset(SessionResourcesPtr, useBMS),
212         XtRImmediate, (XtPointer) True},
213    {SmNsaveFontPath, SmCsaveFontPath, XtRBoolean, sizeof(Boolean),
214         XtOffset(SessionResourcesPtr, saveFontPath),
215         XtRImmediate, (XtPointer) False},
216    {SmNsaveYourselfTimeout, SmCsaveYourselfTimeout, XtRInt, sizeof(int),
217         XtOffset(SessionResourcesPtr, saveYourselfTimeout),
218         XtRImmediate, (XtPointer) 5},
219    {SmNnumSessionsBackedup, SmCnumSessionsBackedup, XtRInt, sizeof(int),
220         XtOffset(SessionResourcesPtr, numSessionsBackedup),
221         XtRImmediate, (XtPointer) DEFAULT_NUM_SESSIONS_BACKED_UP},
222    {SmNignoreEnvironment, SmCignoreEnvironment, XtRString, sizeof(String),
223         XtOffset(SessionResourcesPtr, ignoreEnvironment),
224         XtRImmediate, (XtPointer) NULL},
225 }
226 ;
227
228
229 static XtResource saverResources[]=
230 {
231    {SmNcycleTimeout, SmCcycleTimeout, XtRInt, sizeof(int),
232         XtOffset(SaverResourcesPtr, cycleTimeout),
233         XtRImmediate, (XtPointer) -1},
234    {SmNlockTimeout, SmClockTimeout, XtRInt, sizeof(int),
235         XtOffset(SaverResourcesPtr, lockTimeout),
236         XtRImmediate, (XtPointer) -1},
237    {SmNsaverTimeout, SmCsaverTimeout, XtRInt, sizeof(int),
238         XtOffset(SaverResourcesPtr, saverTimeout),
239         XtRImmediate, (XtPointer) -1},
240    {SmNrandom, SmCrandom, XtRBoolean, sizeof(Boolean),
241         XtOffset(SaverResourcesPtr, random),
242         XtRImmediate, (XtPointer) False},
243    {SmNsaverList, SmCsaverList, XtRString, sizeof(String),
244         XtOffset(SaverResourcesPtr, saverList),
245         XtRImmediate, (XtPointer) ""},
246
247 }
248 ;
249
250
251
252 /*
253  * Machine specific defaults.
254  */
255  static struct 
256  {
257    int machineType;
258    int clientTimeout;
259    int wmTimeout;
260  }
261  machineDefault[] =
262  {
263    {  0,  20,  60},               /* Machine independent default */
264 #ifdef __hpux
265    {300,  10,  60},               /* HP s300                     */
266    {400,  10,  60},               /* HP s400                     */
267    {600,   5,  60},               /* HP s600                     */
268    {700,   5,  60},               /* HP s700                     */
269    {800,   5,  60},               /* HP s800                     */
270 #endif /* __hpux */
271  };
272  #define MACHINEDEFAULTS (sizeof(machineDefault) / sizeof(machineDefault[0]))
273
274 \f
275 /*************************************<->*************************************
276  *
277  *  _SmWaitClientTimeoutDefault (widget, offset, value)
278  *
279  *
280  *  Description:
281  *  -----------
282  *  This function generates a default value for the waitClientTimeout resource.
283  *  We dynamically default to 10 seconds for s400/s300 and to
284  *  5 seconds for s700/s800.
285  *
286  *  Inputs:
287  *  ------
288  *  widget = this is not used
289  *
290  *  offset = this is the resource offset
291  *
292  *  value = this is a pointer to a XrmValue in which to store the result
293  *
294  *  Outputs:
295  *  -------
296  *  value = default resource value and size
297  *
298  *************************************<->***********************************/
299 static
300 void
301 _SmWaitClientTimeoutDefault (Widget widget, int offset, XrmValue *value)
302 {
303     int i;
304
305     for (i = 0; i < MACHINEDEFAULTS; i++)
306     {
307       if (machineDefault[i].machineType == machineType)
308       {
309         break;
310       }
311     }
312
313     if (i == MACHINEDEFAULTS)
314     {
315       i = 0;
316     }
317
318     value->addr = (char *)&machineDefault[i].clientTimeout;
319     value->size = sizeof (int);
320
321 } /* END OF FUNCTION _SmWaitClientTimeoutDefault */
322
323
324 \f
325 /*************************************<->*************************************
326  *
327  *  _SmWaitWmTimeoutDefault (widget, offset, value)
328  *
329  *
330  *  Description:
331  *  -----------
332  *  This function generates a default value for the waitWmTimeout resource.
333  *  We dynamically default to 60 seconds for s400/s300 and to
334  *  60 seconds for s700/s800.  This could change if we get feedback indicating
335  *  the need for a new default.
336  *
337  *  Inputs:
338  *  ------
339  *  widget = this is not used
340  *
341  *  offset = this is the resource offset
342  *
343  *  value = this is a pointer to a XrmValue in which to store the result
344  *
345  *  Outputs:
346  *  -------
347  *  value = default resource value and size
348  *
349  *************************************<->***********************************/
350 static
351 void
352 _SmWaitWmTimeoutDefault (Widget widget, int offset, XrmValue *value)
353 {
354     int i;
355     
356     smGD.userSetWaitWmTimeout = False; /* if we are here, it is not user set */
357
358     for (i = 0; i < MACHINEDEFAULTS; i++)
359     {
360       if (machineDefault[i].machineType == machineType)
361       {
362         break;
363       }
364     }
365
366     if (i == MACHINEDEFAULTS)
367     {
368       i = 0;
369     }
370
371     value->addr = (char *)&machineDefault[i].wmTimeout;
372     value->size = sizeof (int);
373
374 } /* END OF FUNCTION _SmWaitWmTimeoutDefault */
375
376
377 \f
378 /*************************************<->*************************************
379  *
380  *  InitSMGlobals ()
381  *
382  *
383  *  Description:
384  *  -----------
385  *  Sets SM global resources and global settings to a starting value.
386  *
387  *
388  *  Inputs:
389  *  ------
390  *  buttonForm = form widget for button that allows cursor to get colors
391  *  smRes(global) = structure that holds session resources.
392  *  smToSet(global) = structure that holds "which settings to set and how" info
393  *  smGD(global) = structure that holds general data info
394  * 
395  *  Outputs:
396  *  -------
397  *  smRes(global) = structure that holds session resources.
398  *  smToSet(global) = structure that holds "which settings to set and how" info
399  *  smGD(global) = structure that holds general data info
400  *
401  *  Comments:
402  *  --------
403  *  Resources are set to an initial value by the resource manager.  The
404  *  rest are set in the routine.
405  * 
406  *************************************<->***********************************/
407 void 
408 InitSMGlobals( void )
409 {
410     int i;
411     PropDtSmWindowInfo property;
412     struct utsname nameRec;
413     char *firstSlash;
414     char *keyNum;
415
416     smGD.userSetWaitWmTimeout = True; /* assume it is */
417
418 #ifdef __hpux
419     if (uname(&nameRec) == 0)
420     {
421         keyNum = nameRec.machine;
422         if (firstSlash = strchr(keyNum, '/'))
423         {
424             keyNum = ++firstSlash;
425
426             if (     keyNum[0] == '3') 
427             {
428                 machineType = 300;
429             }
430             else if (keyNum[0] == '4') 
431             {
432                 machineType = 400;
433             }
434             else if (keyNum[0] == '6') 
435             {
436                 machineType = 600;
437             }
438             else if (keyNum[0] == '7') 
439             {
440                 machineType = 700;
441             }
442             else if (keyNum[0] == '8') 
443             {
444                 machineType = 800;
445             }
446         }
447     }
448 #endif /* __hpux */
449
450     /*
451      * Get application specific resource values
452      */
453     XtAppAddConverter (smGD.appCon, XtRString, SmRContManagement,
454                        (XtConverter)SmCvtStringToContManagement, NULL, 0);
455     XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smRes,
456                               sessionResources,
457                               XtNumber(sessionResources), NULL, 0);
458
459     if (smGD.lockOnTimeoutStatus == True)
460     {
461      /*
462       * Pull screen saver resources from Dtsession*extension.<name>.
463       */
464       smGD.SmNextension = "extension";
465       smGD.SmCextension = "Extension";
466       smGD.extensionSpec = "extension.";
467     }
468     else
469     {
470      /*
471       * Pull screen saver resources from Dtsession*<name>.
472       */
473       smGD.SmNextension = smGD.SmNextension = smGD.extensionSpec = "";
474     }
475
476     XtGetSubresources(smGD.topLevelWid, (XtPointer) &smSaverRes,
477                       smGD.SmNextension, smGD.SmCextension,
478                       saverResources,
479                       XtNumber(saverResources), NULL, 0);
480
481     smGD.wmStartup = SmNewString(smRes.wmStartup);
482     smGD.keyholders = SmNewString(smRes.keyholders);
483     smGD.sessionLang = SmNewString(smRes.sessionLang);
484     smGD.saverList = SmNewString(smSaverRes.saverList);
485
486     /*
487      * Initialize general data used by apps not initialized by
488      * XtInitialize or DtInitialize
489      */
490     smGD.topLevelWindow = XtWindow(smGD.topLevelWid);
491     smGD.numSavedScreens = (ScreenCount(smGD.display) > MAX_SCREENS_SAVED)
492          ? MAX_SCREENS_SAVED : ScreenCount(smGD.display);
493     smGD.dtwmRunning = False;
494     smSettings.confirmMode = DtSM_VERBOSE_MODE;
495     if (smGD.sessionType == CURRENT_SESSION ||
496         smGD.sessionType == DEFAULT_SESSION)
497         smSettings.startState = DtSM_CURRENT_STATE;
498     else
499         smSettings.startState = DtSM_HOME_STATE;
500     smGD.homeSave = False;
501     smGD.saverListParse = NULL;
502
503     smGD.loggingOut = False;
504
505     /*
506      * Sanity check on timeouts for negative numbers
507      */
508     if (smRes.waitClientTimeout < 0)
509     {
510         smRes.waitClientTimeout = -smRes.waitClientTimeout;
511     }
512     if (smRes.waitWmTimeout < 0)
513     {
514         smRes.waitWmTimeout = -smRes.waitWmTimeout;
515     }
516     if (smRes.saveYourselfTimeout < 0)
517     {
518         smRes.saveYourselfTimeout = -smRes.saveYourselfTimeout;
519     }
520
521
522     /*
523      * Now convert users view of seconds in to XtAppAddTimout's
524      * need for milliseconds.
525      */
526     smRes.waitClientTimeout = 1000 * smRes.waitClientTimeout;
527     smRes.waitWmTimeout = 1000 * smRes.waitWmTimeout;
528     smRes.saveYourselfTimeout = 1000 * smRes.saveYourselfTimeout;
529     smGD.savedWaitWmTimeout = smRes.waitWmTimeout;
530
531     /*
532      * Initialize lock data
533      */
534     smGD.screen = XDefaultScreen(smGD.display);
535     smGD.blackPixel = XBlackPixel(smGD.display, smGD.screen);
536     smGD.whitePixel = XWhitePixel(smGD.display, smGD.screen);
537     smDD.lockDialog = NULL;
538     smDD.lockCoverDialog = NULL;
539     for(i = 0;i < smGD.numSavedScreens;i++)
540     {
541         smDD.coverDialog[i] = NULL;
542         smDD.coverDrawing[i] = NULL;
543     }
544     smGD.lockedState = UNLOCKED;
545
546    /*
547     * Sanity check screen saver resource values.
548     */ 
549     if (smRes.alarmTime < 0) smRes.alarmTime = 0;
550
551     #define SMBOUND(A) (A < 0 ? 0 : A)
552
553     smSaverRes.lockTimeout = SMBOUND(smSaverRes.lockTimeout) * 60;
554     smSaverRes.saverTimeout = SMBOUND(smSaverRes.saverTimeout) * 60;
555     smSaverRes.cycleTimeout = SMBOUND(smSaverRes.cycleTimeout) * 60;
556
557     CreateLockCursor();
558     smGD.waitCursor = _DtGetHourGlassCursor(smGD.display);
559
560     /*
561      * Initialize other global data related to dialogs
562      */
563     smDD.confExit = NULL;
564     smDD.qExit = NULL;
565     smDD.compatExit = NULL;
566     smDD.deadWid = NULL;
567     smDD.saveSession = NULL;            /* Error dialog for Save_Session */
568
569     if (!smDD.smHelpDialog)
570         /*
571          * Don't wipe it out if it is already created
572          */
573         smDD.smHelpDialog = NULL;
574
575     /*
576      * Intern all the atoms needed for the WSM communication
577      */
578     {
579       enum { XA_DT_SM_WINDOW_INFO, XA_DT_SM_WM_PROTOCOL,
580              XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
581              XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
582              XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
583       static char *atom_names[] = {
584              _XA_DT_SM_WINDOW_INFO, _XA_DT_SM_WM_PROTOCOL,
585              _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
586              _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
587              _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };
588
589       Atom atoms[XtNumber(atom_names)];
590
591       XInternAtoms(smGD.display, atom_names, XtNumber(atom_names),
592                    False, atoms);
593
594       XaVsmInfo = atoms[XA_DT_SM_WINDOW_INFO];
595       XaSmWmProtocol = atoms[XA_DT_SM_WM_PROTOCOL];
596       XaSmStartAckWindow = atoms[XA_DT_SM_START_ACK_WINDOWS];
597       XaSmStopAckWindow = atoms[XA_DT_SM_STOP_ACK_WINDOWS];
598       XaWmWindowAck = atoms[XA_DT_WM_WINDOW_ACK];
599       XaWmExitSession = atoms[XA_DT_WM_EXIT_SESSION];
600       XaWmLockDisplay = atoms[XA_DT_WM_LOCK_DISPLAY];
601       XaWmReady = atoms[XA_DT_WM_READY];
602     }
603
604     /*
605      * Set the session manager window property on the root window
606      */
607     property.flags = 0;
608     property.smWindow = (unsigned long) smGD.topLevelWindow;
609     XChangeProperty (smGD.display, RootWindow(smGD.display, 0),
610                      XaVsmInfo, XaVsmInfo,
611                      32, PropModeReplace, (unsigned char *)&property,
612                      PROP_DT_SM_WINDOW_INFO_ELEMENTS);
613
614     /*
615      * Set up the signal handler for forking and execing
616      */
617     sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
618 }
619
620
621 \f
622 /*************************************<->*************************************
623  *
624  *  SetRestorePath ()
625  *
626  *
627  *  Description:
628  *  -----------
629  *  Sets SM global resources and global settings to a starting value.
630  *
631  *
632  *  Inputs:
633  *  ------
634  *  smGD.display = display structure for session manager.  Used to construct
635  *                     a display directory
636  * 
637  *  Outputs:
638  *  -------
639  *  smGD.resourcePath(global) = Path where the resources to be restored are
640  *                              held
641  *  smGD.settingPath(global) = Path where the settings to be restored are
642  *                              held
643  *  smGD.clientPath(global) = Path where the clients to be restored are
644  *                              held
645  *  smGD.savePath(global) = Path where all save files are to be saved
646  *
647  *  Return:
648  *  ------
649  *  Display connection
650  *
651  *  Comments:
652  *  --------
653  *  WARNING:  This routine also determines whether dtsession is being started
654  *            in compatibility mode.  If so - no restore paths are set up and
655  *            the routine is exited.
656  * 
657  *************************************<->***********************************/
658 int
659 SetRestorePath(
660         unsigned int argc,
661         char *argv[] )
662 {
663     Display  *tmpDisplay;
664     int         i;
665     char        *displayName = NULL;
666     char        *session_option = NULL;
667
668     smGD.compatMode = False;
669
670     for(i = 0;i < argc;i++)
671     {
672         if(!strcmp(argv[i], "-display"))
673         {
674             displayName = argv[i + 1];
675             /* 
676              * If -display is used but DISPLAY is not set,
677              * put DISPLAY into the environment
678              */
679             if (getenv("DISPLAY") == 0)
680             {
681                 sprintf(tmpDisplayName, "DISPLAY=%s", displayName);
682                 putenv(tmpDisplayName);
683             }
684         }
685
686         if(!strcmp(argv[i], "-norestore"))
687         {
688             smGD.compatMode = True;
689         }
690
691         if(!strcmp(argv[i], "-session"))
692         {
693             i++;
694             if (i >= argc) 
695             {
696                 char            *pch;
697
698                 pch = strdup ((char *) GETMESSAGE (40, 15,
699                         " No session name was provided for the -session command line option."));
700                 if (!pch) 
701                 { 
702                     DtMsgLogMessage (argv[0], DtMsgLogWarning, pch);
703                     free (pch);
704                 }
705                 break;
706             }
707             session_option = argv[i];
708         }
709     }
710
711     /*
712      *  If we are in compatibility mode - no restore paths are set
713      *  up and we just return
714      */
715     if(smGD.compatMode == True)
716     {
717         smGD.clientPath[0] = NULL;
718         smGD.resourcePath[0] = NULL;
719         smGD.settingPath[0] = NULL;
720         smGD.sessionType = DEFAULT_SESSION;
721         smGD.restoreSession = NULL;
722         return(0);
723     }
724
725     tmpDisplay = XOpenDisplay(displayName);
726     if(tmpDisplay == NULL)
727     {
728         PrintError(DtError, GETMESSAGE(4, 1, "Invalid display name - exiting."));
729         SM_EXIT(-1);
730     }
731
732     if (session_option) 
733     {
734         if (!InitializeSpecificSession (session_option, tmpDisplay, argc, argv))
735                 InitializeGenericSession (tmpDisplay);
736     }
737     else 
738         InitializeGenericSession (tmpDisplay);
739
740     /*
741      * Need to know if the session is for a specific display
742      */
743     smGD.displaySpecific = True;
744     if (session_option = strrchr (smGD.savePath, '/')) 
745     {
746         session_option++;
747         if (!strcmp (session_option, DtSM_SESSION_DIRECTORY))
748             smGD.displaySpecific = False;
749     }
750
751     TrimErrorlog();
752     XCloseDisplay(tmpDisplay);
753
754     /* 
755     ** User's session startup script:
756     **   $HOME/.dt/sessions/sessionetc
757     */
758     strcpy(smGD.etcPath, smGD.savePath);
759     strcat(smGD.etcPath, "/");
760     strcat(smGD.etcPath, smEtcFile);
761
762     /* 
763     ** User's session shutdown script: 
764     **   $HOME/.dt/sessions/sessionexit
765     */
766     strcpy(smGD.exitPath, smGD.savePath);
767     strcat(smGD.exitPath, "/");
768     strcat(smGD.exitPath, smExitFile);
769
770     return(0);
771 }
772
773 void
774 FixPath
775     (
776     char * the1stPath
777     )
778 {
779     char * tempPath;
780     char * pathList = (char *)XtMalloc(strlen(SM_SYSTEM_PATH) +
781                          strlen(":" CDE_INSTALLATION_TOP "/config") + 1);
782
783     strcpy(pathList,SM_SYSTEM_PATH);
784     strcat(pathList,":" CDE_INSTALLATION_TOP "/config");
785
786     tempPath = _DtQualifyWithFirst(the1stPath,pathList);
787     if (tempPath != NULL) {
788         strcpy(the1stPath,tempPath);
789         free(tempPath);
790     }
791
792     XtFree(pathList);
793 }
794
795 \f
796 /*************************************<->*************************************
797  *
798  *  SetSysDefaults ()
799  *
800  *
801  *  Description:
802  *  -----------
803  *  Sets the path to restore the system default files. A convenience routine
804  *
805  *
806  *  Inputs:
807  *  ------
808  *  smGD.savePath = path that files are to be saved in (set up in
809  *                      SetRestorePaths)
810  * 
811  *  Outputs:
812  *  -------
813  *  smGD.resourcePath(global) = Path where the resources to be saved are
814  *                              to be saved.
815  *  smGD.settingPath(global) = Path where the settings to be saved are
816  *                              to be saved.
817  *  smGD.clientPath(global) = Path where the clients to be saved are
818  *                              to be saved.
819  *
820  *  Comments:
821  *  --------
822  * 
823  *************************************<->***********************************/
824 static int 
825 SetSysDefaults( void )
826 {
827     int status;
828     struct stat buf;
829     String tmpString;
830     char        *langSpec;
831     char        *tempPath;
832
833     /*
834      * No files exist for restoration - use the
835      * system defaults
836      */
837     strcpy(smGD.resourcePath, "");
838     strcpy(smGD.clientPath, "");
839     smGD.settingPath[0] = NULL;
840     smGD.sessionType = DEFAULT_SESSION;
841     smGD.restoreSession = (char *) SM_SYSTEM_DIRECTORY;
842
843     langSpec = getenv("LANG");
844     if ((langSpec != NULL) && (*langSpec != 0))
845     {
846         strcat(smGD.clientPath, "/");
847         strncat(smGD.clientPath, langSpec, MAXPATHLEN-2);
848         smGD.clientPath[MAXPATHLEN-1];
849     }
850     
851     strcat(smGD.clientPath, "/");
852     strcat(smGD.clientPath, SM_SYSTEM_CLIENT_FILE);
853    
854     FixPath(smGD.clientPath);
855
856     /*
857      * If the system files don't exist - we're in
858      * trouble - First try LANG location then default
859      */
860     status = stat(smGD.clientPath, &buf);
861     if(status == -1)
862     {
863         if((langSpec == NULL) || (*langSpec == 0))
864         {
865             PrintErrnoError(DtError, GETMESSAGE(4, 2,
866                         "No defaults files exist.  "
867                         "No applications will be restarted."));
868             smGD.clientPath[0] = NULL;
869             smGD.resourcePath[0] = NULL;
870         }
871         else
872         {
873             strcpy(smGD.clientPath, "/C/");
874             strcat(smGD.clientPath, SM_SYSTEM_CLIENT_FILE);
875
876             FixPath(smGD.clientPath);
877
878             status = stat(smGD.clientPath, &buf);
879             if(status == -1)
880             {
881                 PrintErrnoError(DtError, GETMESSAGE(4, 3,
882                             "No defaults files exist.  "
883                             "No applications will be restarted."));
884                 smGD.clientPath[0] = NULL;
885                 smGD.resourcePath[0] = NULL;
886             }
887         }
888     }
889     
890     return(0);
891 }
892
893
894 \f
895 /*************************************<->*************************************
896  *
897  *  SetResSet ()
898  *
899  *
900  *  Description:
901  *  -----------
902  *  Sets the path to restore the settings and resource files.
903  *  A convenience routine
904  *
905  *
906  *  Inputs:
907  *  ------
908  *  smGD.savePath = path that files are to be saved in (set up in
909  *                      SetRestorePaths)
910  * 
911  *  Outputs:
912  *  -------
913  *  smGD.resourcePath(global) = Path where the resources to be saved are
914  *                              to be saved.
915  *  smGD.settingPath(global) = Path where the settings to be saved are
916  *                              to be saved.
917  *  smGD.clientPath(global) = Path where the clients to be saved are
918  *                              to be saved.
919  *
920  *  Comments:
921  *  --------
922  * 
923  *************************************<->***********************************/
924 static int 
925 SetResSet( void )
926 {
927     int status;
928     struct stat buf;
929     
930     /*
931      * If resource or settings file does not exist - just null out
932      * the path so these things will not get restored
933      */
934     status = stat(smGD.resourcePath, &buf);
935     if(status == -1)
936     {
937         smGD.resourcePath[0] = NULL;
938     }
939
940     status = stat(smGD.settingPath, &buf);
941     if(status == -1)
942     {
943         smGD.settingPath[0] = NULL;
944     }
945     return(0);
946 }
947
948
949 /*************************************<->*************************************
950  *
951  *  UndoSetSavePath () - Undoes the directory manipulations done by 
952  *      SetSavePath.  This function is only called if a shutdown/save
953  *      is canceled.
954  *
955  *************************************<->***********************************/
956 void 
957 UndoSetSavePath ( )
958 {
959         char                    * buf;
960
961         if (strcmp ("", savedDir)) {
962
963                 /*
964                  * Remove the directory where the save occurred, e.g.:
965                  *
966                  *    ~/.dt/<session_dir>/current
967                  *    ~/.dt/<session_dir>/home
968                  */
969                 buf = XtMalloc (strlen (savedDir) + 9);
970                 sprintf (buf, "rm -rf %s", savedDir);
971                 SystemCmd (buf);
972                 XtFree (buf);
973
974                 if (strcmp ("", savedOldDir)) {
975
976                         MoveDirectory (savedOldDir, savedDir, False);
977
978                         if (strcmp ("", savedTmpDir)) {
979                                 MoveDirectory (savedTmpDir, savedOldDir, False);
980                         }
981                 }
982         }
983 }
984
985 \f
986 /*************************************<->*************************************
987  *
988  *  SetSavePath (saveToHome, mode)
989  *
990  *
991  *  Description:
992  *  -----------
993  *  Sets up paths for files that need to be saved.  Also removes any files
994  *  that shouldn't be there after the save.
995  *
996  *
997  *  Inputs:
998  *  ------
999  *  smGD.display = display structure for session manager.  Used to construct
1000  *                     a display directory
1001  *  saveToHome = whether this is a save to home session or not
1002  *  mode = whether we are resetting or restarting
1003  * 
1004  *  Outputs:
1005  *  -------
1006  *  smGD.resourcePath(global) = Path where the resources to be saved are
1007  *                              to be saved.
1008  *  smGD.settingPath(global) = Path where the settings to be saved are
1009  *                              to be saved.
1010  *  smGD.clientPath(global) = Path where the clients to be saved are
1011  *                              to be saved.
1012  *
1013  *  Comments:
1014  *  --------
1015  * 
1016  *************************************<->***********************************/
1017 int 
1018 SetSavePath(
1019         Boolean saveToHome,
1020         int mode )
1021 {
1022     struct stat         buf;
1023     int                 status;
1024
1025     /*
1026      * These directory paths are needed in UndoSetSavePaths
1027      * if a shutdown/save is canceled.
1028      */
1029     strcpy (savedDir, "");
1030     strcpy (savedOldDir, "");
1031     strcpy (savedTmpDir, "");
1032     
1033     /*
1034      * Make sure the user hasn't done something like delete the .dt
1035      * directories during the session.  If so - recreate them
1036      */
1037     SM_FREE(smGD.savePath);
1038     smGD.savePath = _DtCreateDtDirs(smGD.display);
1039     if(smGD.savePath == NULL)
1040     {
1041         PrintErrnoError(DtError, smNLS.cantCreateDirsString);
1042         smGD.clientPath[0] = NULL;
1043         smGD.settingPath[0] = NULL;
1044         smGD.resourcePath[0] = NULL;
1045         return(-1);
1046     }
1047         
1048     
1049     /*
1050      * Path for a save defaults to save the current session.
1051      * Otherwise just remove the directories
1052      */
1053     strcpy(smGD.clientPath, smGD.savePath);
1054     strcpy(smGD.settingPath, smGD.savePath);
1055     strcpy(smGD.resourcePath, smGD.savePath);
1056     strcat(smGD.clientPath, "/");
1057     strcat(smGD.settingPath, "/");
1058     strcat(smGD.resourcePath, "/");
1059
1060     if(saveToHome == False)
1061     {
1062         strcat(smGD.clientPath, SM_CURRENT_DIRECTORY);
1063         strcat(smGD.resourcePath, SM_CURRENT_DIRECTORY);
1064         strcat(smGD.settingPath, SM_CURRENT_DIRECTORY);
1065         smGD.restoreSession = SM_CURRENT_DIRECTORY;
1066     }
1067     else
1068     {
1069         strcat(smGD.clientPath, SM_HOME_DIRECTORY);
1070         strcat(smGD.resourcePath, SM_HOME_DIRECTORY);
1071         strcat(smGD.settingPath, SM_HOME_DIRECTORY);
1072         smGD.restoreSession = SM_HOME_DIRECTORY;
1073     }
1074
1075     if ((mode == DtSM_HOME_STATE) && (saveToHome == False) && 
1076        (smSettings.startState == DtSM_HOME_STATE))
1077     {
1078         /* 
1079          * The only time this should should be true is if the
1080          * current session is a Home session and the session
1081          * is being exited.  The idea is that if a "current"
1082          * directory exits, it must be moved because when the
1083          * user next logs in, a Home session should be started
1084          * (if a session is not selected at the login screen)
1085          * and the Session Manager decides whether or not it
1086          * starts a Home or Current session based on if a
1087          * "current" directory exists.  If a "current" directory
1088          * exists, a Current session will be started.
1089          */
1090         status = stat(smGD.clientPath, &buf);
1091         if(status != -1)
1092         {
1093             /*
1094              * The "current" directory exists and must be moved to its
1095              * ".old" version.  But first, if the ".old" version exists,
1096              * it must be moved to a temporary directory.  This temporary
1097              * directory will eventually be pruned - when a user next
1098              * runs a Current session and saves the session.
1099              */
1100             strcpy (savedDir, smGD.clientPath);
1101             sprintf(smGD.etcPath, "%s.%s", smGD.clientPath, SM_OLD_EXTENSION);
1102             status = stat(smGD.etcPath, &buf);
1103             if(status == 0)
1104             {
1105                 char            * tmpName;
1106                 char            * tmpDir;
1107
1108                 strcpy (savedOldDir, smGD.etcPath);
1109
1110                 tmpName = (char *) XtMalloc (strlen (smGD.restoreSession) + 2);
1111                 sprintf (tmpName, "%s.", smGD.restoreSession);
1112                 if (strlen (tmpName) > 5) {
1113                         tmpName[4] = '.';
1114                         tmpName[5] = '\000';
1115                 }
1116                 tmpDir = (char *) tempnam (smGD.savePath, tmpName);
1117                 MoveDirectory (smGD.etcPath, tmpDir, False);
1118
1119                 strcpy (savedTmpDir, tmpDir);
1120                 free (tmpDir);
1121                 XtFree ((char *) tmpName);
1122             }
1123             MoveDirectory(smGD.clientPath, smGD.etcPath, False);
1124         }
1125
1126         smGD.clientPath[0] = NULL;
1127         smGD.settingPath[0] = NULL;
1128         smGD.resourcePath[0] = NULL;
1129     }
1130     else
1131     {
1132         strcpy (savedDir, smGD.clientPath);
1133
1134         /*
1135          * If the desired directory doesn't exist, create it.
1136          */
1137         status = stat(smGD.clientPath, &buf);
1138         if(status == -1)
1139         {
1140             status = mkdir(smGD.clientPath, 0000);
1141             if(status == -1)
1142             {
1143                 PrintErrnoError(DtError, smNLS.cantCreateDirsString);
1144                 smGD.clientPath[0] = NULL;
1145                 smGD.settingPath[0] = NULL;
1146                 smGD.resourcePath[0] = NULL;
1147                 return(-1);
1148             }
1149             chmod(smGD.clientPath, 0755);
1150         }
1151         else
1152         {
1153             /*
1154              * The desired directory already exists so it must
1155              * be archived by moving it to its ".old" version. But
1156              * first, if its ".old" version already exists, it must
1157              * be moved to a temporary directory that will be removed 
1158              * when the session directories are pruned - after the
1159              * save is complete.
1160              */
1161             char                * tmpName;
1162             char                * tmpDir;
1163
1164             sprintf(smGD.etcPath, "%s.%s", smGD.clientPath, SM_OLD_EXTENSION);
1165             status = stat(smGD.etcPath, &buf);
1166             if(status == 0)
1167             {
1168                 tmpName = (char *) XtMalloc (strlen (smGD.restoreSession) + 2);
1169                 sprintf (tmpName, "%s.", smGD.restoreSession);
1170                 strcpy (savedOldDir, smGD.etcPath);
1171                 if (strlen (tmpName) > 5) {
1172                         tmpName[4] = '.';
1173                         tmpName[5] = '\000';
1174                 }
1175                 tmpDir = (char *) tempnam (smGD.savePath, tmpName);
1176                 MoveDirectory (smGD.etcPath, tmpDir, False);
1177
1178                 strcpy (savedTmpDir, tmpDir);
1179                 free (tmpDir);
1180                 XtFree ((char *) tmpName);
1181             }
1182
1183             MoveDirectory(smGD.clientPath, smGD.etcPath, False);
1184
1185             /*
1186              * Now re-make the directory
1187              */
1188                status = mkdir(smGD.clientPath, 0000);
1189                if(status == -1)
1190                {
1191                 PrintErrnoError(DtError, smNLS.cantCreateDirsString);
1192                 smGD.clientPath[0] = NULL;
1193                 smGD.settingPath[0] = NULL;
1194                 smGD.resourcePath[0] = NULL;
1195                 return(-1);
1196             }
1197             chmod(smGD.clientPath, 0755);
1198         }
1199         
1200         strcat(smGD.clientPath, "/");
1201         strcat(smGD.clientPath, SM_CLIENT_FILE2);
1202         strcat(smGD.settingPath, "/");
1203         strcat(smGD.settingPath, SM_SETTING_FILE);
1204         strcat(smGD.resourcePath, "/");
1205         strcat(smGD.resourcePath, SM_RESOURCE_FILE);
1206     }
1207
1208     return(0);
1209 }
1210
1211 \f
1212 /*************************************<->*************************************
1213  *
1214  *  SetFontSavePath (saveToHome, mode)
1215  *
1216  *
1217  *  Description:
1218  *  -----------
1219  *  Sets up the save path for the auxillary directory.
1220  *
1221  *
1222  *  Inputs:
1223  *  ------
1224  *
1225  *  Outputs:
1226  *  -------
1227  *
1228  *  Comments:
1229  *  --------
1230  * 
1231  *************************************<->***********************************/
1232 int 
1233 SetFontSavePath(char *langPtr)
1234 {
1235     struct stat         buf;
1236     int                 status;
1237     char                *sessionSaved;
1238     
1239
1240     /*
1241      * Set up the session font directory and see if it exists
1242      */
1243     if(smGD.sessionType == CURRENT_SESSION)
1244     {
1245         sessionSaved = SM_CURRENT_FONT_DIRECTORY;
1246     }
1247     else
1248     {
1249         sessionSaved = SM_HOME_FONT_DIRECTORY;
1250     }
1251
1252     sprintf(smGD.fontPath, "%s/%s", smGD.savePath, sessionSaved);
1253     status = stat(smGD.fontPath, &buf);
1254     if(status == -1)
1255     {
1256         status = mkdir(smGD.fontPath, 0000);
1257         if(status == -1)
1258         {
1259             PrintErrnoError(DtError, smNLS.cantCreateDirsString);
1260             smGD.fontPath[0] = NULL;
1261             return(-1);
1262         }
1263         chmod(smGD.fontPath, 0755);
1264     }
1265
1266     /*
1267      * Now add the lang subdirectory and see if it exists
1268      */
1269     strcat(smGD.fontPath, "/");
1270     strcat(smGD.fontPath, langPtr);
1271     status = stat(smGD.fontPath, &buf);
1272     if(status == -1)
1273     {
1274         status = mkdir(smGD.fontPath, 0000);
1275         if(status == -1)
1276         {
1277             PrintErrnoError(DtError, smNLS.cantCreateDirsString);
1278             smGD.fontPath[0] = NULL;
1279             return(-1);
1280         }
1281         chmod(smGD.fontPath, 0755);
1282     }
1283
1284     return(0);
1285 }
1286
1287                       
1288 \f
1289 /*************************************<->*************************************
1290  *
1291  *  RemoveFiles()
1292  *
1293  *
1294  *  Description:
1295  *  -----------
1296  *  Remove the files that need to be removed
1297  *
1298  *
1299  *  Inputs:
1300  *  ------
1301  * 
1302  *  Outputs:
1303  *  -------
1304  *
1305  *
1306  *  Comments:
1307  *  --------
1308  * 
1309  *************************************<->***********************************/
1310 static void 
1311 RemoveFiles(
1312         char *path )
1313 {
1314     pid_t  clientFork;
1315     int    execStatus, childStatus, i, statLoc;
1316     String tmpString;
1317
1318     /*
1319      * Fork and exec the client process
1320      */
1321     sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
1322
1323     clientFork = vfork();
1324     
1325     /*
1326      * If the fork fails - Send out an error and return
1327      */
1328     if(clientFork < 0)
1329     {
1330         PrintErrnoError(DtError, smNLS.cantForkClientString);
1331         return;
1332     }
1333     
1334     /*
1335      * Fork succeeded - now do the exec
1336      */
1337     if(clientFork == 0)
1338     {
1339         SetSIGPIPEToDefault ();
1340
1341         /*
1342          * Set the gid of the process back from bin
1343          */
1344 #ifndef __hpux
1345 #ifndef SVR4
1346         setregid(smGD.runningGID, smGD.runningGID);
1347 #else
1348         setgid(smGD.runningGID);
1349         setegid(smGD.runningGID);
1350 #endif
1351 #endif
1352
1353         _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1354         
1355 #ifdef __osf__
1356         setsid();
1357 #else
1358         (void) setpgrp();
1359 #endif /* __osf__ */
1360          
1361         execStatus = execlp("rm","rm", "-rf", path, (char *) 0);
1362         if(execStatus != 0)
1363         {
1364             tmpString = ((char *)GETMESSAGE(4, 4, "Unable to remove session directory.  Make sure write permissions exist on $HOME/.dt directory.  Invalid session files will not be removed.")) ;
1365             PrintErrnoError(DtError, tmpString);
1366             SM_FREE(tmpString);
1367             SM_EXIT(-1);
1368         }
1369     }
1370
1371     while(wait(&statLoc) != clientFork);
1372     
1373     sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
1374 }
1375                       
1376 \f
1377 /*************************************<->*************************************
1378  *
1379  *  MoveDirectory()
1380  *
1381  *  Description:
1382  *  -----------
1383  *  Move the directory specified by pathFrom - to the directory specified
1384  *  by pathTo.
1385  *
1386  *  Inputs:
1387  *  ------
1388  *  pathFrom = the directory to move from
1389  *  pathTo = the directory to move to
1390  *  removeDestDir = if True, directory pathTo is removed before the
1391  *      move occurs
1392  * 
1393  *  Outputs:
1394  *  -------
1395  *
1396  *  Comments:
1397  *  --------
1398  * 
1399  *************************************<->***********************************/
1400 void 
1401 MoveDirectory(
1402         char            *pathFrom,
1403         char            *pathTo,
1404         Boolean         removeDestDir)
1405 {
1406     struct stat buf;
1407     pid_t  clientFork;
1408     int    status, execStatus, childStatus, i, statLoc;
1409     String tmpString;
1410
1411     /*
1412      * If the pathTo directory exists - remove it
1413      */
1414     if (removeDestDir) 
1415     {
1416         status = stat(pathTo, &buf);
1417         if(status != -1)
1418         {
1419             RemoveFiles(pathTo);
1420         }
1421     }
1422            
1423     /*
1424      * Fork and exec the client process
1425      */
1426     sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
1427
1428     clientFork = vfork();
1429     
1430     /*
1431      * If the fork fails - Send out an error and return
1432      */
1433     if(clientFork < 0)
1434     {
1435         PrintErrnoError(DtError, smNLS.cantForkClientString);
1436         return;
1437     }
1438     
1439     /*
1440      * Fork succeeded - now do the exec
1441      */
1442     if(clientFork == 0)
1443     {
1444         SetSIGPIPEToDefault ();
1445
1446         /*
1447          * Set the gid of the process back from bin
1448          */
1449 #ifndef __hpux
1450 #ifndef SVR4
1451         setregid(smGD.runningGID, smGD.runningGID);
1452 #else
1453         setgid(smGD.runningGID);
1454         setegid(smGD.runningGID);
1455 #endif
1456 #endif
1457
1458         _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1459         
1460 #ifdef __osf__
1461         setsid();
1462 #else
1463         (void) setpgrp();
1464 #endif /* __osf__ */
1465         
1466         execStatus = execlp("mv","mv", pathFrom, pathTo, (char *) 0);
1467         if(execStatus != 0)
1468         {
1469             tmpString = ((char *)GETMESSAGE(4, 4, "Unable to remove session directory.  Make sure write permissions exist on $HOME/.dt directory.  Invalid session files will not be removed.")) ;
1470             PrintErrnoError(DtError, tmpString);
1471             SM_FREE(tmpString);
1472             SM_EXIT(-1);
1473         }
1474     }
1475
1476     while(wait(&statLoc) != clientFork);
1477     
1478     sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
1479 }
1480
1481                                       
1482 \f
1483 /*************************************<->*************************************
1484  *
1485  *  InitNlsStrings()
1486  *
1487  *
1488  *  Description:
1489  *  -----------
1490  *  Initialize the NLS strings used in dtsession
1491  *
1492  *
1493  *  Inputs:
1494  *  ------
1495  * 
1496  *  Outputs:
1497  *  -------
1498  *
1499  *
1500  *  Comments:
1501  *  --------
1502  * 
1503  *************************************<->***********************************/
1504 void 
1505 InitNlsStrings( void )
1506 {
1507     char        *tmpString;
1508
1509     /*
1510      * Malloc failure error message - THIS MESSAGE MUST BE INITIALIZED FIRST
1511      */
1512     smNLS.cantMallocErrorString = strdup (((char *)GETMESSAGE(4, 5, "Unable to malloc memory for operation.")));
1513
1514     /*
1515      * Error message when dtsession cant lock the display
1516      */
1517     smNLS.cantLockErrorString = strdup (((char *)GETMESSAGE(4, 6, "Unable to lock display.  Another application may have the pointer or keyboard grabbed.")));
1518
1519     /*
1520      * Error message when dtsession cant open files for reading or writing
1521      */
1522     smNLS.cantOpenFileString = strdup (((char *)GETMESSAGE(4, 7, "Unable to open session file.  No clients will be restarted.")));
1523
1524     /*
1525      * Error message when dtsession cant fork client process
1526      */
1527     smNLS.cantForkClientString = strdup (((char *)GETMESSAGE(4, 8, "Unable to fork client process.")));
1528
1529     /*
1530      * Error message when dtsession cant create dt directories
1531      */
1532     smNLS.cantCreateDirsString = strdup (((char *)GETMESSAGE(4, 9, "Unable to create DT directories.  Check permissions on home directory.")));
1533
1534     /*
1535      * Error message when trying to lock display on trusted system
1536      */
1537     smNLS.trustedSystemErrorString = strdup (((char *)GETMESSAGE(4, 10, "Unable to lock display due to security restrictions")));
1538 }
1539  
1540                                       
1541 \f
1542 /*************************************<->*************************************
1543  *
1544  *  WaitChildDeath()
1545  *
1546  *
1547  *  Description:
1548  *  -----------
1549  *  When a SIGCHLD signal comes in, wait for all child processes to die.
1550  *
1551  *
1552  *  Inputs:
1553  *  ------
1554  * 
1555  *  Outputs:
1556  *  -------
1557  *
1558  *
1559  *  Comments:
1560  *  --------
1561  * 
1562  *************************************<->***********************************/
1563
1564 void
1565 WaitChildDeath( int i )
1566 {
1567   int   stat_loc;
1568   pid_t pid;
1569
1570  /*
1571   * Wait on any children that have died since the last SIGCHLD we
1572   * received. Any child process death that occurs while we are 
1573   * in WaitChildDeath() will not result in a SIGCHLD. Any
1574   * child proceses that die after our last call to waitpid() will
1575   * remain zombiefied until the next invocation of WaitChildDeath().
1576   */
1577   while ((pid = waitpid(-1, &stat_loc, WNOHANG)) > 0)
1578   ;
1579
1580   sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
1581 }
1582
1583                                       
1584 \f
1585 /*************************************<->*************************************
1586  *
1587  *  TrimErrorlog()
1588  *
1589  *
1590  *  Description:
1591  *  -----------
1592  *  Trim the errorlog file using the following algorithm:
1593  *      if(errorlog.old exists and is not empty) move it to errorlog.oldest
1594  *      if(errorlog exists and is not empty) move it to errorlog.old
1595  *
1596  *
1597  *  Inputs:
1598  *  ------
1599  * 
1600  *  Outputs:
1601  *  -------
1602  *
1603  *
1604  *  Comments:
1605  *  --------
1606  * 
1607  *************************************<->***********************************/
1608 static void
1609 TrimErrorlog( void )
1610 {
1611     char        *savePath,      /* common path element for all pathnames */
1612                 *checkPath1, 
1613                 *checkPath2;
1614     struct stat buf;
1615     int len, status;
1616     char *home;
1617
1618     /*
1619      * Allocate the strings needed
1620      */
1621     savePath = (char *) SM_MALLOC(MAXPATHLEN + 1);
1622     checkPath1 = (char *) SM_MALLOC(MAXPATHLEN + 1);
1623     checkPath2 = (char *) SM_MALLOC(MAXPATHLEN + 1);
1624     if ((home=getenv("HOME")) == NULL)
1625         home="";
1626     
1627     len = strlen(home) + strlen(DtPERSONAL_CONFIG_DIRECTORY) + 2;
1628     if (len > MAXPATHLEN) savePath = SM_REALLOC(savePath, len);
1629     sprintf(savePath, "%s/%s", home, DtPERSONAL_CONFIG_DIRECTORY);
1630     
1631     /*
1632      * If errorlog.old exists and it is not empty, delete
1633      * errorlog.older and then move errolog.old to 
1634      * errorlog.older
1635      */
1636     if (len + strlen(DtOLDER_ERRORLOG_FILE) > MAXPATHLEN)
1637       checkPath1 = SM_REALLOC(savePath, len + strlen(DtOLDER_ERRORLOG_FILE));
1638     sprintf(checkPath1, "%s/%s", savePath, DtOLDER_ERRORLOG_FILE);
1639
1640     if (len + strlen(DtOLD_ERRORLOG_FILE) > MAXPATHLEN)
1641       checkPath2 = SM_REALLOC(savePath, len + strlen(DtOLD_ERRORLOG_FILE));
1642     sprintf(checkPath2, "%s/%s", savePath, DtOLD_ERRORLOG_FILE);
1643
1644     status = stat(checkPath2, &buf);
1645     if((status != -1) && (buf.st_size > 0))
1646     {
1647         (void) unlink(checkPath1);
1648         (void) link(checkPath2, checkPath1);
1649         (void) unlink(checkPath2);
1650     }
1651
1652     /*
1653      * If errorlog exists and it is not empty, move it to
1654      * errorlog.old
1655      */
1656     if (len + strlen(DtERRORLOG_FILE) > MAXPATHLEN)
1657       checkPath1 = SM_REALLOC(savePath, len + strlen(DtERRORLOG_FILE));
1658     sprintf(checkPath1, "%s/%s", savePath, DtERRORLOG_FILE);
1659
1660     status = stat(checkPath1, &buf);
1661     if((status != -1) && (buf.st_size > 0))
1662     {
1663         (void) link(checkPath1, checkPath2);
1664         (void) unlink(checkPath1);
1665     }
1666
1667     SM_FREE((char *) savePath);
1668     SM_FREE((char *) checkPath1);
1669     SM_FREE((char *) checkPath2);
1670
1671     return;
1672 }
1673
1674                                       
1675 \f
1676 /*************************************<->*************************************
1677  *
1678  *  SetSystemReady()
1679  *
1680  *
1681  *  Description:
1682  *  -----------
1683  *  Do everything that needs to be done to get the system back into a
1684  *  READY state.  This includes checking to be sure that the BMS did not
1685  *  die while we were in process
1686  *
1687  *
1688  *  Inputs:
1689  *  ------
1690  * 
1691  *  Outputs:
1692  *  -------
1693  *
1694  *
1695  *  Comments:
1696  *  --------
1697  * 
1698  *************************************<->***********************************/
1699 void
1700 SetSystemReady( void )
1701 {
1702     smGD.smState = READY;
1703     if(smGD.bmsDead == True)
1704     {
1705         WarnMsgFailure();
1706     }
1707
1708     return;
1709 }
1710
1711
1712 /*************************************<->*************************************
1713  *
1714  *  SmCvtStringToContManagement (args, numArgs, fromVal, toVal)
1715  *
1716  *
1717  *  Description:
1718  *  -----------
1719  *  This function converts a string to a value for the 
1720  *  contention management flag set.
1721  *
1722  *
1723  *  Inputs:
1724  *  ------
1725  *  args = additional XrmValue arguments to the converter - NULL here
1726  *
1727  *  numArgs = number of XrmValue arguments - 0 here
1728  *
1729  *  fromVal = resource value to convert
1730  *
1731  * 
1732  *  Outputs:
1733  *  -------
1734  *  toVal = descriptor to use to return converted value
1735  *
1736  *************************************<->***********************************/
1737
1738 void SmCvtStringToContManagement (XrmValue *args, Cardinal numArgs, XrmValue *fromVal, XrmValue *toVal)
1739 {
1740
1741     unsigned char       *pch = (unsigned char *) (fromVal->addr);
1742     unsigned char       *pchNext;
1743     int         len;
1744     static long cval;
1745     Boolean     fHit = False;
1746     Boolean    fAddNext = True;
1747
1748 /*
1749  * Names of contention management options
1750  */
1751
1752 #define CM_ALL_STR              (unsigned char *)"all"
1753 #define CM_SYSTEM_STR           (unsigned char *)"system"
1754 #define CM_HANDSHAKE_STR        (unsigned char *)"handshake"
1755 #define CM_NONE_STR             (unsigned char *)"none"
1756
1757     /*
1758      * Check first token. If '-' we subtract from all options.
1759      * Otherwise, we start with no contention management and add things in.
1760      */
1761
1762     if (*pch &&
1763         (_DtNextToken (pch, &len, &pchNext)) &&
1764         (*pch == '-'))
1765     {
1766         cval = SM_CM_ALL;
1767         fHit = True;
1768     }
1769     else
1770     {
1771         cval = SM_CM_NONE;
1772     }
1773
1774     while (*pch && _DtNextToken (pch, &len, &pchNext))
1775     {
1776            /*
1777             * Strip off "sign" if prepended to another token, and process
1778             * that token the next time through.
1779             */
1780
1781         if (*pch == '+')
1782         {
1783             if (len != 1)
1784             {
1785                 pchNext = pch + 1;
1786             }
1787             fAddNext = TRUE;
1788         }
1789
1790         else if (*pch == '-')
1791         {
1792             if (len != 1)
1793             {
1794                 pchNext = pch + 1;
1795             }
1796             fAddNext = FALSE;
1797         }
1798
1799         if ((*pch == 'A') || (*pch == 'a'))
1800         {
1801             if (_DtWmStringsAreEqual (pch, CM_ALL_STR, len))
1802             {
1803                 cval = fAddNext ? (cval | SM_CM_ALL) :
1804                                   (cval & ~SM_CM_ALL);
1805                 fHit = True;
1806             }
1807         }
1808
1809         else if ((*pch == 'S') || (*pch == 's'))
1810         {
1811             if (_DtWmStringsAreEqual (pch, CM_SYSTEM_STR, len))
1812             {
1813                 cval = fAddNext ? (cval | SM_CM_SYSTEM) :
1814                                   (cval & ~SM_CM_SYSTEM);
1815                 fHit = True;
1816             }
1817         }
1818
1819         else if ((*pch == 'H') || (*pch == 'h'))
1820         {
1821             if (_DtWmStringsAreEqual (pch, CM_HANDSHAKE_STR, len))
1822             {
1823                 cval = fAddNext ? (cval | SM_CM_HANDSHAKE) :
1824                                   (cval & ~SM_CM_HANDSHAKE);
1825                 fHit = True;
1826             }
1827         }
1828
1829         else if ((*pch == 'N') || (*pch == 'n'))
1830         {
1831             if (_DtWmStringsAreEqual (pch, CM_NONE_STR, len))
1832             {
1833                 /* don't bother adding or subtracting nothing */
1834                 fHit = True;
1835             }
1836         }
1837
1838         pch = pchNext;
1839     }
1840
1841
1842
1843     /*
1844      * If we didn't match anything then set to default.
1845      */
1846     if (!fHit)
1847     {
1848         cval =  SM_CM_DEFAULT;
1849     }
1850
1851
1852     (*toVal).size = sizeof (long);
1853     (*toVal).addr = (caddr_t) &cval;
1854
1855
1856 } /* END OF FUNCTION SmCvtStringToContManagement */
1857
1858
1859 /*************************************<->*************************************
1860  *
1861  *  _DtNextToken (pchIn, pLen, ppchNext)
1862  *
1863  *
1864  *  Description:
1865  *  -----------
1866  *  XXDescription ...
1867  *
1868  *
1869  *  Inputs:
1870  *  ------
1871  *  pchIn = pointer to start of next token
1872  *
1873  * 
1874  *  Outputs:
1875  *  -------
1876  *  pLen  =    pointer to integer containing number of characters in next token
1877  *  ppchNext = address of pointer to following token
1878  *
1879  *  Return =   next token or NULL
1880  *
1881  *
1882  *  Comments:
1883  *  --------
1884  *  None.
1885  * 
1886  *************************************<->***********************************/
1887
1888 unsigned char *_DtNextToken (unsigned char *pchIn, int *pLen, 
1889         unsigned char **ppchNext)
1890 {
1891     unsigned char *pchR = pchIn;
1892     register int   i;
1893
1894 #ifdef MULTIBYTE
1895     register int   chlen;
1896
1897     for (i = 0; ((chlen = mblen ((char *)pchIn, MB_CUR_MAX)) > 0); i++)
1898     /* find end of word: requires singlebyte whitespace terminator */
1899     {
1900         if ((chlen == 1) && isspace (*pchIn))
1901         {
1902             break;
1903         }
1904         pchIn += chlen;
1905     }
1906
1907 #else
1908     for (i = 0; *pchIn && !isspace (*pchIn); i++, pchIn++)
1909     /* find end of word */
1910     {
1911     }
1912 #endif
1913
1914     /* skip to next word */
1915     ScanWhitespace (&pchIn);
1916
1917     *ppchNext = pchIn;
1918     *pLen = i;
1919     if (i)
1920     {
1921         return(pchR);
1922     }
1923     else
1924     {
1925        return(NULL);
1926     }
1927
1928 } /* END OF FUNCTION _DtNextToken */   
1929
1930
1931 \f
1932 /*************************************<->*************************************
1933  *
1934  *  _DtWmStringsAreEqual (pch1, pch2, len)
1935  *
1936  *
1937  *  Description:
1938  *  -----------
1939  *  XXDescription ...
1940  *
1941  *
1942  *  Inputs:
1943  *  ------
1944  *  pch1 =
1945  *  pch2 =
1946  *  len  =
1947  *
1948  * 
1949  *  Outputs:
1950  *  -------
1951  *  Return = (Boolean) True iff strings match (case insensitive)
1952  *
1953  *
1954  *  Comments:
1955  *  --------
1956  *  None.
1957  * 
1958  *************************************<->***********************************/
1959
1960 Boolean _DtWmStringsAreEqual (unsigned char *pch1, unsigned char *pch2, int len)
1961 {
1962 #ifdef MULTIBYTE
1963     int       chlen1;
1964     int       chlen2;
1965     wchar_t   wch1;
1966     wchar_t   wch2;
1967
1968     while (len  && 
1969            ((chlen1 = mbtowc (&wch1, (char *) pch1, 2)) > 0) &&
1970            ((chlen2 = mbtowc (&wch2, (char *) pch2, 2)) == chlen1) )
1971     {
1972         if (chlen1 == 1)
1973         /* singlebyte characters -- make case insensitive */
1974         {
1975             if ((isupper (*pch1) ? tolower(*pch1) : *pch1) !=
1976                 (isupper (*pch2) ? tolower(*pch2) : *pch2))
1977             {
1978                 break;
1979             }
1980         }
1981         else
1982         /* multibyte characters */
1983         {
1984             if (wch1 != wch2)
1985             {
1986                 break;
1987             }
1988         }
1989         pch1 += chlen1;
1990         pch2 += chlen2;
1991         len--;
1992     }
1993
1994 #else
1995     while (len  && *pch1 && *pch2 &&
1996            ((isupper (*pch1) ? tolower(*pch1) : *pch1) ==
1997             (isupper (*pch2) ? tolower(*pch2) : *pch2)))
1998     {
1999         *pch1++;
2000         *pch2++;
2001         len--;
2002     }
2003 #endif
2004
2005     return (len == 0);
2006
2007 } /* END OF _DtWmStringsAreEqual */   
2008
2009 /*************************************<->*************************************
2010  *
2011  *  InitializeGenericSession - set the smGD paths using the CDE 1.0
2012  *       session starting algorithm.
2013  *
2014  *  Description:
2015  *  -----------
2016  *  Initializes several variables in smGD
2017  *
2018  *  Inputs:
2019  *  ------
2020  *  tmpDisplay
2021  * 
2022  *  Outputs:
2023  *  -------
2024  *  Return = void
2025  *
2026  *  Comments:
2027  *  --------
2028  * 
2029  *************************************<->***********************************/
2030 static void
2031 InitializeGenericSession (
2032         Display         *tmpDisplay)
2033 {
2034     struct      stat buf;
2035     int         session_needed = 1;
2036     int         status;
2037     char        tmpPath[MAXPATHLEN];
2038
2039     smGD.savePath = _DtCreateDtDirs(tmpDisplay);
2040
2041     if (session_needed)
2042     {
2043       strcpy(smGD.clientPath, smGD.savePath);
2044       strcat(smGD.clientPath, "/");
2045       strcat(smGD.clientPath, SM_CURRENT_DIRECTORY);
2046       strcat(smGD.clientPath, "/");
2047       strcpy (tmpPath, smGD.clientPath);
2048       strcat(smGD.clientPath, SM_CLIENT_FILE2);
2049
2050       status = stat(smGD.clientPath, &buf);
2051
2052       if (status != 0) {
2053          strcpy (smGD.clientPath, tmpPath);
2054          strcat (smGD.clientPath, SM_CLIENT_FILE);
2055          status = stat(smGD.clientPath, &buf);
2056       }
2057
2058       if(status == 0)
2059       {
2060        /*
2061         * sessions/current/dt.settings exist, restore to 'current' session
2062         */
2063         strcpy(smGD.resourcePath, smGD.savePath);
2064         strcat(smGD.resourcePath, "/");
2065         strcat(smGD.resourcePath, SM_CURRENT_DIRECTORY);
2066         strcat(smGD.resourcePath, "/");
2067         strcat(smGD.resourcePath, SM_RESOURCE_FILE);
2068         strcpy(smGD.settingPath, smGD.savePath);
2069         strcat(smGD.settingPath, "/");
2070         strcat(smGD.settingPath, SM_CURRENT_DIRECTORY);
2071         strcat(smGD.settingPath, "/");
2072         strcat(smGD.settingPath, SM_SETTING_FILE);
2073         SetResSet();
2074         smGD.sessionType = CURRENT_SESSION;
2075         smGD.restoreSession = (char *) SM_CURRENT_DIRECTORY;
2076         session_needed = 0;
2077       }
2078     }
2079
2080     if (session_needed)
2081     {
2082       strcpy(smGD.clientPath, smGD.savePath);
2083       strcat(smGD.clientPath, "/");
2084       strcat(smGD.clientPath, SM_HOME_DIRECTORY);
2085       strcat(smGD.clientPath, "/");
2086       strcpy(tmpPath, smGD.clientPath);
2087       strcat(smGD.clientPath, SM_CLIENT_FILE2);
2088
2089       status = stat(smGD.clientPath, &buf);
2090
2091       if (status != 0) {
2092          strcpy (smGD.clientPath, tmpPath);
2093          strcat (smGD.clientPath, SM_CLIENT_FILE);
2094          status = stat(smGD.clientPath, &buf);
2095       }
2096
2097       if(status == 0)
2098       {
2099        /*
2100         * sessions/home/dt.settings exist, restore to 'home' session
2101         */
2102         strcpy(smGD.resourcePath, smGD.savePath);
2103         strcat(smGD.resourcePath, "/");
2104         strcat(smGD.resourcePath, SM_HOME_DIRECTORY);
2105         strcat(smGD.resourcePath, "/");
2106         strcat(smGD.resourcePath, SM_RESOURCE_FILE);
2107         strcpy(smGD.settingPath, smGD.savePath);
2108         strcat(smGD.settingPath, "/");
2109         strcat(smGD.settingPath, SM_HOME_DIRECTORY);
2110         strcat(smGD.settingPath, "/");
2111         strcat(smGD.settingPath, SM_SETTING_FILE);
2112         SetResSet();
2113         smGD.sessionType = HOME_SESSION;
2114         smGD.restoreSession = (char *) SM_HOME_DIRECTORY;
2115         session_needed = 0;
2116       }
2117     }
2118
2119     if (session_needed)
2120     {
2121       SetSysDefaults();
2122     }
2123 }
2124
2125 /*************************************<->*************************************
2126  *
2127  *  InternSessionDir - intern the session dir property and put it
2128  *     on the root window
2129  *
2130  *     NOTE: - also checks the validity of the -session command line
2131  *         option
2132  *
2133  *  Inputs:
2134  *  ------
2135  *  session_option - as given in the command line
2136  *  display
2137  * 
2138  *  Outputs:
2139  *  ------
2140  *  smGD.restoreSession - initialized
2141  *
2142  *  Return = void
2143  *
2144  *************************************<->***********************************/
2145 static Boolean
2146 InternSessionDir (
2147         char            *session_option,
2148         Display         *disp)
2149 {
2150         char            *pch;
2151
2152         if (!strcmp (session_option, SM_CURRENT_DIRECTORY)) {
2153                 pch = DtSM_SESSION_DIRECTORY;
2154                 smGD.restoreSession = SM_CURRENT_DIRECTORY;
2155         }
2156         else if (!strcmp (session_option, SM_HOME_DIRECTORY)) {
2157                 pch = DtSM_SESSION_DIRECTORY;
2158                 smGD.restoreSession = SM_HOME_DIRECTORY;
2159         }
2160         else if (!strcmp (session_option, SM_DISPLAY_HOME)) {
2161                 pch = DtSM_SESSION_DISPLAY_DIRECTORY;
2162                 smGD.restoreSession = SM_HOME_DIRECTORY;
2163         }
2164         else if (!strcmp (session_option, SM_DISPLAY_CURRENT)) {
2165                 pch = DtSM_SESSION_DISPLAY_DIRECTORY;
2166                 smGD.restoreSession = SM_CURRENT_DIRECTORY;
2167         }
2168         else
2169                 /*
2170                  * The session_option is not supported 
2171                  */
2172                 return (False);
2173
2174         XaSmRestoreDir = XInternAtom(disp, _XA_DT_RESTORE_DIR, False);
2175
2176         XChangeProperty(disp, RootWindow(disp, 0),
2177                 XaSmRestoreDir, XA_STRING, 8, PropModeReplace,
2178                 (unsigned char *)pch, strlen(pch));
2179
2180         XFlush(disp);
2181
2182
2183         return (True);
2184 }
2185
2186
2187 /*************************************<->*************************************
2188  *
2189  *  InitializeSpecificSession - set the smGD paths based on the session
2190  *       name given on the command line.
2191  *
2192  *  Description:
2193  *  -----------
2194  *  Initializes several variables in smGD
2195  *
2196  *  Inputs:
2197  *  ------
2198  *  session_option
2199  *  tmpDisplay
2200  * 
2201  *  Outputs:
2202  *  -------
2203  *  Return = void
2204  *
2205  *  Comments:
2206  *  --------
2207  * 
2208  *************************************<->***********************************/
2209 static Boolean
2210 InitializeSpecificSession (
2211         char            *session_option,
2212         Display         *disp,
2213         unsigned int    argc,
2214         char            **argv)
2215 {
2216         char            *session_dir = (char *) XtMalloc(MAXPATHLEN);
2217         char            *alt_dir = (char *) XtMalloc(MAXPATHLEN);
2218         int             len;
2219         struct stat     buf;
2220
2221         if (!InternSessionDir (session_option, disp))
2222                 return (False);
2223
2224         InitializePaths (smGD.restoreSession, disp);
2225
2226         if (!strcmp (session_option, SM_HOME_DIRECTORY)) {
2227                 /*
2228                  * Home session
2229                  */
2230                 if (smGD.clientPath[0] == '\0') {
2231                         if ((stat (smGD.savePath, &buf)) != 0) {
2232                                 if ((mkdir (smGD.savePath, 0000)) == 0)
2233                                         (void) chmod (smGD.savePath, 0755);
2234                                 else
2235                                         PrintErrnoError(DtError, 
2236                                                 smNLS.cantCreateDirsString);
2237                         }
2238                         SetSysDefaults ();
2239                 }
2240                 smGD.sessionType = HOME_SESSION;
2241                 smGD.restoreSession = SM_HOME_DIRECTORY;
2242         } 
2243         else if (!strcmp (session_option, SM_CURRENT_DIRECTORY)) {
2244                 /*
2245                  * Current session
2246                  */
2247                 if (smGD.clientPath[0] == '\0') {
2248                         /*
2249                          * Fallback to the generic home session
2250                          */
2251                         (void) sprintf (session_dir, "%s/%s",
2252                                         smGD.savePath, SM_CURRENT_DIRECTORY);
2253                         (void) sprintf (alt_dir, "%s/%s",
2254                                         smGD.savePath, SM_HOME_DIRECTORY);
2255
2256                         if (!SetAlternateSession (session_dir, alt_dir, True))
2257                                 SetSysDefaults ();
2258                 }
2259                 smGD.sessionType = CURRENT_SESSION;
2260                 smGD.restoreSession = SM_CURRENT_DIRECTORY;
2261         }
2262         else if (!strcmp (session_option, SM_DISPLAY_HOME)) {
2263                 /*
2264                  * Display-specific Home session
2265                  */
2266                 (void) sprintf (session_dir, "%s/%s",
2267                                 smGD.savePath, SM_HOME_DIRECTORY);
2268
2269                 if ((stat(session_dir, &buf)) != 0){
2270                         /*
2271                          * The session does not exist, give the user a
2272                          * change to exit.
2273                          */
2274                         if (!ConfirmSessionCreation (HOME_SESSION, argc, argv))
2275                                 SM_EXIT (0);
2276                                 
2277                 }
2278
2279                 if (smGD.clientPath[0] == '\0') {
2280                         /*
2281                          * Fallback to the generic home session
2282                          */
2283                         char            *home;
2284
2285                         if ((home = getenv ("HOME")) == 0)
2286                                 home = "";
2287
2288                         /* JET - VU#497553 */
2289                         len = strlen(home) + 
2290                           strlen(DtPERSONAL_CONFIG_DIRECTORY) +
2291                           strlen(DtSM_SESSION_DIRECTORY) +
2292                           strlen(SM_HOME_DIRECTORY);
2293
2294                         if (len > MAXPATHLEN)
2295                           alt_dir = XtRealloc(alt_dir, len + 1);
2296
2297                         (void) sprintf (alt_dir, "%s/%s/%s/%s",
2298                                         home,
2299                                         DtPERSONAL_CONFIG_DIRECTORY,
2300                                         DtSM_SESSION_DIRECTORY,
2301                                         SM_HOME_DIRECTORY);
2302                         if (!SetAlternateSession (session_dir, alt_dir, True))
2303                                 SetSysDefaults ();
2304                 }
2305                 smGD.sessionType = HOME_SESSION;
2306                 smGD.restoreSession = SM_HOME_DIRECTORY;
2307         }
2308         else if (!strcmp (session_option, SM_DISPLAY_CURRENT)) {
2309                 /*
2310                  * Display-specific Current session
2311                  */
2312                 (void) sprintf (session_dir, "%s/%s",
2313                                 smGD.savePath, SM_CURRENT_DIRECTORY);
2314
2315                 if ((stat(session_dir, &buf)) != 0){
2316                         /*
2317                          * The session does not exist, give the user a
2318                          * change to exit.
2319                          */
2320                         if (!ConfirmSessionCreation (CURRENT_SESSION, argc, argv))
2321                                 SM_EXIT (0);
2322                 }
2323
2324                 if (smGD.clientPath[0] == '\0') {
2325                         /*
2326                          * First, fallback to the display-specific home session
2327                          */
2328                         char            *home;
2329
2330                         (void) sprintf (alt_dir, "%s/%s",
2331                                         smGD.savePath, SM_HOME_DIRECTORY);
2332
2333                         if (!SetAlternateSession (session_dir, alt_dir, False)){
2334                                 /*
2335                                  * Try the generic home session
2336                                  */
2337                                 if ((home = getenv ("HOME")) == 0)
2338                                         home = "";
2339
2340                                 /* JET - VU#497553 */
2341                                 len = strlen(home) + 
2342                                   strlen(DtPERSONAL_CONFIG_DIRECTORY) +
2343                                   strlen(DtSM_SESSION_DIRECTORY) +
2344                                   strlen(SM_HOME_DIRECTORY);
2345
2346                                 if (len > MAXPATHLEN)
2347                                   alt_dir = XtRealloc(alt_dir, len + 1);
2348
2349                                 (void) sprintf (alt_dir, "%s/%s/%s/%s",
2350                                                 home,
2351                                                 DtPERSONAL_CONFIG_DIRECTORY,
2352                                                 DtSM_SESSION_DIRECTORY,
2353                                                 SM_HOME_DIRECTORY);
2354
2355                                 if (!SetAlternateSession (session_dir, 
2356                                                           alt_dir, 
2357                                                           True))
2358                                         SetSysDefaults ();
2359                         }
2360                 }
2361                 smGD.sessionType = CURRENT_SESSION;
2362                 smGD.restoreSession = SM_CURRENT_DIRECTORY;
2363         }
2364         else {
2365                 if (session_dir) XtFree(session_dir);
2366                 if (alt_dir) XtFree(alt_dir);
2367                 return (False);
2368         }
2369         
2370         if (session_dir) XtFree(session_dir);
2371         if (alt_dir) XtFree(alt_dir);
2372         return (True);
2373 }
2374
2375
2376 /*************************************<->*************************************
2377  *
2378  *  InitializePaths 
2379  *
2380  *  Description:
2381  *  -----------
2382  *  Initializes the following variables:
2383  *
2384  *     smGD.savePath
2385  *     smGD.settingsPath
2386  *     smGD.resourcePath
2387  *     smGD.clientPath - [0] = '\0' if the database files do not exist
2388  *
2389  *  Inputs:
2390  *  ------
2391  *  session_name = "current" or "home"
2392  * 
2393  *  Outputs:
2394  *  -------
2395  *  Return = void
2396  *
2397  *  Comments:
2398  *  --------
2399  * 
2400  *************************************<->***********************************/
2401 static void
2402 InitializePaths (
2403         char            * session_name,
2404         Display         * disp)
2405 {
2406         char            *db_file = (char *) XtMalloc(MAXPATHLEN);
2407         struct stat     buf;
2408
2409         smGD.savePath = _DtCreateDtDirs(disp);
2410
2411         (void) sprintf (smGD.settingPath, "%s/%s/%s", 
2412                         smGD.savePath, session_name, SM_SETTING_FILE);
2413
2414         (void) sprintf (smGD.resourcePath, "%s/%s/%s",
2415                         smGD.savePath, session_name, SM_RESOURCE_FILE);
2416
2417
2418         smGD.clientPath[0] = '\0';
2419
2420         (void) sprintf (db_file, "%s/%s/%s", 
2421                         smGD.savePath, session_name, SM_CLIENT_FILE2);
2422
2423         if ((stat(db_file, &buf)) == 0)
2424                 (void) strcpy (smGD.clientPath, db_file);
2425         else {
2426                 (void) sprintf (db_file, "%s/%s/%s", 
2427                                 smGD.savePath, session_name, SM_CLIENT_FILE);
2428                 if ((stat(db_file, &buf)) == 0)
2429                         (void) strcpy (smGD.clientPath, db_file);
2430         }
2431         if (db_file) XtFree(db_file);
2432 }
2433
2434
2435 /*************************************<->*************************************
2436  *
2437  *  SetAlternateSession
2438  *
2439  *  Assumptions:
2440  *
2441  *     Neither of the client databases in the session_dir directory
2442  *     exist.
2443  *
2444  *  Inputs:
2445  *  ------
2446  *  session_dir - the directory path for the session including home
2447  *     or current
2448  *  alt_dir - the directory to use in the search for an alternate
2449  *     or fallback session database
2450  *  make_dir - if True, a session_dir will be created if it does not
2451  *     exits; if False, session_dir will not be created
2452  * 
2453  *  Outputs:
2454  *  -------
2455  *  Return = Boolean
2456  *
2457  *************************************<->***********************************/
2458 static Boolean
2459 SetAlternateSession (
2460         char            * session_dir,
2461         char            * alt_dir,
2462         Boolean         make_dir)
2463 {
2464         char            *tmp_dir = NULL;
2465         char            *db_file1 = (char *) XtMalloc(MAXPATHLEN);
2466         char            *db_file2 = (char *) XtMalloc(MAXPATHLEN);
2467         struct stat     buf;
2468
2469         if ((stat (session_dir, &buf)) != 0) {
2470                 /*
2471                  * The requested dir does not exist, create it
2472                  * by either copying the session from alt_dir (if
2473                  * it exists and has a client database) or by
2474                  * calling mkdir.
2475                  */
2476                 
2477                 (void) sprintf (db_file1, "%s/%s", 
2478                                 alt_dir, SM_CLIENT_FILE2);
2479                 (void) sprintf (db_file2, "%s/%s", 
2480                                 alt_dir, SM_CLIENT_FILE);
2481
2482                 if ((stat(db_file1, &buf)) == 0)
2483                         tmp_dir = db_file1;
2484                 else if ((stat(db_file2, &buf)) == 0)
2485                         tmp_dir = db_file2;
2486
2487                 if (!tmp_dir && !make_dir) {
2488                         if (db_file1) XtFree(db_file1);
2489                         if (db_file2) XtFree(db_file2);
2490                         /*
2491                          * This alt_dir doesn't have a session database
2492                          * return now and try another directory
2493                          */
2494                         return (False);
2495                 }
2496
2497                 if (tmp_dir) {
2498                         /*
2499                          * The alt_dir has a session database, create
2500                          * a copy of its entire directory because all
2501                          * of the sessions state is needed.
2502                          */
2503                         char            *tmp;
2504                         
2505                         tmp = XtMalloc (strlen (alt_dir) + 
2506                                         strlen (session_dir) + 10);
2507                         if (!tmp)
2508                                 return (False);
2509
2510                         (void) sprintf (tmp, "cp -r %s %s",
2511                                         alt_dir, session_dir);
2512
2513                         if ((system (tmp)) == -1)
2514                                 return (False);
2515                         XtFree (tmp);
2516
2517                         if ((stat(session_dir, &buf)) != 0)
2518                                 /*
2519                                  * It should have been created by the cp
2520                                  */
2521                                 return (False);
2522
2523                         /*
2524                          * The session database needs to be updated.
2525                          */
2526                         if (tmp_dir == db_file1)
2527                                 sprintf (smGD.clientPath, "%s/%s",
2528                                         session_dir, SM_CLIENT_FILE2);
2529                         else
2530                                 sprintf (smGD.clientPath, "%s/%s",
2531                                         session_dir, SM_CLIENT_FILE);
2532                 } else {
2533                         /*
2534                          * The alt_dir did not have a session database.
2535                          * Create a directory and load the system defaults
2536                          */
2537                         if ((mkdir (session_dir, 0000)) == 0)
2538                                 (void) chmod (session_dir, 0755);
2539                         else {
2540                                 PrintErrnoError(DtError, 
2541                                         smNLS.cantCreateDirsString);
2542                                 return (False);
2543                         }
2544                         SetSysDefaults ();
2545                 }
2546         } else {
2547                 /*
2548                  * The directory for the specified session exists
2549                  * but it doesn't have any client databases.  Start
2550                  * a new user session.  If a user wants a sesssion
2551                  * with no apps, they should create a zero-length
2552                  * session database.
2553                  */
2554                 SetSysDefaults ();
2555         }
2556
2557         if (db_file1) XtFree(db_file1);
2558         if (db_file2) XtFree(db_file2);
2559         return (True);
2560 }
2561
2562
2563 void 
2564 SmExit (
2565         int             exitStatus)
2566 {
2567         if (smXSMP.saveState.saveComplete && 
2568             smXSMP.saveState.shutdown &&
2569             !smXSMP.saveState.shutdownCanceled)
2570                 XSMPExit ();
2571
2572         exit (exitStatus);
2573 }
2574
2575 void
2576 SetSIGPIPEToDefault ()
2577 {
2578         struct sigaction pipeSig;
2579
2580         sigemptyset(&pipeSig.sa_mask);
2581         pipeSig.sa_flags = 0;
2582         pipeSig.sa_handler = SIG_DFL;
2583         (void) sigaction(SIGPIPE, &pipeSig, (struct sigaction *) NULL);
2584 }