/*
 * CDE - Common Desktop Environment
 *
 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
 *
 * These libraries and programs are free software; you can
 * redistribute them and/or modify them under the terms of the GNU
 * Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * These libraries and programs are distributed in the hope that
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with these libraries and programs; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301 USA
 */
/* $TOG: SmGlobals.c /main/37 1998/10/26 17:21:18 mgreess $ */
/*
 * (c) Copyright 1995 Digital Equipment Corporation.
 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
 * (c) Copyright 1993, 1994, 1995 Novell, Inc. 
 * (c) Copyright 1995 FUJITSU LIMITED.
 * (c) Copyright 1995 Hitachi.
 */
/*************************************<+>*************************************
 *****************************************************************************
 **
 **  File:        SmGlobals.c
 **
 **  Project:     HP DT Session Manager (dtsession)
 **
 **  Description:
 **  -----------
 **  This file contains all routines in charge of managing all global
 **  variables used by the session manager.  These variables include
 **  mostly state and setting information.
 **
 **
 **
 *******************************************************************
 **  (c) Copyright Hewlett-Packard Company, 1990.  All rights are  
 **  reserved.  Copying or other reproduction of this program      
 **  except for archival purposes is prohibited without prior      
 **  written consent of Hewlett-Packard Company.                     
 ********************************************************************
 **
 **
 **
 *****************************************************************************
 *************************************<+>*************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
#include <Dt/DtP.h>
#include <Dt/SessionP.h>
#include <Dt/Wsm.h>
#include <Dt/WsmP.h>
#include <Dt/UserMsg.h>
#include <Dt/HourGlass.h>
#include <Dt/SessionM.h>
#include <Dt/EnvControlP.h>
#include <Dt/Qualify.h>
#include <Dt/MsgLog.h>
#include "Sm.h"
#include "SmResource.h"
#include "SmError.h"
#include "SmUI.h"
#include "SmGlobals.h"
#include "SmLock.h"
#include "SmRestore.h"
#include "SmProtocol.h"
#include "SmXSMP.h"

/*
 * Internal Variable Declaraions
 */
static char savedDir    [MAXPATHLEN];
static char savedOldDir [MAXPATHLEN];
static char savedTmpDir [MAXPATHLEN];

/*
 * Internal Function Declaraions
 */

static int SetSysDefaults( void ) ;
static int SetResSet( void ) ;
static void RemoveFiles( char *) ;
static void TrimErrorlog(void);

static void _SmWaitClientTimeoutDefault (
	Widget widget, 
       int offset, 
       XrmValue *value);

static void _SmWaitWmTimeoutDefault (
	Widget widget, 
	int offset, 
	XrmValue *value);

void SmCvtStringToContManagement (
	XrmValue *args, 
	Cardinal numArgs,
	XrmValue *fromVal, 
	XrmValue *toVal);

unsigned char *_DtNextToken (
	unsigned char *pchIn, 
	int *pLen, 
	unsigned char **ppchNext);

Boolean _DtWmStringsAreEqual (
	unsigned char *pch1, 
	unsigned char *pch2, 
	int len);

static Boolean InitializeSpecificSession (
	char		*session_name,
	Display		*disp,
	unsigned int	argc,
	char		**argv);

static void InitializeGenericSession (
	Display		*disp);

static void InitializePaths (
	char		*session_option,
	Display		*disp);

static Boolean SetAlternateSession (
	char		* session_dir,
	char		* alt_dir,
	Boolean		make_dir);

/*
 * Global Data
 */

/*
 * These are the global structures used throughout dtsession
 * They are defined in Sm.h
 */
SessionResources     smRes;
SaverResources       smSaverRes;
SettingsSet           smToSet;
SettingsCust     smCust;
SessionSettings      smSettings;
GeneralData          smGD;
char SM_SCREEN_SAVER_LOC [MAXPATHLEN + 1];

/*
 * Internal Global Data
 */
static char     tmpDisplayName[MAXPATHLEN + 1];
int machineType = 0;

static XtResource sessionResources[]=
{
   {SmNwmStartup, SmCwmStartup, XtRString, sizeof(String),
        XtOffset(SessionResourcesPtr, wmStartup),
        XtRImmediate, (XtPointer) NULL},
   {SmNquerySettings, SmCquerySettings, XtRBoolean, sizeof(Boolean),
        XtOffset(SessionResourcesPtr, querySettings),
        XtRImmediate, (XtPointer) False},
   {SmNkeys, SmCkeys, XtRString, sizeof(String),
        XtOffset(SessionResourcesPtr, keyholders), XtRString, NULL},
   {SmNalarmTime, SmCalarmTime, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, alarmTime), 
        XtRImmediate, (XtPointer) 10},
   {SmNmemThreshold, SmCmemThreshold, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, memThreshold), 
        XtRImmediate, (XtPointer) 100},
   {SmNsessionVersion, SmCsessionVersion, XtRString, sizeof(String),
        XtOffset(SessionResourcesPtr, sessionVersion),
        XtRImmediate, (XtPointer) NULL},
   {SmNdisplayResolution, SmCdisplayResolution, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, displayResolution),
        XtRImmediate, (XtPointer) 0},
   {SmNsessionLang, SmCsessionLang, XtRString, sizeof(String),
        XtOffset(SessionResourcesPtr, sessionLang),
        XtRImmediate, (XtPointer) ""},
   {SmNcontManagement, SmCContManagement, SmRContManagement, sizeof(long),
        XtOffset(SessionResourcesPtr, contManagement),
        XtRImmediate, (XtPointer) (SM_CM_DEFAULT)},
   {SmNwaitClientTimeout, SmCWaitClientTimeout, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, waitClientTimeout),
        XtRCallProc, (XtPointer)_SmWaitClientTimeoutDefault },
   {SmNwaitWmTimeout, SmCWaitWmTimeout, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, waitWmTimeout),
        XtRCallProc, (XtPointer)_SmWaitWmTimeoutDefault },
   {SmNuseMessaging, SmCUseMessaging, XtRBoolean, sizeof(Boolean),
        XtOffset(SessionResourcesPtr, useBMS),
        XtRImmediate, (XtPointer) True},
   {SmNsaveFontPath, SmCsaveFontPath, XtRBoolean, sizeof(Boolean),
        XtOffset(SessionResourcesPtr, saveFontPath),
        XtRImmediate, (XtPointer) False},
   {SmNsaveYourselfTimeout, SmCsaveYourselfTimeout, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, saveYourselfTimeout),
        XtRImmediate, (XtPointer) 5},
   {SmNnumSessionsBackedup, SmCnumSessionsBackedup, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, numSessionsBackedup),
        XtRImmediate, (XtPointer) DEFAULT_NUM_SESSIONS_BACKED_UP},
   {SmNignoreEnvironment, SmCignoreEnvironment, XtRString, sizeof(String),
        XtOffset(SessionResourcesPtr, ignoreEnvironment),
        XtRImmediate, (XtPointer) NULL},
#if defined(USE_XINERAMA)	/* JET - Xinerama */
   {SmNxineramaPreferredScreen, SmCxineramaPreferredScreen, XtRInt, sizeof(int),
        XtOffset(SessionResourcesPtr, xineramaPreferredScreen),
        XtRImmediate, (XtPointer) 0},
#endif

}
;


static XtResource saverResources[]=
{
   {SmNcycleTimeout, SmCcycleTimeout, XtRInt, sizeof(int),
        XtOffset(SaverResourcesPtr, cycleTimeout),
        XtRImmediate, (XtPointer) -1},
   {SmNlockTimeout, SmClockTimeout, XtRInt, sizeof(int),
        XtOffset(SaverResourcesPtr, lockTimeout),
        XtRImmediate, (XtPointer) -1},
   {SmNsaverTimeout, SmCsaverTimeout, XtRInt, sizeof(int),
        XtOffset(SaverResourcesPtr, saverTimeout),
        XtRImmediate, (XtPointer) -1},
   {SmNrandom, SmCrandom, XtRBoolean, sizeof(Boolean),
        XtOffset(SaverResourcesPtr, random),
        XtRImmediate, (XtPointer) False},
   {SmNsaverList, SmCsaverList, XtRString, sizeof(String),
        XtOffset(SaverResourcesPtr, saverList),
        XtRImmediate, (XtPointer) ""},

}
;



/*
 * Machine specific defaults.
 */
 static struct 
 {
   int machineType;
   int clientTimeout;
   int wmTimeout;
 }
 machineDefault[] =
 {
   {  0,  20,  60},               /* Machine independent default */
 };
 #define MACHINEDEFAULTS (sizeof(machineDefault) / sizeof(machineDefault[0]))


/*************************************<->*************************************
 *
 *  _SmWaitClientTimeoutDefault (widget, offset, value)
 *
 *
 *  Description:
 *  -----------
 *  This function generates a default value for the waitClientTimeout resource.
 *  We dynamically default to 10 seconds for s400/s300 and to
 *  5 seconds for s700/s800.
 *
 *  Inputs:
 *  ------
 *  widget = this is not used
 *
 *  offset = this is the resource offset
 *
 *  value = this is a pointer to a XrmValue in which to store the result
 *
 *  Outputs:
 *  -------
 *  value = default resource value and size
 *
 *************************************<->***********************************/
static
void
_SmWaitClientTimeoutDefault (Widget widget, int offset, XrmValue *value)
{
    int i;

    for (i = 0; i < MACHINEDEFAULTS; i++)
    {
      if (machineDefault[i].machineType == machineType)
      {
        break;
      }
    }

    if (i == MACHINEDEFAULTS)
    {
      i = 0;
    }

    value->addr = (char *)&machineDefault[i].clientTimeout;
    value->size = sizeof (int);

} /* END OF FUNCTION _SmWaitClientTimeoutDefault */



/*************************************<->*************************************
 *
 *  _SmWaitWmTimeoutDefault (widget, offset, value)
 *
 *
 *  Description:
 *  -----------
 *  This function generates a default value for the waitWmTimeout resource.
 *  We dynamically default to 60 seconds for s400/s300 and to
 *  60 seconds for s700/s800.  This could change if we get feedback indicating
 *  the need for a new default.
 *
 *  Inputs:
 *  ------
 *  widget = this is not used
 *
 *  offset = this is the resource offset
 *
 *  value = this is a pointer to a XrmValue in which to store the result
 *
 *  Outputs:
 *  -------
 *  value = default resource value and size
 *
 *************************************<->***********************************/
static
void
_SmWaitWmTimeoutDefault (Widget widget, int offset, XrmValue *value)
{
    int i;
    
    smGD.userSetWaitWmTimeout = False; /* if we are here, it is not user set */

    for (i = 0; i < MACHINEDEFAULTS; i++)
    {
      if (machineDefault[i].machineType == machineType)
      {
        break;
      }
    }

    if (i == MACHINEDEFAULTS)
    {
      i = 0;
    }

    value->addr = (char *)&machineDefault[i].wmTimeout;
    value->size = sizeof (int);

} /* END OF FUNCTION _SmWaitWmTimeoutDefault */



/*************************************<->*************************************
 *
 *  InitSMGlobals ()
 *
 *
 *  Description:
 *  -----------
 *  Sets SM global resources and global settings to a starting value.
 *
 *
 *  Inputs:
 *  ------
 *  buttonForm = form widget for button that allows cursor to get colors
 *  smRes(global) = structure that holds session resources.
 *  smToSet(global) = structure that holds "which settings to set and how" info
 *  smGD(global) = structure that holds general data info
 * 
 *  Outputs:
 *  -------
 *  smRes(global) = structure that holds session resources.
 *  smToSet(global) = structure that holds "which settings to set and how" info
 *  smGD(global) = structure that holds general data info
 *
 *  Comments:
 *  --------
 *  Resources are set to an initial value by the resource manager.  The
 *  rest are set in the routine.
 * 
 *************************************<->***********************************/
void 
InitSMGlobals( void )
{
    int i;
    PropDtSmWindowInfo property;
    struct utsname nameRec;
    char *firstSlash;
    char *keyNum;

    smGD.userSetWaitWmTimeout = True; /* assume it is */

    /*
     * Get application specific resource values
     */
    XtAppAddConverter (smGD.appCon, XtRString, SmRContManagement,
                       (XtConverter)SmCvtStringToContManagement, NULL, 0);
    XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smRes,
                              sessionResources,
                              XtNumber(sessionResources), NULL, 0);

    if (smGD.lockOnTimeoutStatus == True)
    {
     /*
      * Pull screen saver resources from Dtsession*extension.<name>.
      */
      smGD.SmNextension = "extension";
      smGD.SmCextension = "Extension";
      smGD.extensionSpec = "extension.";
    }
    else
    {
     /*
      * Pull screen saver resources from Dtsession*<name>.
      */
      smGD.SmNextension = smGD.SmCextension = smGD.extensionSpec = "";
    }

    XtGetSubresources(smGD.topLevelWid, (XtPointer) &smSaverRes,
                      smGD.SmNextension, smGD.SmCextension,
                      saverResources,
                      XtNumber(saverResources), NULL, 0);

    smGD.wmStartup = SmNewString(smRes.wmStartup);
    smGD.keyholders = SmNewString(smRes.keyholders);
    smGD.sessionLang = SmNewString(smRes.sessionLang);
    smGD.saverList = SmNewString(smSaverRes.saverList);

    /*
     * Initialize general data used by apps not initialized by
     * XtInitialize or DtInitialize
     */
    smGD.topLevelWindow = XtWindow(smGD.topLevelWid);
    smGD.numSavedScreens = (ScreenCount(smGD.display) > MAX_SCREENS_SAVED)
         ? MAX_SCREENS_SAVED : ScreenCount(smGD.display);
    smGD.dtwmRunning = False;
    smSettings.confirmMode = DtSM_VERBOSE_MODE;
    if (smGD.sessionType == CURRENT_SESSION ||
	smGD.sessionType == DEFAULT_SESSION)
        smSettings.startState = DtSM_CURRENT_STATE;
    else
        smSettings.startState = DtSM_HOME_STATE;
    smGD.homeSave = False;
    smGD.saverListParse = NULL;

    smGD.loggingOut = False;

    /*
     * Sanity check on timeouts for negative numbers
     */
    if (smRes.waitClientTimeout < 0)
    {
        smRes.waitClientTimeout = -smRes.waitClientTimeout;
    }
    if (smRes.waitWmTimeout < 0)
    {
        smRes.waitWmTimeout = -smRes.waitWmTimeout;
    }
    if (smRes.saveYourselfTimeout < 0)
    {
        smRes.saveYourselfTimeout = -smRes.saveYourselfTimeout;
    }


    /*
     * Now convert users view of seconds in to XtAppAddTimout's
     * need for milliseconds.
     */
    smRes.waitClientTimeout = 1000 * smRes.waitClientTimeout;
    smRes.waitWmTimeout = 1000 * smRes.waitWmTimeout;
    smRes.saveYourselfTimeout = 1000 * smRes.saveYourselfTimeout;
    smGD.savedWaitWmTimeout = smRes.waitWmTimeout;

    /*
     * Initialize lock data
     */
    smGD.screen = XDefaultScreen(smGD.display);
    smGD.blackPixel = XBlackPixel(smGD.display, smGD.screen);
    smGD.whitePixel = XWhitePixel(smGD.display, smGD.screen);
    smDD.lockDialog = NULL;
    smDD.lockCoverDialog = NULL;
    for(i = 0;i < smGD.numSavedScreens;i++)
    {
        smDD.coverDialog[i] = NULL;
        smDD.coverDrawing[i] = NULL;
    }
    smGD.lockedState = UNLOCKED;

   /*
    * Sanity check screen saver resource values.
    */ 
    if (smRes.alarmTime < 0) smRes.alarmTime = 0;

    #define SMBOUND(A) (A < 0 ? 0 : A)

    smSaverRes.lockTimeout = SMBOUND(smSaverRes.lockTimeout) * 60;
    smSaverRes.saverTimeout = SMBOUND(smSaverRes.saverTimeout) * 60;
    smSaverRes.cycleTimeout = SMBOUND(smSaverRes.cycleTimeout) * 60;

    CreateLockCursor();
    smGD.waitCursor = _DtGetHourGlassCursor(smGD.display);

    /*
     * Initialize other global data related to dialogs
     */
    smDD.confExit = NULL;
    smDD.qExit = NULL;
    smDD.compatExit = NULL;
    smDD.deadWid = NULL;
    smDD.saveSession = NULL;         	/* Error dialog for Save_Session */

    if (!smDD.smHelpDialog)
	/*
	 * Don't wipe it out if it is already created
	 */
        smDD.smHelpDialog = NULL;

    /*
     * Intern all the atoms needed for the WSM communication
     */
    {
      enum { XA_DT_SM_WINDOW_INFO, XA_DT_SM_WM_PROTOCOL,
	     XA_DT_SM_START_ACK_WINDOWS, XA_DT_SM_STOP_ACK_WINDOWS,
	     XA_DT_WM_WINDOW_ACK, XA_DT_WM_EXIT_SESSION,
	     XA_DT_WM_LOCK_DISPLAY, XA_DT_WM_READY, NUM_ATOMS };
      static char *atom_names[] = {
	     _XA_DT_SM_WINDOW_INFO, _XA_DT_SM_WM_PROTOCOL,
	     _XA_DT_SM_START_ACK_WINDOWS, _XA_DT_SM_STOP_ACK_WINDOWS,
	     _XA_DT_WM_WINDOW_ACK, _XA_DT_WM_EXIT_SESSION,
	     _XA_DT_WM_LOCK_DISPLAY, _XA_DT_WM_READY };

      Atom atoms[XtNumber(atom_names)];

      XInternAtoms(smGD.display, atom_names, XtNumber(atom_names),
		   False, atoms);

      XaVsmInfo = atoms[XA_DT_SM_WINDOW_INFO];
      XaSmWmProtocol = atoms[XA_DT_SM_WM_PROTOCOL];
      XaSmStartAckWindow = atoms[XA_DT_SM_START_ACK_WINDOWS];
      XaSmStopAckWindow = atoms[XA_DT_SM_STOP_ACK_WINDOWS];
      XaWmWindowAck = atoms[XA_DT_WM_WINDOW_ACK];
      XaWmExitSession = atoms[XA_DT_WM_EXIT_SESSION];
      XaWmLockDisplay = atoms[XA_DT_WM_LOCK_DISPLAY];
      XaWmReady = atoms[XA_DT_WM_READY];
    }

    /*
     * Set the session manager window property on the root window
     */
    property.flags = 0;
    property.smWindow = (unsigned long) smGD.topLevelWindow;
    XChangeProperty (smGD.display, RootWindow(smGD.display, 0),
                     XaVsmInfo, XaVsmInfo,
                     32, PropModeReplace, (unsigned char *)&property,
                     PROP_DT_SM_WINDOW_INFO_ELEMENTS);

    /*
     * Set up the signal handler for forking and execing
     */
    sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
}



/*************************************<->*************************************
 *
 *  SetRestorePath ()
 *
 *
 *  Description:
 *  -----------
 *  Sets SM global resources and global settings to a starting value.
 *
 *
 *  Inputs:
 *  ------
 *  smGD.display = display structure for session manager.  Used to construct
 *                     a display directory
 * 
 *  Outputs:
 *  -------
 *  smGD.resourcePath(global) = Path where the resources to be restored are
 *                              held
 *  smGD.settingPath(global) = Path where the settings to be restored are
 *                              held
 *  smGD.clientPath(global) = Path where the clients to be restored are
 *                              held
 *  smGD.savePath(global) = Path where all save files are to be saved
 *
 *  Return:
 *  ------
 *  Display connection
 *
 *  Comments:
 *  --------
 *  WARNING:  This routine also determines whether dtsession is being started
 *            in compatibility mode.  If so - no restore paths are set up and
 *            the routine is exited.
 * 
 *************************************<->***********************************/
int
SetRestorePath(
        unsigned int argc,
        char *argv[] )
{
    Display  *tmpDisplay;
    int 	i;
    char        *displayName = NULL;
    char	*session_option = NULL;

    smGD.compatMode = False;

    for(i = 0;i < argc;i++)
    {
        if(!strcmp(argv[i], "-display"))
        {
            displayName = argv[i + 1];
            /* 
             * If -display is used but DISPLAY is not set,
             * put DISPLAY into the environment
             */
            if (getenv("DISPLAY") == 0)
            {
                snprintf(tmpDisplayName, MAXPATHLEN, "DISPLAY=%s", displayName);
                putenv(tmpDisplayName);
            }
        }

        if(!strcmp(argv[i], "-norestore"))
        {
            smGD.compatMode = True;
        }

        if(!strcmp(argv[i], "-session"))
        {
	    i++;
	    if (i >= argc) 
	    {
		char		*pch;

		pch = strdup ((char *) GETMESSAGE (40, 15,
			" No session name was provided for the -session command line option."));
	      	if (pch) 
		{ 
		    DtMsgLogMessage (argv[0], DtMsgLogWarning, pch);
		    free (pch);
		}
	        break;
	    }
            session_option = argv[i];
        }
    }

    /*
     *  If we are in compatibility mode - no restore paths are set
     *  up and we just return
     */
    if(smGD.compatMode == True)
    {
	smGD.clientPath[0] = 0;
	smGD.resourcePath[0] = 0;
	smGD.settingPath[0] = 0;
	smGD.sessionType = DEFAULT_SESSION;
	smGD.restoreSession = NULL;
        return(0);
    }

    tmpDisplay = XOpenDisplay(displayName);
    if(tmpDisplay == NULL)
    {
        PrintError(DtError, GETMESSAGE(4, 1, "Invalid display name - exiting."));
        SM_EXIT(-1);
    }

    if (session_option) 
    {
        if (!InitializeSpecificSession (session_option, tmpDisplay, argc, argv))
        	InitializeGenericSession (tmpDisplay);
    }
    else 
        InitializeGenericSession (tmpDisplay);

    /*
     * Need to know if the session is for a specific display
     */
    smGD.displaySpecific = True;
    if (session_option = strrchr (smGD.savePath, '/')) 
    {
	session_option++;
	if (!strcmp (session_option, DtSM_SESSION_DIRECTORY))
            smGD.displaySpecific = False;
    }

    TrimErrorlog();
    XCloseDisplay(tmpDisplay);

    /* 
    ** User's session startup script:
    **   $HOME/.dt/sessions/sessionetc
    */
    strcpy(smGD.etcPath, smGD.savePath);
    strcat(smGD.etcPath, "/");
    strcat(smGD.etcPath, smEtcFile);

    /* 
    ** User's session shutdown script: 
    **   $HOME/.dt/sessions/sessionexit
    */
    strcpy(smGD.exitPath, smGD.savePath);
    strcat(smGD.exitPath, "/");
    strcat(smGD.exitPath, smExitFile);

    return(0);
}

void
FixPath
    (
    char * the1stPath
    )
{
    char * tempPath;
    char * pathList = (char *)XtMalloc(strlen(SM_SYSTEM_PATH) +
			 strlen(":" CDE_INSTALLATION_TOP "/config") + 1);

    strcpy(pathList,SM_SYSTEM_PATH);
    strcat(pathList,":" CDE_INSTALLATION_TOP "/config");

    tempPath = _DtQualifyWithFirst(the1stPath,pathList);
    if (tempPath != NULL) {
        strcpy(the1stPath,tempPath);
        free(tempPath);
    }

    XtFree(pathList);
}


/*************************************<->*************************************
 *
 *  SetSysDefaults ()
 *
 *
 *  Description:
 *  -----------
 *  Sets the path to restore the system default files. A convenience routine
 *
 *
 *  Inputs:
 *  ------
 *  smGD.savePath = path that files are to be saved in (set up in
 *                      SetRestorePaths)
 * 
 *  Outputs:
 *  -------
 *  smGD.resourcePath(global) = Path where the resources to be saved are
 *                              to be saved.
 *  smGD.settingPath(global) = Path where the settings to be saved are
 *                              to be saved.
 *  smGD.clientPath(global) = Path where the clients to be saved are
 *                              to be saved.
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static int 
SetSysDefaults( void )
{
    int status;
    struct stat buf;
    String tmpString;
    char        *langSpec;
    char        *tempPath;

    /*
     * No files exist for restoration - use the
     * system defaults
     */
    strcpy(smGD.resourcePath, "");
    strcpy(smGD.clientPath, "");
    smGD.settingPath[0] = 0;
    smGD.sessionType = DEFAULT_SESSION;
    smGD.restoreSession = (char *) SM_SYSTEM_DIRECTORY;

    langSpec = getenv("LANG");
    if ((langSpec != NULL) && (*langSpec != 0))
    {
        strcat(smGD.clientPath, "/");
        strncat(smGD.clientPath, langSpec, MAXPATHLEN-2);
        smGD.clientPath[MAXPATHLEN-1] = 0;
    }
    
    strcat(smGD.clientPath, "/");
    strcat(smGD.clientPath, SM_SYSTEM_CLIENT_FILE);
   
    FixPath(smGD.clientPath);

    /*
     * If the system files don't exist - we're in
     * trouble - First try LANG location then default
     */
    status = stat(smGD.clientPath, &buf);
    if(status == -1)
    {
        if((langSpec == NULL) || (*langSpec == 0))
        {
            PrintErrnoError(DtError, GETMESSAGE(4, 2,
                        "No defaults files exist.  "
                        "No applications will be restarted."));
            smGD.clientPath[0] = 0;
            smGD.resourcePath[0] = 0;
        }
        else
        {
            strcpy(smGD.clientPath, "/C/");
            strcat(smGD.clientPath, SM_SYSTEM_CLIENT_FILE);

	    FixPath(smGD.clientPath);

            status = stat(smGD.clientPath, &buf);
            if(status == -1)
            {
                PrintErrnoError(DtError, GETMESSAGE(4, 3,
                            "No defaults files exist.  "
                            "No applications will be restarted."));
                smGD.clientPath[0] = 0;
                smGD.resourcePath[0] = 0;
            }
        }
    }
    
    return(0);
}



/*************************************<->*************************************
 *
 *  SetResSet ()
 *
 *
 *  Description:
 *  -----------
 *  Sets the path to restore the settings and resource files.
 *  A convenience routine
 *
 *
 *  Inputs:
 *  ------
 *  smGD.savePath = path that files are to be saved in (set up in
 *                      SetRestorePaths)
 * 
 *  Outputs:
 *  -------
 *  smGD.resourcePath(global) = Path where the resources to be saved are
 *                              to be saved.
 *  smGD.settingPath(global) = Path where the settings to be saved are
 *                              to be saved.
 *  smGD.clientPath(global) = Path where the clients to be saved are
 *                              to be saved.
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static int 
SetResSet( void )
{
    int status;
    struct stat buf;
    
    /*
     * If resource or settings file does not exist - just null out
     * the path so these things will not get restored
     */
    status = stat(smGD.resourcePath, &buf);
    if(status == -1)
    {
        smGD.resourcePath[0] = 0;
    }

    status = stat(smGD.settingPath, &buf);
    if(status == -1)
    {
        smGD.settingPath[0] = 0;
    }
    return(0);
}


/*************************************<->*************************************
 *
 *  UndoSetSavePath () - Undoes the directory manipulations done by 
 *  	SetSavePath.  This function is only called if a shutdown/save
 *	is canceled.
 *
 *************************************<->***********************************/
void 
UndoSetSavePath (void)
{
	char			* buf;

	if (strcmp ("", savedDir)) {

		/*
		 * Remove the directory where the save occurred, e.g.:
		 *
		 *    ~/.dt/<session_dir>/current
		 *    ~/.dt/<session_dir>/home
		 */
		buf = XtMalloc (strlen (savedDir) + 9);
		sprintf (buf, "rm -rf %s", savedDir);
		SystemCmd (buf);
		XtFree (buf);

		if (strcmp ("", savedOldDir)) {

			MoveDirectory (savedOldDir, savedDir, False);

			if (strcmp ("", savedTmpDir)) {
				MoveDirectory (savedTmpDir, savedOldDir, False);
			}
		}
	}
}


/*************************************<->*************************************
 *
 *  SetSavePath (saveToHome, mode)
 *
 *
 *  Description:
 *  -----------
 *  Sets up paths for files that need to be saved.  Also removes any files
 *  that shouldn't be there after the save.
 *
 *
 *  Inputs:
 *  ------
 *  smGD.display = display structure for session manager.  Used to construct
 *                     a display directory
 *  saveToHome = whether this is a save to home session or not
 *  mode = whether we are resetting or restarting
 * 
 *  Outputs:
 *  -------
 *  smGD.resourcePath(global) = Path where the resources to be saved are
 *                              to be saved.
 *  smGD.settingPath(global) = Path where the settings to be saved are
 *                              to be saved.
 *  smGD.clientPath(global) = Path where the clients to be saved are
 *                              to be saved.
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
int 
SetSavePath(
        Boolean saveToHome,
        int mode )
{
    struct stat         buf;
    int                 status;

    /*
     * These directory paths are needed in UndoSetSavePaths
     * if a shutdown/save is canceled.
     */
    strcpy (savedDir, "");
    strcpy (savedOldDir, "");
    strcpy (savedTmpDir, "");
    
    /*
     * Make sure the user hasn't done something like delete the .dt
     * directories during the session.  If so - recreate them
     */
    SM_FREE(smGD.savePath);
    smGD.savePath = _DtCreateDtDirs(smGD.display);
    if(smGD.savePath == NULL)
    {
        PrintErrnoError(DtError, smNLS.cantCreateDirsString);
        smGD.clientPath[0] = 0;
        smGD.settingPath[0] = 0;
        smGD.resourcePath[0] = 0;
        return(-1);
    }
        
    
    /*
     * Path for a save defaults to save the current session.
     * Otherwise just remove the directories
     */
    strcpy(smGD.clientPath, smGD.savePath);
    strcpy(smGD.settingPath, smGD.savePath);
    strcpy(smGD.resourcePath, smGD.savePath);
    strcat(smGD.clientPath, "/");
    strcat(smGD.settingPath, "/");
    strcat(smGD.resourcePath, "/");

    if(saveToHome == False)
    {
        strcat(smGD.clientPath, SM_CURRENT_DIRECTORY);
        strcat(smGD.resourcePath, SM_CURRENT_DIRECTORY);
        strcat(smGD.settingPath, SM_CURRENT_DIRECTORY);
	smGD.restoreSession = SM_CURRENT_DIRECTORY;
    }
    else
    {
        strcat(smGD.clientPath, SM_HOME_DIRECTORY);
        strcat(smGD.resourcePath, SM_HOME_DIRECTORY);
        strcat(smGD.settingPath, SM_HOME_DIRECTORY);
	smGD.restoreSession = SM_HOME_DIRECTORY;
    }

    if ((mode == DtSM_HOME_STATE) && (saveToHome == False) && 
       (smSettings.startState == DtSM_HOME_STATE))
    {
	/* 
	 * The only time this should should be true is if the
	 * current session is a Home session and the session
	 * is being exited.  The idea is that if a "current"
	 * directory exits, it must be moved because when the
	 * user next logs in, a Home session should be started
	 * (if a session is not selected at the login screen)
	 * and the Session Manager decides whether or not it
	 * starts a Home or Current session based on if a
	 * "current" directory exists.  If a "current" directory
	 * exists, a Current session will be started.
	 */
        status = stat(smGD.clientPath, &buf);
        if(status != -1)
        {
	    /*
	     * The "current" directory exists and must be moved to its
	     * ".old" version.  But first, if the ".old" version exists,
	     * it must be moved to a temporary directory.  This temporary
	     * directory will eventually be pruned - when a user next
	     * runs a Current session and saves the session.
	     */
	    strcpy (savedDir, smGD.clientPath);
            snprintf(smGD.etcPath, sizeof(smGD.etcPath), "%s.%s", smGD.clientPath, SM_OLD_EXTENSION);
            status = stat(smGD.etcPath, &buf);
            if(status == 0)
	    {
		char 		* tmpName;
                int len, tfd;

                strcpy(savedOldDir, smGD.etcPath);

                len = strlen(smGD.savePath) + strlen(smGD.restoreSession) 
                  + strlen("XXXXXX") + 3;
		tmpName = (char *) XtCalloc(1, len);

		sprintf(tmpName, "%s/%s.XXXXXX", smGD.savePath, 
                        smGD.restoreSession);

                if ((tfd = mkstemp(tmpName)) == -1)
                  {
                    PrintErrnoError(DtError, smNLS.cantCreateDirsString);
                  }
                else
                  {
                    close(tfd);
                    unlink(tmpName);

                    MoveDirectory(smGD.etcPath, tmpName, False);
                    
                    strncpy(savedTmpDir, tmpName, len - 1);
                  }
                XtFree((char *) tmpName);
	    }
	    MoveDirectory(smGD.clientPath, smGD.etcPath, False);
        }

        smGD.clientPath[0] = 0;
        smGD.settingPath[0] = 0;
        smGD.resourcePath[0] = 0;
    }
    else
    {
        strcpy (savedDir, smGD.clientPath);

        /*
         * If the desired directory doesn't exist, create it.
         */
        status = stat(smGD.clientPath, &buf);
        if(status == -1)
        {
            status = mkdir(smGD.clientPath, 0000);
            if(status == -1)
            {
                PrintErrnoError(DtError, smNLS.cantCreateDirsString);
                smGD.clientPath[0] = 0;
                smGD.settingPath[0] = 0;
                smGD.resourcePath[0] = 0;
                return(-1);
            }
            if(-1 == chmod(smGD.clientPath, 0755))
            {
				fprintf(stderr, "%s chmod error %s\n", smGD.clientPath, strerror(errno));
			}
        }
        else
        {
	    /*
	     * The desired directory already exists so it must
	     * be archived by moving it to its ".old" version. But
	     * first, if its ".old" version already exists, it must
	     * be moved to a temporary directory that will be removed 
	     * when the session directories are pruned - after the
	     * save is complete.
	     */
	    char 		* tmpName;

            snprintf(smGD.etcPath, sizeof(smGD.etcPath), "%s.%s", smGD.clientPath, SM_OLD_EXTENSION);
            status = stat(smGD.etcPath, &buf);
            if(status == 0)
	    {
              int len, tfd;

              len = strlen(smGD.savePath) + strlen(smGD.restoreSession) 
                + strlen("XXXXXX") + 3;
              tmpName = (char *) XtCalloc(1, len);
              snprintf(tmpName, len, "%s/%s.XXXXXX", smGD.savePath, 
                      smGD.restoreSession);

              strcpy (savedOldDir, smGD.etcPath);

              if ((tfd = mkstemp(tmpName)) == -1)
                {
                  PrintErrnoError(DtError, smNLS.cantCreateDirsString);
                }
              else
                {
                  close(tfd);
                  unlink(tmpName);

                  MoveDirectory (smGD.etcPath, tmpName, False);
              
                  strcpy (savedTmpDir, tmpName);
                }
              XtFree((char *) tmpName);
	    }

            MoveDirectory(smGD.clientPath, smGD.etcPath, False);

            /*
             * Now re-make the directory
             */
	       status = mkdir(smGD.clientPath, 0000);
	       if(status == -1)
	       {
                 PrintErrnoError(DtError, smNLS.cantCreateDirsString);
                 smGD.clientPath[0] = 0;
                 smGD.settingPath[0] = 0;
                 smGD.resourcePath[0] = 0;
                 return(-1);
               }
            status = chmod(smGD.clientPath, 0755);
            if(status == -1)
              {
                PrintErrnoError(DtError, smNLS.cantCreateDirsString);
                smGD.clientPath[0] = 0;
                smGD.settingPath[0] = 0;
                smGD.resourcePath[0] = 0;
                return(-1);
              }
        }
        
        strcat(smGD.clientPath, "/");
        strcat(smGD.clientPath, SM_CLIENT_FILE2);
        strcat(smGD.settingPath, "/");
        strcat(smGD.settingPath, SM_SETTING_FILE);
        strcat(smGD.resourcePath, "/");
        strcat(smGD.resourcePath, SM_RESOURCE_FILE);
    }

    return(0);
}


/*************************************<->*************************************
 *
 *  SetFontSavePath (saveToHome, mode)
 *
 *
 *  Description:
 *  -----------
 *  Sets up the save path for the auxillary directory.
 *
 *
 *  Inputs:
 *  ------
 *
 *  Outputs:
 *  -------
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
int 
SetFontSavePath(char *langPtr)
{
    struct stat         buf;
    int                 status;
    char                *sessionSaved;
    

    /*
     * Set up the session font directory and see if it exists
     */
    if(smGD.sessionType == CURRENT_SESSION)
    {
        sessionSaved = SM_CURRENT_FONT_DIRECTORY;
    }
    else
    {
        sessionSaved = SM_HOME_FONT_DIRECTORY;
    }

    snprintf(smGD.fontPath, MAXPATHLEN, "%s/%s", smGD.savePath, sessionSaved);
    status = stat(smGD.fontPath, &buf);
    if(status == -1)
    {
        status = mkdir(smGD.fontPath, 0000);
        if(status == -1)
        {
            PrintErrnoError(DtError, smNLS.cantCreateDirsString);
            smGD.fontPath[0] = 0;
            return(-1);
        }
        if(-1 == chmod(smGD.fontPath, 0755))
        {
			fprintf(stderr, "%s chmod error %s\n", smGD.fontPath, strerror(errno)); 
		}
    }

    /*
     * Now add the lang subdirectory and see if it exists
     */
    strncat(smGD.fontPath, "/", MAXPATHLEN);
    strncat(smGD.fontPath, langPtr, MAXPATHLEN);
    status = stat(smGD.fontPath, &buf);
    if(status == -1)
    {
        status = mkdir(smGD.fontPath, 0000);
        if(status == -1)
        {
            PrintErrnoError(DtError, smNLS.cantCreateDirsString);
            smGD.fontPath[0] = 0;
            return(-1);
        }
        status = chmod(smGD.fontPath, 0755);
        if(status == -1)
          {
            PrintErrnoError(DtError, smNLS.cantCreateDirsString);
            smGD.fontPath[0] = 0;
            return(-1);
          }
    }

    return(0);
}

                      

/*************************************<->*************************************
 *
 *  RemoveFiles()
 *
 *
 *  Description:
 *  -----------
 *  Remove the files that need to be removed
 *
 *
 *  Inputs:
 *  ------
 * 
 *  Outputs:
 *  -------
 *
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static void 
RemoveFiles(
        char *path )
{
    pid_t  clientFork;
    int    execStatus, childStatus, i, statLoc;
    String tmpString;

    /*
     * Fork and exec the client process
     */
    sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);

    clientFork = vfork();
    
    /*
     * If the fork fails - Send out an error and return
     */
    if(clientFork < 0)
    {
        PrintErrnoError(DtError, smNLS.cantForkClientString);
        return;
    }
    
    /*
     * Fork succeeded - now do the exec
     */
    if(clientFork == 0)
    {
        SetSIGPIPEToDefault ();

        /*
         * Set the gid of the process back from bin
         */
#ifndef SVR4
        setregid(smGD.runningGID, smGD.runningGID);
#else
        setgid(smGD.runningGID);
        setegid(smGD.runningGID);
#endif

        _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
        
#if defined(CSRG_BASED)
        setsid();
#else
        (void) setpgrp();
#endif /* CSRG_BASED */
         
        execStatus = execlp("rm","rm", "-rf", path, (char *) 0);
        if(execStatus != 0)
        {
            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.")) ;
            PrintErrnoError(DtError, tmpString);
            SM_FREE(tmpString);
            SM_EXIT(-1);
        }
    }

    while(wait(&statLoc) != clientFork);
    
    sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
}
                      

/*************************************<->*************************************
 *
 *  MoveDirectory()
 *
 *  Description:
 *  -----------
 *  Move the directory specified by pathFrom - to the directory specified
 *  by pathTo.
 *
 *  Inputs:
 *  ------
 *  pathFrom = the directory to move from
 *  pathTo = the directory to move to
 *  removeDestDir = if True, directory pathTo is removed before the
 * 	move occurs
 * 
 *  Outputs:
 *  -------
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
void 
MoveDirectory(
	char 		*pathFrom,
	char 		*pathTo,
	Boolean		removeDestDir)
{
    struct stat buf;
    pid_t  clientFork;
    int    status, execStatus, childStatus, i, statLoc;
    String tmpString;

    /*
     * If the pathTo directory exists - remove it
     */
    if (removeDestDir) 
    {
        status = stat(pathTo, &buf);
        if(status != -1)
        {
            RemoveFiles(pathTo);
        }
    }
           
    /*
     * Fork and exec the client process
     */
    sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);

    clientFork = vfork();
    
    /*
     * If the fork fails - Send out an error and return
     */
    if(clientFork < 0)
    {
        PrintErrnoError(DtError, smNLS.cantForkClientString);
        return;
    }
    
    /*
     * Fork succeeded - now do the exec
     */
    if(clientFork == 0)
    {
        SetSIGPIPEToDefault ();

        /*
         * Set the gid of the process back from bin
         */
#ifndef SVR4
        setregid(smGD.runningGID, smGD.runningGID);
#else
        setgid(smGD.runningGID);
        setegid(smGD.runningGID);
#endif

        _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
        
#if defined(CSRG_BASED)
        setsid();
#else
        (void) setpgrp();
#endif /* CSRG_BASED */
        
        execStatus = execlp("mv","mv", pathFrom, pathTo, (char *) 0);
        if(execStatus != 0)
        {
            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.")) ;
            PrintErrnoError(DtError, tmpString);
            SM_FREE(tmpString);
            SM_EXIT(-1);
        }
    }

    while(wait(&statLoc) != clientFork);
    
    sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
}

                                      

/*************************************<->*************************************
 *
 *  InitNlsStrings()
 *
 *
 *  Description:
 *  -----------
 *  Initialize the NLS strings used in dtsession
 *
 *
 *  Inputs:
 *  ------
 * 
 *  Outputs:
 *  -------
 *
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
void 
InitNlsStrings( void )
{
    char        *tmpString;

    /*
     * Malloc failure error message - THIS MESSAGE MUST BE INITIALIZED FIRST
     */
    smNLS.cantMallocErrorString = strdup (((char *)GETMESSAGE(4, 5, "Unable to malloc memory for operation.")));

    /*
     * Error message when dtsession cant lock the display
     */
    smNLS.cantLockErrorString = strdup (((char *)GETMESSAGE(4, 6, "Unable to lock display.  Another application may have the pointer or keyboard grabbed.")));

    /*
     * Error message when dtsession cant open files for reading or writing
     */
    smNLS.cantOpenFileString = strdup (((char *)GETMESSAGE(4, 7, "Unable to open session file.  No clients will be restarted.")));

    /*
     * Error message when dtsession cant fork client process
     */
    smNLS.cantForkClientString = strdup (((char *)GETMESSAGE(4, 8, "Unable to fork client process.")));

    /*
     * Error message when dtsession cant create dt directories
     */
    smNLS.cantCreateDirsString = strdup (((char *)GETMESSAGE(4, 9, "Unable to create DT directories.  Check permissions on home directory.")));

    /*
     * Error message when trying to lock display on trusted system
     */
    smNLS.trustedSystemErrorString = strdup (((char *)GETMESSAGE(4, 10, "Unable to lock display due to security restrictions")));
}
 
                                      

/*************************************<->*************************************
 *
 *  WaitChildDeath()
 *
 *
 *  Description:
 *  -----------
 *  When a SIGCHLD signal comes in, wait for all child processes to die.
 *
 *
 *  Inputs:
 *  ------
 * 
 *  Outputs:
 *  -------
 *
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/

void
WaitChildDeath( int i )
{
  int   stat_loc;
  pid_t pid;

 /*
  * Wait on any children that have died since the last SIGCHLD we
  * received. Any child process death that occurs while we are 
  * in WaitChildDeath() will not result in a SIGCHLD. Any
  * child proceses that die after our last call to waitpid() will
  * remain zombiefied until the next invocation of WaitChildDeath().
  */
  while ((pid = waitpid(-1, &stat_loc, WNOHANG)) > 0)
  ;

  sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
}

                                      

/*************************************<->*************************************
 *
 *  TrimErrorlog()
 *
 *
 *  Description:
 *  -----------
 *  Trim the errorlog file using the following algorithm:
 *      if(errorlog.old exists and is not empty) move it to errorlog.oldest
 *      if(errorlog exists and is not empty) move it to errorlog.old
 *
 *
 *  Inputs:
 *  ------
 * 
 *  Outputs:
 *  -------
 *
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static void
TrimErrorlog( void )
{
    char        *savePath, 	/* common path element for all pathnames */
		*checkPath1, 
		*checkPath2;
    struct stat buf;
    int len, status;
    char *home;

    /*
     * Allocate the strings needed
     */
    savePath = (char *) SM_MALLOC(MAXPATHLEN + 1);
    checkPath1 = (char *) SM_MALLOC(MAXPATHLEN + 1);
    checkPath2 = (char *) SM_MALLOC(MAXPATHLEN + 1);
    if ((home=getenv("HOME")) == NULL)
        home="";
    
    len = strlen(home) + strlen(DtPERSONAL_CONFIG_DIRECTORY) + 2;
    if (len > MAXPATHLEN) savePath = SM_REALLOC(savePath, len);
    snprintf(savePath, len, "%s/%s", home, DtPERSONAL_CONFIG_DIRECTORY);
    
    /*
     * If errorlog.old exists and it is not empty, delete
     * errorlog.older and then move errolog.old to 
     * errorlog.older
     */
    if (len + strlen(DtOLDER_ERRORLOG_FILE) > MAXPATHLEN)
      checkPath1 = SM_REALLOC(savePath, len + strlen(DtOLDER_ERRORLOG_FILE));
    sprintf(checkPath1, "%s/%s", savePath, DtOLDER_ERRORLOG_FILE);

    if (len + strlen(DtOLD_ERRORLOG_FILE) > MAXPATHLEN)
      checkPath2 = SM_REALLOC(savePath, len + strlen(DtOLD_ERRORLOG_FILE));
    sprintf(checkPath2, "%s/%s", savePath, DtOLD_ERRORLOG_FILE);

    status = stat(checkPath2, &buf);
    if((status != -1) && (buf.st_size > 0))
    {
	(void) unlink(checkPath1);
        (void) link(checkPath2, checkPath1);
        (void) unlink(checkPath2);
    }

    /*
     * If errorlog exists and it is not empty, move it to
     * errorlog.old
     */
    if (len + strlen(DtERRORLOG_FILE) > MAXPATHLEN)
      checkPath1 = SM_REALLOC(savePath, len + strlen(DtERRORLOG_FILE));
    snprintf(checkPath1, len + strlen(DtERRORLOG_FILE), "%s/%s", savePath, DtERRORLOG_FILE);

    status = stat(checkPath1, &buf);
    if((status != -1) && (buf.st_size > 0))
    {
        (void) link(checkPath1, checkPath2);
        (void) unlink(checkPath1);
    }

    SM_FREE((char *) savePath);
    SM_FREE((char *) checkPath1);
    SM_FREE((char *) checkPath2);

    return;
}

                                      

/*************************************<->*************************************
 *
 *  SetSystemReady()
 *
 *
 *  Description:
 *  -----------
 *  Do everything that needs to be done to get the system back into a
 *  READY state.  This includes checking to be sure that the BMS did not
 *  die while we were in process
 *
 *
 *  Inputs:
 *  ------
 * 
 *  Outputs:
 *  -------
 *
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
void
SetSystemReady( void )
{
    smGD.smState = READY;
    if(smGD.bmsDead == True)
    {
        WarnMsgFailure();
    }

    return;
}


/*************************************<->*************************************
 *
 *  SmCvtStringToContManagement (args, numArgs, fromVal, toVal)
 *
 *
 *  Description:
 *  -----------
 *  This function converts a string to a value for the 
 *  contention management flag set.
 *
 *
 *  Inputs:
 *  ------
 *  args = additional XrmValue arguments to the converter - NULL here
 *
 *  numArgs = number of XrmValue arguments - 0 here
 *
 *  fromVal = resource value to convert
 *
 * 
 *  Outputs:
 *  -------
 *  toVal = descriptor to use to return converted value
 *
 *************************************<->***********************************/

void SmCvtStringToContManagement (XrmValue *args, Cardinal numArgs, XrmValue *fromVal, XrmValue *toVal)
{

    unsigned char       *pch = (unsigned char *) (fromVal->addr);
    unsigned char       *pchNext;
    int         len;
    static long cval;
    Boolean     fHit = False;
    Boolean    fAddNext = True;

/*
 * Names of contention management options
 */

#define CM_ALL_STR              (unsigned char *)"all"
#define CM_SYSTEM_STR           (unsigned char *)"system"
#define CM_HANDSHAKE_STR        (unsigned char *)"handshake"
#define CM_NONE_STR             (unsigned char *)"none"

    /*
     * Check first token. If '-' we subtract from all options.
     * Otherwise, we start with no contention management and add things in.
     */

    if (*pch &&
        (_DtNextToken (pch, &len, &pchNext)) &&
        (*pch == '-'))
    {
        cval = SM_CM_ALL;
        fHit = True;
    }
    else
    {
        cval = SM_CM_NONE;
    }

    while (*pch && _DtNextToken (pch, &len, &pchNext))
    {
           /*
            * Strip off "sign" if prepended to another token, and process
            * that token the next time through.
            */

        if (*pch == '+')
        {
            if (len != 1)
            {
                pchNext = pch + 1;
            }
            fAddNext = TRUE;
        }

        else if (*pch == '-')
        {
            if (len != 1)
            {
                pchNext = pch + 1;
            }
            fAddNext = FALSE;
        }

        if ((*pch == 'A') || (*pch == 'a'))
        {
            if (_DtWmStringsAreEqual (pch, CM_ALL_STR, len))
            {
                cval = fAddNext ? (cval | SM_CM_ALL) :
                                  (cval & ~SM_CM_ALL);
                fHit = True;
            }
        }

        else if ((*pch == 'S') || (*pch == 's'))
        {
            if (_DtWmStringsAreEqual (pch, CM_SYSTEM_STR, len))
            {
                cval = fAddNext ? (cval | SM_CM_SYSTEM) :
                                  (cval & ~SM_CM_SYSTEM);
                fHit = True;
            }
        }

        else if ((*pch == 'H') || (*pch == 'h'))
        {
            if (_DtWmStringsAreEqual (pch, CM_HANDSHAKE_STR, len))
            {
                cval = fAddNext ? (cval | SM_CM_HANDSHAKE) :
                                  (cval & ~SM_CM_HANDSHAKE);
                fHit = True;
            }
        }

        else if ((*pch == 'N') || (*pch == 'n'))
        {
            if (_DtWmStringsAreEqual (pch, CM_NONE_STR, len))
            {
                /* don't bother adding or subtracting nothing */
                fHit = True;
            }
        }

        pch = pchNext;
    }



    /*
     * If we didn't match anything then set to default.
     */
    if (!fHit)
    {
        cval =  SM_CM_DEFAULT;
    }


    (*toVal).size = sizeof (long);
    (*toVal).addr = (caddr_t) &cval;


} /* END OF FUNCTION SmCvtStringToContManagement */


/*************************************<->*************************************
 *
 *  _DtNextToken (pchIn, pLen, ppchNext)
 *
 *
 *  Description:
 *  -----------
 *  XXDescription ...
 *
 *
 *  Inputs:
 *  ------
 *  pchIn = pointer to start of next token
 *
 * 
 *  Outputs:
 *  -------
 *  pLen  =    pointer to integer containing number of characters in next token
 *  ppchNext = address of pointer to following token
 *
 *  Return =   next token or NULL
 *
 *
 *  Comments:
 *  --------
 *  None.
 * 
 *************************************<->***********************************/

unsigned char *_DtNextToken (unsigned char *pchIn, int *pLen, 
        unsigned char **ppchNext)
{
    unsigned char *pchR = pchIn;
    register int   i;

#ifdef MULTIBYTE
    register int   chlen;

    for (i = 0; ((chlen = mblen ((char *)pchIn, MB_CUR_MAX)) > 0); i++)
    /* find end of word: requires singlebyte whitespace terminator */
    {
        if ((chlen == 1) && isspace (*pchIn))
        {
            break;
        }
        pchIn += chlen;
    }

#else
    for (i = 0; *pchIn && !isspace (*pchIn); i++, pchIn++)
    /* find end of word */
    {
    }
#endif

    /* skip to next word */
    ScanWhitespace (&pchIn);

    *ppchNext = pchIn;
    *pLen = i;
    if (i)
    {
        return(pchR);
    }
    else
    {
       return(NULL);
    }

} /* END OF FUNCTION _DtNextToken */   



/*************************************<->*************************************
 *
 *  _DtWmStringsAreEqual (pch1, pch2, len)
 *
 *
 *  Description:
 *  -----------
 *  XXDescription ...
 *
 *
 *  Inputs:
 *  ------
 *  pch1 =
 *  pch2 =
 *  len  =
 *
 * 
 *  Outputs:
 *  -------
 *  Return = (Boolean) True iff strings match (case insensitive)
 *
 *
 *  Comments:
 *  --------
 *  None.
 * 
 *************************************<->***********************************/

Boolean _DtWmStringsAreEqual (unsigned char *pch1, unsigned char *pch2, int len)
{
#ifdef MULTIBYTE
    int       chlen1;
    int       chlen2;
    wchar_t   wch1;
    wchar_t   wch2;

    while (len  && 
           ((chlen1 = mbtowc (&wch1, (char *) pch1, 2)) > 0) &&
           ((chlen2 = mbtowc (&wch2, (char *) pch2, 2)) == chlen1) )
    {
        if (chlen1 == 1)
        /* singlebyte characters -- make case insensitive */
        {
            if ((isupper (*pch1) ? tolower(*pch1) : *pch1) !=
                (isupper (*pch2) ? tolower(*pch2) : *pch2))
            {
                break;
            }
        }
        else
        /* multibyte characters */
        {
            if (wch1 != wch2)
            {
                break;
            }
        }
        pch1 += chlen1;
        pch2 += chlen2;
        len--;
    }

#else
    while (len  && *pch1 && *pch2 &&
           ((isupper (*pch1) ? tolower(*pch1) : *pch1) ==
            (isupper (*pch2) ? tolower(*pch2) : *pch2)))
    {
        *pch1++;
        *pch2++;
        len--;
    }
#endif

    return (len == 0);

} /* END OF _DtWmStringsAreEqual */   

/*************************************<->*************************************
 *
 *  InitializeGenericSession - set the smGD paths using the CDE 1.0
 *       session starting algorithm.
 *
 *  Description:
 *  -----------
 *  Initializes several variables in smGD
 *
 *  Inputs:
 *  ------
 *  tmpDisplay
 * 
 *  Outputs:
 *  -------
 *  Return = void
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static void
InitializeGenericSession (
	Display		*tmpDisplay)
{
    struct 	stat buf;
    int 	session_needed = 1;
    int 	status;
    char	tmpPath[MAXPATHLEN];

    smGD.savePath = _DtCreateDtDirs(tmpDisplay);

    if (session_needed)
    {
      strcpy(smGD.clientPath, smGD.savePath);
      strcat(smGD.clientPath, "/");
      strcat(smGD.clientPath, SM_CURRENT_DIRECTORY);
      strcat(smGD.clientPath, "/");
      strcpy (tmpPath, smGD.clientPath);
      strcat(smGD.clientPath, SM_CLIENT_FILE2);

      status = stat(smGD.clientPath, &buf);

      if (status != 0) {
	 strcpy (smGD.clientPath, tmpPath);
	 strcat (smGD.clientPath, SM_CLIENT_FILE);
         status = stat(smGD.clientPath, &buf);
      }

      if(status == 0)
      {
       /*
        * sessions/current/dt.settings exist, restore to 'current' session
        */
        strcpy(smGD.resourcePath, smGD.savePath);
        strcat(smGD.resourcePath, "/");
        strcat(smGD.resourcePath, SM_CURRENT_DIRECTORY);
	strcat(smGD.resourcePath, "/");
	strcat(smGD.resourcePath, SM_RESOURCE_FILE);
        strcpy(smGD.settingPath, smGD.savePath);
        strcat(smGD.settingPath, "/");
        strcat(smGD.settingPath, SM_CURRENT_DIRECTORY);
        strcat(smGD.settingPath, "/");
        strcat(smGD.settingPath, SM_SETTING_FILE);
        SetResSet();
        smGD.sessionType = CURRENT_SESSION;
        smGD.restoreSession = (char *) SM_CURRENT_DIRECTORY;
        session_needed = 0;
      }
    }

    if (session_needed)
    {
      strcpy(smGD.clientPath, smGD.savePath);
      strcat(smGD.clientPath, "/");
      strcat(smGD.clientPath, SM_HOME_DIRECTORY);
      strcat(smGD.clientPath, "/");
      strcpy(tmpPath, smGD.clientPath);
      strcat(smGD.clientPath, SM_CLIENT_FILE2);

      status = stat(smGD.clientPath, &buf);

      if (status != 0) {
	 strcpy (smGD.clientPath, tmpPath);
	 strcat (smGD.clientPath, SM_CLIENT_FILE);
         status = stat(smGD.clientPath, &buf);
      }

      if(status == 0)
      {
       /*
        * sessions/home/dt.settings exist, restore to 'home' session
        */
        strcpy(smGD.resourcePath, smGD.savePath);
        strcat(smGD.resourcePath, "/");
        strcat(smGD.resourcePath, SM_HOME_DIRECTORY);
	strcat(smGD.resourcePath, "/");
	strcat(smGD.resourcePath, SM_RESOURCE_FILE);
        strcpy(smGD.settingPath, smGD.savePath);
        strcat(smGD.settingPath, "/");
        strcat(smGD.settingPath, SM_HOME_DIRECTORY);
        strcat(smGD.settingPath, "/");
        strcat(smGD.settingPath, SM_SETTING_FILE);
        SetResSet();
        smGD.sessionType = HOME_SESSION;
        smGD.restoreSession = (char *) SM_HOME_DIRECTORY;
        session_needed = 0;
      }
    }

    if (session_needed)
    {
      SetSysDefaults();
    }
}

/*************************************<->*************************************
 *
 *  InternSessionDir - intern the session dir property and put it
 *     on the root window
 *
 *     NOTE: - also checks the validity of the -session command line
 *	   option
 *
 *  Inputs:
 *  ------
 *  session_option - as given in the command line
 *  display
 * 
 *  Outputs:
 *  ------
 *  smGD.restoreSession - initialized
 *
 *  Return = void
 *
 *************************************<->***********************************/
static Boolean
InternSessionDir (
	char		*session_option,
	Display		*disp)
{
	char		*pch;

	if (!strcmp (session_option, SM_CURRENT_DIRECTORY)) {
		pch = DtSM_SESSION_DIRECTORY;
		smGD.restoreSession = SM_CURRENT_DIRECTORY;
	}
	else if (!strcmp (session_option, SM_HOME_DIRECTORY)) {
		pch = DtSM_SESSION_DIRECTORY;
		smGD.restoreSession = SM_HOME_DIRECTORY;
	}
	else if (!strcmp (session_option, SM_DISPLAY_HOME)) {
		pch = DtSM_SESSION_DISPLAY_DIRECTORY;
		smGD.restoreSession = SM_HOME_DIRECTORY;
	}
	else if (!strcmp (session_option, SM_DISPLAY_CURRENT)) {
		pch = DtSM_SESSION_DISPLAY_DIRECTORY;
		smGD.restoreSession = SM_CURRENT_DIRECTORY;
	}
	else
		/*
		 * The session_option is not supported 
		 */
		return (False);

	XaSmRestoreDir = XInternAtom(disp, _XA_DT_RESTORE_DIR, False);

	XChangeProperty(disp, RootWindow(disp, 0),
		XaSmRestoreDir, XA_STRING, 8, PropModeReplace,
		(unsigned char *)pch, strlen(pch));

	XFlush(disp);


	return (True);
}


/*************************************<->*************************************
 *
 *  InitializeSpecificSession - set the smGD paths based on the session
 *       name given on the command line.
 *
 *  Description:
 *  -----------
 *  Initializes several variables in smGD
 *
 *  Inputs:
 *  ------
 *  session_option
 *  tmpDisplay
 * 
 *  Outputs:
 *  -------
 *  Return = void
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static Boolean
InitializeSpecificSession (
	char		*session_option,
	Display		*disp,
	unsigned int	argc,
	char		**argv)
{
	char		*session_dir = (char *) XtMalloc(MAXPATHLEN);
	char		*alt_dir = (char *) XtMalloc(MAXPATHLEN);
        int             len;
	struct stat 	buf;

	if (!InternSessionDir (session_option, disp))
		return (False);

	InitializePaths (smGD.restoreSession, disp);

	if (!strcmp (session_option, SM_HOME_DIRECTORY)) {
		/*
		 * Home session
		 */
		if (smGD.clientPath[0] == '\0') {
			if ((stat (smGD.savePath, &buf)) != 0) {
				if ((mkdir (smGD.savePath, 0000)) == 0)
					(void) chmod (smGD.savePath, 0755);
				else
                			PrintErrnoError(DtError, 
						smNLS.cantCreateDirsString);
			}
			SetSysDefaults ();
		}
		smGD.sessionType = HOME_SESSION;
		smGD.restoreSession = SM_HOME_DIRECTORY;
	} 
	else if (!strcmp (session_option, SM_CURRENT_DIRECTORY)) {
		/*
		 * Current session
		 */
		if (smGD.clientPath[0] == '\0') {
			/*
			 * Fallback to the generic home session
			 */
			(void) sprintf (session_dir, "%s/%s",
					smGD.savePath, SM_CURRENT_DIRECTORY);
			(void) sprintf (alt_dir, "%s/%s",
					smGD.savePath, SM_HOME_DIRECTORY);

			if (!SetAlternateSession (session_dir, alt_dir, True))
				SetSysDefaults ();
		}
		smGD.sessionType = CURRENT_SESSION;
		smGD.restoreSession = SM_CURRENT_DIRECTORY;
	}
	else if (!strcmp (session_option, SM_DISPLAY_HOME)) {
		/*
		 * Display-specific Home session
		 */
		(void) sprintf (session_dir, "%s/%s",
				smGD.savePath, SM_HOME_DIRECTORY);

		if ((stat(session_dir, &buf)) != 0){
			/*
			 * The session does not exist, give the user a
			 * change to exit.
			 */
			if (!ConfirmSessionCreation (HOME_SESSION, argc, argv))
				SM_EXIT (0);
				
		}

		if (smGD.clientPath[0] == '\0') {
			/*
			 * Fallback to the generic home session
			 */
			char		*home;

			if ((home = getenv ("HOME")) == 0)
				home = "";

                        /* JET - VU#497553 */
			len = strlen(home) + 
			  strlen(DtPERSONAL_CONFIG_DIRECTORY) +
			  strlen(DtSM_SESSION_DIRECTORY) +
			  strlen(SM_HOME_DIRECTORY);

			if (len > MAXPATHLEN)
			  alt_dir = XtRealloc(alt_dir, len + 1);

			(void) sprintf (alt_dir, "%s/%s/%s/%s",
					home,
					DtPERSONAL_CONFIG_DIRECTORY,
					DtSM_SESSION_DIRECTORY,
					SM_HOME_DIRECTORY);
			if (!SetAlternateSession (session_dir, alt_dir, True))
				SetSysDefaults ();
		}
		smGD.sessionType = HOME_SESSION;
		smGD.restoreSession = SM_HOME_DIRECTORY;
	}
	else if (!strcmp (session_option, SM_DISPLAY_CURRENT)) {
		/*
		 * Display-specific Current session
		 */
		(void) sprintf (session_dir, "%s/%s",
				smGD.savePath, SM_CURRENT_DIRECTORY);

		if ((stat(session_dir, &buf)) != 0){
			/*
			 * The session does not exist, give the user a
			 * change to exit.
			 */
			if (!ConfirmSessionCreation (CURRENT_SESSION, argc, argv))
				SM_EXIT (0);
		}

		if (smGD.clientPath[0] == '\0') {
			/*
			 * First, fallback to the display-specific home session
			 */
			char		*home;

			(void) sprintf (alt_dir, "%s/%s",
					smGD.savePath, SM_HOME_DIRECTORY);

			if (!SetAlternateSession (session_dir, alt_dir, False)){
				/*
				 * Try the generic home session
				 */
				if ((home = getenv ("HOME")) == 0)
					home = "";

                                /* JET - VU#497553 */
				len = strlen(home) + 
				  strlen(DtPERSONAL_CONFIG_DIRECTORY) +
				  strlen(DtSM_SESSION_DIRECTORY) +
				  strlen(SM_HOME_DIRECTORY);

				if (len > MAXPATHLEN)
				  alt_dir = XtRealloc(alt_dir, len + 1);

				snprintf(alt_dir, len, "%s/%s/%s/%s",
                                         home,
                                         DtPERSONAL_CONFIG_DIRECTORY,
                                         DtSM_SESSION_DIRECTORY,
                                         SM_HOME_DIRECTORY);

				if (!SetAlternateSession (session_dir, 
							  alt_dir, 
							  True))
					SetSysDefaults ();
			}
		}
		smGD.sessionType = CURRENT_SESSION;
		smGD.restoreSession = SM_CURRENT_DIRECTORY;
	}
	else {
		if (session_dir) XtFree(session_dir);
		if (alt_dir) XtFree(alt_dir);
		return (False);
	}
	
	if (session_dir) XtFree(session_dir);
	if (alt_dir) XtFree(alt_dir);
	return (True);
}


/*************************************<->*************************************
 *
 *  InitializePaths 
 *
 *  Description:
 *  -----------
 *  Initializes the following variables:
 *
 *     smGD.savePath
 *     smGD.settingsPath
 *     smGD.resourcePath
 *     smGD.clientPath - [0] = '\0' if the database files do not exist
 *
 *  Inputs:
 *  ------
 *  session_name = "current" or "home"
 * 
 *  Outputs:
 *  -------
 *  Return = void
 *
 *  Comments:
 *  --------
 * 
 *************************************<->***********************************/
static void
InitializePaths (
	char		* session_name,
	Display		* disp)
{
	char		*db_file = (char *) XtMalloc(MAXPATHLEN);
	struct stat 	buf;

        if (!db_file)
          {
            PrintError(DtError, smNLS.cantMallocErrorString);
            return;
          }

	smGD.savePath = _DtCreateDtDirs(disp);

	(void) sprintf (smGD.settingPath, "%s/%s/%s", 
			smGD.savePath, session_name, SM_SETTING_FILE);

	(void) sprintf (smGD.resourcePath, "%s/%s/%s",
			smGD.savePath, session_name, SM_RESOURCE_FILE);


	smGD.clientPath[0] = '\0';

	(void) sprintf (db_file, "%s/%s/%s", 
			smGD.savePath, session_name, SM_CLIENT_FILE2);

	if ((stat(db_file, &buf)) == 0)
		(void) strcpy (smGD.clientPath, db_file);
	else {
		(void) sprintf (db_file, "%s/%s/%s", 
				smGD.savePath, session_name, SM_CLIENT_FILE);
		if ((stat(db_file, &buf)) == 0)
			(void) strcpy (smGD.clientPath, db_file);
	}
	XtFree(db_file);
}


/*************************************<->*************************************
 *
 *  SetAlternateSession
 *
 *  Assumptions:
 *
 *     Neither of the client databases in the session_dir directory
 *     exist.
 *
 *  Inputs:
 *  ------
 *  session_dir - the directory path for the session including home
 *     or current
 *  alt_dir - the directory to use in the search for an alternate
 *     or fallback session database
 *  make_dir - if True, a session_dir will be created if it does not
 *     exits; if False, session_dir will not be created
 * 
 *  Outputs:
 *  -------
 *  Return = Boolean
 *
 *************************************<->***********************************/
static Boolean
SetAlternateSession (
	char		* session_dir,
	char		* alt_dir,
	Boolean		make_dir)
{
	char		*tmp_dir = NULL;
	char		*db_file1 = (char *) XtMalloc(MAXPATHLEN);
	char		*db_file2 = (char *) XtMalloc(MAXPATHLEN);
	struct stat 	buf;

        if (!db_file1 || !db_file2)
          {
            PrintError(DtError, smNLS.cantMallocErrorString);
            return False;
          }


	if ((stat (session_dir, &buf)) != 0) {
		/*
		 * The requested dir does not exist, create it
		 * by either copying the session from alt_dir (if
		 * it exists and has a client database) or by
		 * calling mkdir.
		 */
		
		(void) sprintf (db_file1, "%s/%s", 
				alt_dir, SM_CLIENT_FILE2);
		(void) sprintf (db_file2, "%s/%s", 
				alt_dir, SM_CLIENT_FILE);

		if ((stat(db_file1, &buf)) == 0)
			tmp_dir = db_file1;
		else if ((stat(db_file2, &buf)) == 0)
			tmp_dir = db_file2;

		if (!tmp_dir && !make_dir) {
			if (db_file1) XtFree(db_file1);
			if (db_file2) XtFree(db_file2);
			/*
			 * This alt_dir doesn't have a session database
			 * return now and try another directory
			 */
			return (False);
		}

		if (tmp_dir) {
			/*
			 * The alt_dir has a session database, create
			 * a copy of its entire directory because all
			 * of the sessions state is needed.
			 */
			char		*tmp;
			
			tmp = XtMalloc (strlen (alt_dir) + 
					strlen (session_dir) + 10);
			if (!tmp)
				return (False);

			(void) sprintf (tmp, "cp -r %s %s",
					alt_dir, session_dir);

			if ((system (tmp)) == -1)
				return (False);
			XtFree (tmp);

			if ((stat(session_dir, &buf)) != 0)
				/*
				 * It should have been created by the cp
				 */
				return (False);

			/*
			 * The session database needs to be updated.
			 */
			if (tmp_dir == db_file1)
				sprintf (smGD.clientPath, "%s/%s",
					session_dir, SM_CLIENT_FILE2);
			else
				sprintf (smGD.clientPath, "%s/%s",
					session_dir, SM_CLIENT_FILE);
		} else {
			/*
			 * The alt_dir did not have a session database.
			 * Create a directory and load the system defaults
			 */
			if ((mkdir (session_dir, 0000)) == 0)
				(void) chmod (session_dir, 0755);
			else {
                		PrintErrnoError(DtError, 
					smNLS.cantCreateDirsString);
				return (False);
			}
			SetSysDefaults ();
		}
	} else {
		/*
		 * The directory for the specified session exists
		 * but it doesn't have any client databases.  Start
		 * a new user session.  If a user wants a session
		 * with no apps, they should create a zero-length
		 * session database.
		 */
		SetSysDefaults ();
	}

	XtFree(db_file1);
	XtFree(db_file2);
	return (True);
}


void 
SmExit (
	int		exitStatus)
{
  /* JET - needed to rework this to avoid exiting before we are
   *  *really* ready to 
   */
  if (smGD.ExitComplete)
    {
      if (smXSMP.saveState.saveComplete && 
	  smXSMP.saveState.shutdown &&
	  !smXSMP.saveState.shutdownCanceled)
	XSMPExit ();
      _exit(exitStatus);
    }
  else
    return;
}

void
SetSIGPIPEToDefault (void)
{
	struct sigaction pipeSig;

	sigemptyset(&pipeSig.sa_mask);
	pipeSig.sa_flags = 0;
	pipeSig.sa_handler = SIG_DFL;
	(void) sigaction(SIGPIPE, &pipeSig, (struct sigaction *) NULL);
}
