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