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