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