2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: SmRestore.c /main/26 1998/12/14 20:13:07 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /*************************************<+>*************************************
31 *****************************************************************************
35 ** Project: HP DT Session Manager (dtsession)
39 ** This file contains functions that are in charge of restoring state.
40 ** When the session manager is first started, it restores the state that
41 ** was either last saved (home state), or last exited (current state). The
42 ** state restored depends on values the user has configured.
46 *******************************************************************
47 ** (c) Copyright Hewlett-Packard Company, 1990. All rights are
48 ** reserved. Copying or other reproduction of this program
49 ** except for archival purposes is prohibited without prior
50 ** written consent of Hewlett-Packard Company.
51 ********************************************************************
55 *****************************************************************************
56 *************************************<+>*************************************/
62 #ifdef _SUN_OS /* to get the define for NOFILE */
63 #include <sys/param.h>
65 #include <sys/types.h>
68 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
70 #include <sys/socket.h>
72 #include <netinet/in.h>
77 #include <X11/Intrinsic.h>
78 #include <X11/Xutil.h>
79 #include <X11/Xatom.h>
80 #include <X11/StringDefs.h>
81 #include <X11/keysymdef.h>
82 #include <X11/SM/SMlib.h>
86 # define Va_start(a,b) va_start(a,b)
89 #include <Dt/Message.h>
90 #include <Dt/CommandM.h>
91 #include <Dt/Connect.h>
94 #include <Dt/UserMsg.h>
95 #include <Dt/SessionM.h>
96 #include <Dt/EnvControlP.h>
97 #include <Dt/Utility.h>
98 #include <Dt/MsgLog.h>
100 #include <Dt/CmdInv.h>
101 #include <Dt/ActionUtilP.h>
104 #include "SmResource.h"
106 #include "SmCommun.h"
107 #include "SmRestore.h"
108 #include "SmProtocol.h"
109 #include "SmConMgmt.h"
112 #include "SmGlobals.h"
118 #include <X11/Xlibint.h>
124 static const char * DISPLAY_NAME_EQUAL = "DISPLAY=";
125 static const char * DISPLAY_NAME = "DISPLAY";
126 static char * savedDisplay = NULL;
132 #define MAXPATHSM 1023
133 #define MAX_QUOTE_DEPTH 10
135 #define SM_MAX_ARGS MAXLINE
137 #if defined (SVR4) || defined (__osf__)
138 #define REMOTE_CMD_STRING "rsh %s -n %s &"
140 #define REMOTE_CMD_STRING "remsh %s -n %s &"
149 unsigned char *hostPtr;
150 unsigned char *cmdPtr;
154 * Variables global to this module only
156 static XtResource settingsResources[] =
158 {SmNaccelNum, SmCaccelNum, XtRInt, sizeof(int),
159 XtOffset(SessionSettingsPtr, accelNum),
160 XtRImmediate, (XtPointer) -1},
161 {SmNaccelDenom, SmCaccelDenom, XtRInt, sizeof(int),
162 XtOffset(SessionSettingsPtr, accelDenom),
163 XtRImmediate, (XtPointer) -1},
164 {SmNthreshold, SmCthreshold, XtRInt, sizeof(int),
165 XtOffset(SessionSettingsPtr, threshold),
166 XtRImmediate, (XtPointer) -1},
168 {SmNtimeout, SmCtimeout, XtRInt, sizeof(int),
169 XtOffset(SessionSettingsPtr, timeout),
170 XtRImmediate, (XtPointer) -1},
171 {SmNinterval, SmCinterval, XtRInt, sizeof(int),
172 XtOffset(SessionSettingsPtr, interval),
173 XtRImmediate, (XtPointer) -1},
174 {SmNpreferBlank, SmCpreferBlank, XtRInt, sizeof(int),
175 XtOffset(SessionSettingsPtr, preferBlank),
176 XtRImmediate, (XtPointer) 0},
177 {SmNallowExp, SmCallowExp, XtRInt, sizeof(int),
178 XtOffset(SessionSettingsPtr, allowExp),
179 XtRImmediate, (XtPointer) 0},
181 {SmNfontPath, SmCfontPath, XtRString, sizeof(String),
182 XtOffset(SessionSettingsPtr, fontDirs), XtRString, (XtPointer) ""},
184 {SmNkeyClick, SmCkeyClick, XtRInt, sizeof(int),
185 XtOffset(SessionSettingsPtr, kbdState.key_click_percent),
186 XtRImmediate, (XtPointer) -1},
187 {SmNbellPercent, SmCbellPercent, XtRInt, sizeof(int),
188 XtOffset(SessionSettingsPtr, kbdState.bell_percent),
189 XtRImmediate, (XtPointer) -1},
190 {SmNbellPitch, SmCbellPitch, XtRInt, sizeof(int),
191 XtOffset(SessionSettingsPtr, kbdState.bell_pitch),
192 XtRImmediate, (XtPointer) -1},
193 {SmNbellDuration, SmCbellDuration, XtRInt, sizeof(int),
194 XtOffset(SessionSettingsPtr, kbdState.bell_duration),
195 XtRImmediate, (XtPointer) -1},
196 {SmNledMask, SmCledMask, XtRInt, sizeof(int),
197 XtOffset(SessionSettingsPtr, kbdState.led_mask),
198 XtRImmediate, (XtPointer) 0},
199 {SmNglobalRepeats, SmCglobalRepeats, XtRInt, sizeof(int),
200 XtOffset(SessionSettingsPtr, kbdState.global_auto_repeat),
201 XtRImmediate, (XtPointer) 2},
202 {SmNautoRepeats, SmCautoRepeats, XtRString, sizeof(String),
203 XtOffset(SessionSettingsPtr, autoRepeats), XtRString, (XtPointer) ""},
205 {SmNbuttonMap, SmCbuttonMap, XtRString, sizeof(String),
206 XtOffset(SessionSettingsPtr, buttonMap), XtRString, (XtPointer) ""},
208 {SmNnumKeyCode, SmCnumKeyCode, XtRInt, sizeof(int),
209 XtOffset(SessionSettingsPtr, numKeyCode), XtRImmediate, (XtPointer) 0},
210 {SmNkeySymsPerKey, SmCkeySymsPerKey, XtRInt, sizeof(int),
211 XtOffset(SessionSettingsPtr, keySymPerCode),
212 XtRImmediate, (XtPointer) 0},
213 {SmNkeySyms, SmCkeySyms, XtRString, sizeof(String),
214 XtOffset(SessionSettingsPtr, keySyms), XtRString, (XtPointer) ""},
216 {SmNmaxKeyPerMod, SmCmaxKeyPerMod, XtRInt, sizeof(int),
217 XtOffset(SessionSettingsPtr, maxKeyPerMod),
218 XtRImmediate, (XtPointer) 0},
219 {SmNmodMap, SmCmodMap, XtRString, sizeof(String),
220 XtOffset(SessionSettingsPtr, modSyms),
221 XtRString, (XtPointer) ""},
223 {SmNdidQuerySettings, SmCdidQuerySettings, XtRBoolean, sizeof(Boolean),
224 XtOffset(SessionSettingsPtr, didQuery),
225 XtRImmediate, (XtPointer) False},
226 {SmNshutDownState, SmCshutDownState, XtRInt, sizeof(int),
227 XtOffset(SessionSettingsPtr, confirmMode),
228 XtRImmediate, (XtPointer) 1},
229 {SmNshutDownMode, SmCshutDownMode, XtRInt, sizeof(int),
230 XtOffset(SessionSettingsPtr, startState),
231 XtRImmediate, (XtPointer) 4},
235 * Variables used for parsing code
238 static unsigned char fallBackLine[MAXLINE+2]; /* line buffer */
239 static unsigned char *line; /* line buffer */
240 static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
241 static int linec = 0; /* line counter for parser */
242 static unsigned char *parseP = NULL; /* pointer to parse string */
243 static int fileSize = 0;
244 char **smExecArray = NULL;
247 * Variables used for remote execution
249 static int numRemoteExecs = 0;
250 unsigned char *remoteBuf[MAX_SCREENS_SAVED];
251 unsigned int actRemoteSize[MAX_SCREENS_SAVED];
252 RemoteReq remoteBufPtr[MAX_REMOTE_CLIENTS];
253 static char localHost[MAXHOSTNAMELEN];
254 static char ** ignoreEnvPtr = NULL;
257 * Timeout for workspace manager handshake
259 static Boolean wmTimeout;
262 * These lines were added to support the builtin
266 char tmpExecWmFile[MAXPATHSM+1];
267 static Boolean localWmLaunched = False;
270 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
271 * End of lines were added to support the builtin
286 "*XmTextField*FontList",
287 "*DtEditor*textFontList",
292 static char *fontclass[] = {
300 "*XmTextField*FontList",
301 "*DtEditor*textFontList",
310 static int RestoreSettings( void ) ;
311 static int RestoreClients( void ) ;
312 static unsigned char * GetNextLine( void ) ;
313 static unsigned int PeekAhead( unsigned char *, unsigned int ) ;
314 static unsigned char * GetSmartString( unsigned char **) ;
315 static void ForkWM( void ) ;
316 static int FillCmdBuf( unsigned char *, unsigned char **,
317 unsigned int *, unsigned int *,
318 unsigned int, unsigned int *) ;
319 static int FillRemoteBuf( unsigned char *, unsigned char *,
320 unsigned char *, unsigned char **,
321 unsigned int *, unsigned int *, unsigned int) ;
322 static int FillHintBuf(unsigned char *, unsigned char **,
323 unsigned int *, unsigned int *,
324 unsigned int, unsigned int *);
325 static void WaitForWM( void ) ;
326 static void HandleWMClientMessage(Widget smWidget, XtPointer dummy,
328 static void WaitWMTimeout( XtPointer , XtIntervalId *) ;
329 static void FixEnvironmentData( void ) ;
330 static void ResetScreenInfo(unsigned char **,
331 int *, unsigned int *,
334 static void RemoteRequestFailed(char *, void *);
335 static void RemoteRequestSucceeded(char *, void *);
337 static void SetTemporaryDisplay (
340 int RestorePreferences(char *filename);
342 static void RestoreDisplay (
345 static Boolean StartLocalClient (
351 Boolean useIgnoreEnvResource);
353 static Boolean StartRemoteClient (
359 Boolean useIgnoreEnvResource);
361 static Boolean CheckRequiredProperties (
362 XSMPClientDBRecPtr pDbRec,
363 char * databaseName);
365 static Boolean CheckRequiredFields (
366 ProxyClientDBRecPtr pDbRec,
370 static void LogXSMPOpenDatabaseFailure (
372 DtMsgLogType msgType,
375 static void LogMissingPropertyMessage (
376 XSMPClientDBRecPtr pDbRec,
379 DtMsgLogType msgType);
381 static void LogCWDMessage (
386 static char ** RemoveEnvironmentVars (
389 static void MarkFileDescriptors (
395 /*************************************<->*************************************
402 * Sets _DT_SM_STATE_INFO for dtstyle indicating compatibility mode
415 * The only thing dtstyle should be looking at is the compatMode
417 *************************************<->***********************************/
419 SetCompatState( void )
424 * BEFORE any clients are started
425 * set a property on the top level window
426 * which lets the style manager know what state the sm is in
428 state.flags = SM_STATE_ALL;
429 state.smStartState = 0;
430 state.smConfirmMode = 0;
431 state.smCompatMode = True;
432 state.smSendSettings = False;
433 state.smCoverScreen = True;
434 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
435 state.smCycleTimeout = 0;
436 state.smLockTimeout = 0;
437 state.smSaverTimeout = 0;
439 state.smDisplaySpecific = smGD.displaySpecific;
441 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
443 XFlush(smGD.display);
447 } /* END OF FUNCTION SetCompatState */
450 /*************************************<->*************************************
457 * This function fiddles with our signal handling and calls the
458 * system() function to invoke a unix command.
463 * pchCmd = string with the command we want to exec.
471 * The system() command is touchy about the SIGCLD behavior. Restore
472 * the default SIGCLD handler during the time we run system().
474 *************************************<->***********************************/
477 SystemCmd (char *pchCmd)
479 void (*signalHandler) ();
481 signalHandler = (void (*)())signal (SIGCHLD, SIG_DFL);
485 signal (SIGCHLD, signalHandler);
486 } /* END OF FUNTION SystemCmd */
490 /*************************************<->*************************************
506 * When this routine is finished, all settings and resources will be restored.
507 * Clients may not be, as they are actually restored by different processes.
509 *************************************<->***********************************/
515 char convertCommand[MAXPATHSM+1];
517 Boolean fixedBuffer = False;
520 Boolean useXrmDB = False;
523 * Restore all the X settings which were active at the time of shutdown
527 if (smGD.sessionType == HOME_SESSION)
528 smSettings.startState = DtSM_HOME_STATE;
530 smSettings.startState = DtSM_CURRENT_STATE;
533 * BEFORE any clients are started
534 * set a property on the top level window
535 * which lets the style manager know what state the sm is in
537 state.flags = SM_STATE_ALL;
538 state.smStartState = smSettings.startState;
539 state.smConfirmMode = smSettings.confirmMode;
540 state.smCompatMode = smGD.compatMode;
541 state.smSendSettings = !smRes.querySettings;
542 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
543 state.smCycleTimeout = smSaverRes.cycleTimeout;
544 state.smLockTimeout = smSaverRes.lockTimeout;
545 state.smSaverTimeout = smSaverRes.saverTimeout;
546 state.smRandom = smSaverRes.random;
547 state.smDisplaySpecific = smGD.displaySpecific;
549 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
551 saver.saverList = smGD.saverList;
552 _DtSetSmSaver(smGD.display, smGD.topLevelWindow, &saver);
555 * Set up the Property telling all applications what session is being
558 XaSmRestoreMode = XInternAtom(smGD.display, _XA_DT_RESTORE_MODE, False);
559 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
560 XaSmRestoreMode, XA_STRING, 8, PropModeReplace,
561 (unsigned char *)smGD.restoreSession, strlen(smGD.restoreSession));
562 XFlush(smGD.display);
565 * Check the session database and either parse it as an
566 * Xrm-database or the CDE1.0 format
568 if ((pchar = strrchr (smGD.clientPath, '/')) != NULL)
571 if ((*pchar != '\0') && (!strcmp (pchar, SM_CLIENT_FILE2)))
577 return (StartXSMPSession (smGD.clientPath));
581 * Malloc line for parsing.
583 status = stat(smGD.clientPath, &buf);
586 fileSize = buf.st_size;
589 if (fileSize < MAXLINE + 1)
591 fileSize = MAXLINE + 1;
594 line = malloc(fileSize + 1);
598 fileSize = MAXLINE + 1;
601 cfileP = fopen(smGD.clientPath, "r");
604 PrintErrnoError(DtError, smNLS.cantOpenFileString);
605 if (!fixedBuffer && line)
607 SM_FREE((char *)line);
614 if (!fixedBuffer && line)
616 SM_FREE((char *)line);
625 /*************************************<->*************************************
632 * Start up the window manager. The default is to start dtmwm unless
633 * another one is specified in a resource.
646 * When this routine is finished, all settings and resources will be restored.
647 * Clients may not be, as they are actually restored by different processes.
649 *************************************<->***********************************/
653 char wmStartupErrorString[(2 * MAXPATHSM) + 1];
654 char localWmErrorString[(2 * MAXPATHSM) + 1];
655 Boolean goodWmStartup = True;
658 if((smGD.wmStartup == NULL) || (*smGD.wmStartup == 0))
664 CreateExecString(smGD.wmStartup);
667 * check to see if the wmStartup string exists and is
670 status = access(smExecArray[0], F_OK | X_OK);
673 goodWmStartup = False;
674 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
677 if(smExecArray[0] != NULL)
679 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
680 NULL, False, False, -1);
685 * We used to start the message server before the window
686 * manager and then if the message server did not start
687 * we would exit. Now we start the window manager, then
688 * start the message server and then wait for the window
689 * manager. This seems to improve performance.
694 if (goodWmStartup == False)
696 sprintf(wmStartupErrorString, GETMESSAGE(16, 7,
697 "The wmStartupCommand resource is set to:\n\n"
699 "This file does not exist or is not executable.\n"
700 CDE_INSTALLATION_TOP "/bin/dtwm will be started "
703 PrintError(DtError, wmStartupErrorString);
709 * These lines were added to support the builtin
713 if (localWmLaunched && wmTimeout)
715 if (!smGD.userSetWaitWmTimeout)
717 smRes.waitWmTimeout = smGD.savedWaitWmTimeout;
720 localWmLaunched = False;
722 * A special version of a built-in Xterminal dtwm
723 * was attempted and failed.
724 * Try to launch .../dt/bin/dtwm instead
727 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
728 if(smExecArray[0] != NULL)
730 (void) StartClient(smExecArray[0], smExecArray, NULL,
731 NULL, NULL, False, False, -1);
734 sprintf(localWmErrorString, GETMESSAGE(16, 9,
735 "The following window manager did not start:\n\n"
737 "This message indicates you tried to start a\n"
738 "window manager that is built into an X terminal.\n"
739 "This will only work with X terminals that support this protocol.\n"
740 CDE_INSTALLATION_TOP "/bin/dtwm will be started instead.\n"),
742 PrintError(DtError, localWmErrorString);
745 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
746 * End of lines were added to support the builtin
755 /*************************************<->*************************************
762 * Reloads RESOURCE_MANAGER during running session
774 *************************************<->***********************************/
777 ReloadResources(void)
780 * Load sys.resources and .Xdefaults
782 RestoreResources(True,
789 * Merge _DT_SM_PREFERENCES
791 RestorePreferences(NULL);
797 /*************************************<->*************************************
799 * RestoreResources (errorHandlerInstalled, options ... )
804 * Calls routines responsible for restoring resources.
805 * Resources are restored by a fork and exec of dtsession_res.
818 * When this routine is finished, all settings and resources will be restored.
819 * Clients may not be, as they are actually restored by different processes.
821 *************************************<->***********************************/
824 RestoreResources( Boolean errorHandlerInstalled, ... )
827 int childStatus, execStatus, i;
833 /* JET - this seems like a bad (and unused) idea */
835 * Check for alternate resource loader.
837 if ((pgrm = getenv("DTLOADRESOURCES")) == NULL)
839 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
842 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
846 * By convention, exec() wants arg0 to be the program name. Ex: if pgrm
847 * is /usr/dt/bin/dtsession_res, the program name is dtsession_res.
848 * If all else fails, use pgrm.
850 argv[0] = (p = strrchr(pgrm, '/')) != NULL && *(p+1) != '\0' ? p+1 : pgrm;
853 Va_start(args,errorHandlerInstalled);
857 argv[i] = va_arg(args, char *);
863 * if an error handler is installed - remove it
865 if(errorHandlerInstalled)
867 sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
871 * Fork and exec the xrdb process to load in the file created by
872 * writing out the resource manager string generated by the last
873 * session termination.
876 for(i = 0;(i < 10) && ((forkrc = vfork()) < 0);i++)
887 PrintErrnoError(DtError, smNLS.cantForkClientString);
892 * Fork succeeded - now do the exec
896 SetSIGPIPEToDefault ();
900 * Set the gid of the process back from bin
903 setregid(smGD.runningGID, smGD.runningGID);
905 setgid(smGD.runningGID);
906 setegid(smGD.runningGID);
909 #if defined(__osf__) || defined(CSRG_BASED)
915 MarkFileDescriptors (3, F_SETFD, 1);
917 execStatus = execv(pgrm, argv);
921 char clientMessage[MAXPATHLEN + 256];
923 memset(clientMessage, 0, MAXPATHLEN + 256);
924 snprintf(clientMessage, (MAXPATHLEN + 256) - 1,
925 ((char *)GETMESSAGE(16, 1, "Unable to exec process %s. No session resources will be restored.")), pgrm);
926 PrintErrnoError(DtError, clientMessage);
931 while(wait(&childStatus) != forkrc);
934 * if an error handler is installed - remove it
936 if(errorHandlerInstalled)
938 sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
945 /*************************************<->*************************************
947 * RestorePreferences ( filename)
953 * This routine has two roles:
955 * 1) If 'filename' specified, the content of filename is read, and
956 * _DT_SM_PREFERENCES is populated with its content. This is used
957 * at session startup to set the initial state of _DT_SM_PREFERENCES.
959 * 2) If 'filename' is NULL, the content of _DT_SM_PREFERENCES is
960 * merged into RESOURCE_MANAGER. This is used when resources are
961 * reloaded at user request during a session.
974 *************************************<->***********************************/
986 struct stat statinfo;
988 if(access(filename,R_OK) != 0)
994 * Determine size of file.
996 if (stat(filename, &statinfo) == -1)
1004 if ((data = (char *)SM_MALLOC(statinfo.st_size + 1)) == NULL)
1010 * Read file into memory.
1012 if ((fp = fopen(filename, "r")) == NULL)
1018 size = fread(data, 1, statinfo.st_size, fp);
1020 if (size == statinfo.st_size)
1023 * Merge .Xdefaults string into RESOURCE_MANAGER database, and
1024 * also convert to Xrm database form for later subtraction.
1027 _DtAddResString(smGD.display, data, _DT_ATR_PREFS);
1035 * Read string from _DT_SM_PREFERENCES
1037 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1040 * Merge string into RESOURCE_MANAGER
1042 _DtAddResString(smGD.display, data, _DT_ATR_RESMGR);
1051 /*************************************<->*************************************
1053 * RestoreSettings ()
1058 * In charge of restoring all settings. Settings are stored in resource
1059 * format so it gets the values by getting the resource values stored in
1060 * a resource file that was created by the session manager.
1065 * smGD.settingPath = path that points to the settings resource file.
1074 * This routine messes with the actual strings returned by the resource
1075 * manager by tokenizing them, so these session settings resources should
1076 * not be accessed again.
1078 *************************************<->***********************************/
1080 RestoreSettings( void )
1082 XrmDatabase smBase = NULL;
1083 XKeyboardControl kbdControl;
1085 char **restorePtrArray, **tmpRestore;
1086 char *restoreCharArray;
1087 int numArgs, ptrSize, charSize;
1090 KeySym *tmpSyms, codeSym;
1093 XModifierKeymap restoreMod;
1097 restorePtrArray = (char **) SM_MALLOC (ptrSize * sizeof(char *));
1098 restoreCharArray = (char *) SM_MALLOC (charSize * sizeof(char));
1099 if((restorePtrArray == NULL) || (restoreCharArray == NULL))
1101 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1103 if(restorePtrArray != NULL)
1105 SM_FREE((char *) restorePtrArray);
1109 if(restoreCharArray != NULL)
1111 SM_FREE(restoreCharArray);
1118 * Load the resources from the SM database file
1120 if (smGD.settingPath[0] != 0)
1122 smBase = XrmGetFileDatabase(smGD.settingPath);
1126 PrintError(DtError, GETMESSAGE(16, 2, "Invalid client settings file. No settings restored."));
1131 XrmMergeDatabases(smBase, &(smGD.display->db));
1136 * Retrieve the session settings file from the database
1138 XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smSettings,
1139 settingsResources, XtNumber(settingsResources),
1143 * Copy any string resources since they may be overwritten in
1146 smGD.fontDirs = SmNewString(smSettings.fontDirs);
1147 smGD.autoRepeats = SmNewString(smSettings.autoRepeats);
1148 smGD.buttonMap = SmNewString(smSettings.buttonMap);
1149 smGD.keySyms = SmNewString(smSettings.keySyms);
1150 smGD.modSyms = SmNewString(smSettings.modSyms);
1154 * This is provided for backward compatibility sake. The values that
1155 * confirmMode can take have changed
1157 if(smSettings.confirmMode == DtSM_ASK_STATE)
1159 smSettings.confirmMode = DtSM_VERBOSE_MODE;
1163 * If the user has previously used the "query" method, and now wishes
1164 * to use "only what I've customized" method, then we have to start
1165 * from scratch. So don't set anything until customizer tells me to
1167 if((smSettings.didQuery == True) && (smRes.querySettings == False))
1169 SM_FREE((char *) restorePtrArray);
1170 SM_FREE(restoreCharArray);
1175 * Restore pointer control settings
1177 if((smSettings.accelNum > -1 ) || (smSettings.threshold > -1))
1179 XChangePointerControl(smGD.display, True, True,
1180 smSettings.accelNum,
1181 smSettings.accelDenom,
1182 smSettings.threshold);
1183 smToSet.pointerChange = True;
1187 smToSet.pointerChange = False;
1191 * Restore screen saver settings if any are set to non-default
1194 if ((smSettings.timeout > -1) || (smSettings.interval > -1) ||
1195 (smSaverRes.saverTimeout > -1) || (smSaverRes.lockTimeout > -1) ||
1196 (smSaverRes.cycleTimeout > -1))
1200 * For the time between Screen Savers, use the cycleTimeout
1201 * if the user has set this value. Otherwise, use the interval
1202 * value that was set when the session was saved.
1204 if (smSaverRes.cycleTimeout < 0)
1206 screenSaverVals.smInterval = smSettings.interval;
1210 screenSaverVals.smInterval = smSaverRes.cycleTimeout;
1214 * For the screen saver time, use the minimum of the values set for
1215 * saverTimeout or lockTimeout if the user has set one of these
1218 * Otherwise, use the Timeout value that was set when the
1219 * session was saved.
1221 * If it is not set, then use the minimum of the values set for
1222 * saverTimeout or lockTimeout. Set timeout to the Timeout value
1225 if ((smSaverRes.saverTimeout > -1) ||
1226 (smSaverRes.lockTimeout > -1))
1228 if (smSaverRes.saverTimeout > -1)
1230 if ((smSaverRes.lockTimeout > -1) &&
1231 (smSaverRes.lockTimeout < smSaverRes.saverTimeout))
1233 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1237 screenSaverVals.smTimeout = smSaverRes.saverTimeout;
1242 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1247 screenSaverVals.smTimeout = smSettings.timeout;
1249 screenSaverVals.smPreferBlank = smSettings.preferBlank;
1250 screenSaverVals.smAllowExp = smSettings.allowExp;
1252 /* Notify X of the new screen saver values */
1253 XSetScreenSaver(smGD.display, screenSaverVals.smTimeout,
1254 screenSaverVals.smInterval,
1255 screenSaverVals.smPreferBlank,
1256 screenSaverVals.smAllowExp);
1259 * If using timeout or interval values that were
1260 * previously saved, then set flag to indicate that they
1261 * should be saved again when the state for the session
1264 if ((smSettings.timeout > -1) || (smSettings.interval > -1))
1266 smToSet.screenSavChange = True;
1270 smToSet.screenSavChange = False;
1276 smToSet.screenSavChange = False;
1280 * Get the font path. Then set it.
1282 tmpRestore = restorePtrArray;
1284 *tmpRestore = strtok(smGD.fontDirs, ",");
1286 while(*tmpRestore != NULL)
1288 numArgs++; tmpRestore++;
1289 *tmpRestore = strtok(NULL, ",");
1290 if((numArgs >= ptrSize) && (*tmpRestore != NULL))
1293 restorePtrArray = (char **)SM_REALLOC((char *)
1294 restorePtrArray, ptrSize *
1296 if(restorePtrArray == NULL)
1298 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1299 SM_FREE(restoreCharArray);
1307 XSetFontPath(smGD.display, restorePtrArray, numArgs);
1311 * Restore the keyboard control information. In order for it
1312 * to be restored it has to be changed from a XKeyboardState
1313 * format to an XKeyboardControl format.
1315 if((smSettings.kbdState.key_click_percent > -1) ||
1316 (smSettings.kbdState.bell_percent > -1) ||
1317 (smSettings.kbdState.bell_pitch > -1) ||
1318 (smSettings.kbdState.bell_duration > -1))
1322 if((smSettings.kbdState.bell_percent > -1) ||
1323 (smSettings.kbdState.bell_pitch > -1) ||
1324 (smSettings.kbdState.bell_duration > -1))
1326 kbdControl.bell_percent = smSettings.kbdState.bell_percent;
1327 kbdControl.bell_pitch = smSettings.kbdState.bell_pitch;
1328 kbdControl.bell_duration = smSettings.kbdState.bell_duration;
1329 kbdControlMask |= (KBBellPercent | KBBellPitch | KBBellDuration);
1330 smToSet.audioChange = True;
1331 audioVals.smBellPercent = smSettings.kbdState.bell_percent;
1332 audioVals.smBellPitch = smSettings.kbdState.bell_pitch;
1333 audioVals.smBellDuration = smSettings.kbdState.bell_duration;
1337 smToSet.audioChange = False;
1340 if((smSettings.kbdState.key_click_percent > -1) ||
1341 (smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn))
1343 kbdControl.key_click_percent =
1344 smSettings.kbdState.key_click_percent;
1345 kbdControlMask |= KBKeyClickPercent;
1346 smToSet.keyboardChange = True;
1347 keyboardVals.smKeyClickPercent = kbdControl.key_click_percent;
1351 smToSet.keyboardChange = False;
1356 * NOTICE THAT THE LED'S DON'T GET RESET. THIS IS BECAUSE LED STUFF
1357 * IS MACHINE DEPENDENT.
1360 * Set the auto repeat stuff
1362 tmpKey = strtok(smGD.autoRepeats, ",");
1363 if((tmpKey == NULL) &&
1364 ((smSettings.kbdState.global_auto_repeat == AutoRepeatModeOff) ||
1365 (smSettings.kbdState.global_auto_repeat == AutoRepeatModeOn)))
1367 smToSet.keyboardChange = True;
1368 kbdControl.auto_repeat_mode =
1369 smSettings.kbdState.global_auto_repeat;
1370 kbdControlMask |= KBAutoRepeatMode;
1371 XChangeKeyboardControl(smGD.display, kbdControlMask, &kbdControl);
1372 keyboardVals.smGlobalAutoRepeat =
1373 smSettings.kbdState.global_auto_repeat;
1379 smToSet.keyboardChange = True;
1380 kbdControl.auto_repeat_mode = smSettings.kbdState.global_auto_repeat;
1381 kbdControlMask |= KBAutoRepeatMode;
1382 XChangeKeyboardControl(smGD.display,
1383 kbdControlMask, &kbdControl);
1384 kbdControl.auto_repeat_mode = AutoRepeatModeOn;
1385 kbdControlMask = KBAutoRepeatMode | KBKey;
1387 * This is only involked when there is auto repeats set for
1388 * specific keys only. It is VERY SLOW code so unless you
1389 * have to save off auto repeats for single keys - DONT
1391 while(tmpKey != NULL)
1393 kbdControl.key = atoi(tmpKey);
1394 XChangeKeyboardControl(smGD.display,
1395 kbdControlMask, &kbdControl);
1396 tmpKey = strtok(NULL, ",");
1401 if(kbdControlMask != 0)
1403 XChangeKeyboardControl(smGD.display,
1404 kbdControlMask, &kbdControl);
1411 smToSet.audioChange = False;
1412 smToSet.keyboardChange = False;
1416 * Restore the button mappings
1419 tmpKey = strtok(smGD.buttonMap, ",");
1423 smToSet.pointerMapChange = True;
1427 smToSet.pointerMapChange = False;
1430 while(tmpKey != NULL)
1432 restoreCharArray[numArgs] = (char) atoi(tmpKey);
1434 tmpKey = strtok(NULL, ",");
1435 if((numArgs >= charSize) && (tmpKey != NULL))
1438 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1439 charSize * sizeof(char));
1440 if(restoreCharArray == NULL)
1442 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1443 SM_FREE((char *)restorePtrArray);
1451 XSetPointerMapping(smGD.display, (unsigned char *)restoreCharArray, numArgs);
1454 * Copy the pointer map into the saved map for logout
1456 smToSet.numButton = ((numArgs > 5) ? 5 : numArgs);
1457 for(i = 0; i < smToSet.numButton;i++)
1459 smToSet.pointerMap[i] = restoreCharArray[i];
1464 * Restore the key mappings
1466 if(smSettings.numKeyCode > 0)
1468 tmpSyms = (KeySym *) restoreCharArray;
1469 symSize = (charSize * sizeof(char)) / sizeof(KeySym);
1470 tmpKey = strtok(smGD.keySyms, ",");
1471 for(i = 0;tmpKey != NULL;i++)
1473 tmpSyms[i] = (KeySym) atol(tmpKey);
1474 tmpKey = strtok(NULL, ",");
1476 if((numArgs >= symSize) && (tmpKey != NULL))
1479 symSize = (charSize * sizeof(char))/sizeof(KeySym);
1480 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1481 (charSize * sizeof(char)));
1482 if(restoreCharArray == NULL)
1484 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1485 SM_FREE((char *) restorePtrArray);
1488 tmpSyms = (KeySym *) restoreCharArray;
1491 numArgs /= smSettings.keySymPerCode;
1492 XChangeKeyboardMapping(smGD.display, (KeyCode)
1493 smGD.display->min_keycode,
1494 smSettings.keySymPerCode, tmpSyms,
1499 * Restore the modifier mappings
1501 tmpCode = (KeyCode *) restoreCharArray;
1502 tmpKey = strtok(smGD.modSyms, ",");
1505 for(i = 0;i < (8 * smSettings.maxKeyPerMod);i++)
1509 codeSym = (KeySym) atol(tmpKey);
1512 tmpCode[i] = XKeysymToKeycode(smGD.display, codeSym);
1516 tmpCode[i] = (KeyCode) 0;
1521 tmpCode[i] = (KeyCode) 0;
1523 tmpKey = strtok(NULL, ",");
1525 restoreMod.max_keypermod = smSettings.maxKeyPerMod;
1526 restoreMod.modifiermap = tmpCode;
1527 XSetModifierMapping(smGD.display, &restoreMod);
1530 SM_FREE((char *) restorePtrArray);
1531 SM_FREE(restoreCharArray);
1538 /*************************************<->*************************************
1540 * RestoreIndependentResources ()
1545 * In charge of restoring the resources that help make the session more
1546 * resolution and language independent - only restored if they are
1547 * necessary (lang || resolution has changed) and exist
1552 * smResources = global pointer to the resources to be restored by the SM
1562 *************************************<->***********************************/
1564 RestoreIndependentResources( void )
1568 unsigned long nitems, leftover;
1569 unsigned char *data = NULL;
1571 XrmValue fontResourceReturn;
1572 char *currentLangPtr, *resValRet, *sessionType;
1574 int intYRes[2], status,i;
1577 Boolean resIndep = False, resRet;
1580 if(((smGD.sessionLang == NULL) || (*smGD.sessionLang == 0)) &&
1581 (smRes.displayResolution == 0))
1584 * No saved info to draw from - nothing new is added
1589 currentLangPtr = getenv("LANG");
1591 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1592 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1594 if(fltYRes < MED_RES_Y_RES)
1596 intYRes[0] = LOW_RES_Y_RES;
1597 sessionRes = SM_LOW_RES_EXT;
1601 if(fltYRes >= HIGH_RES_Y_RES)
1603 intYRes[0] = HIGH_RES_Y_RES;
1604 sessionRes = SM_HIGH_RES_EXT;
1608 intYRes[0] = MED_RES_Y_RES;
1609 sessionRes = SM_MED_RES_EXT;
1613 if(smRes.displayResolution < MED_RES_Y_RES)
1615 intYRes[1] = LOW_RES_Y_RES;
1619 if(smRes.displayResolution >= HIGH_RES_Y_RES)
1621 intYRes[1] = HIGH_RES_Y_RES;
1625 intYRes[1] = MED_RES_Y_RES;
1630 * If the resolution or the language has changed -
1631 * load the language/resolution independent fonts if
1632 * they exist in the users home directory or in the system
1634 if((strcmp(currentLangPtr, smGD.sessionLang)) ||
1635 (intYRes[0] != intYRes[1]))
1637 char *fontPath = SM_MALLOC(MAXPATHLEN + 1);
1639 if(smGD.sessionType == HOME_SESSION)
1641 sessionType = SM_HOME_FONT_DIRECTORY;
1645 sessionType = SM_CURRENT_FONT_DIRECTORY;
1648 memset(fontPath, 0, MAXPATHLEN + 1);
1649 snprintf(fontPath, MAXPATHLEN, "%s/%s/%s/%s.%s",
1650 smGD.savePath, sessionType,
1651 currentLangPtr, SM_FONT_FILE, sessionRes);
1652 status = stat(fontPath, &buf);
1656 * User has nothing there - look in the system defaults
1657 * first in the language dep -then in lang independent
1659 memset(fontPath, 0, MAXPATHLEN + 1);
1661 if((currentLangPtr != NULL) && (*currentLangPtr != 0))
1663 strcat(fontPath, "/");
1664 strncat(fontPath, currentLangPtr, MAXPATHLEN);
1667 strncat(fontPath, "/", MAXPATHLEN);
1668 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1672 status = stat(fontPath, &buf);
1675 if((currentLangPtr != NULL) && (*currentLangPtr != 0) &&
1676 (strcmp(currentLangPtr, "C")))
1678 memset(fontPath, 0, MAXPATHLEN + 1);
1679 strcpy(fontPath, "/C/");
1680 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1684 status = stat(fontPath, &buf);
1701 strncpy(smGD.fontPath, fontPath, MAXPATHLEN);
1703 if(resIndep == True)
1707 * add the auxillary resources onto the root window
1709 RestoreResources(True, "-merge", "-file", smGD.fontPath, NULL);
1712 * Load the resources from the RESOURCE_MANAGER
1713 * property on the root window
1715 if(XGetWindowProperty(smGD.display, RootWindow(smGD.display, 0),
1716 XA_RESOURCE_MANAGER,0L,
1717 100000000L,False,XA_STRING,&actualType,
1718 &actualFormat,&nitems,&leftover,
1719 (unsigned char**) &data) == Success)
1721 smBase = XrmGetStringDatabase((char *)data);
1730 PrintError(DtError, GETMESSAGE(16, 6, "Invalid display/language independent resource file. No display/language independent resources will be restored."));
1731 SM_FREE((char *)data);
1737 * Get the new fontlist from the resources and
1738 * Put it on the application shell. Then add
1739 * the auxillary resources into the display struct
1741 resRet = XrmGetResource(smBase, "*fontList", "*FontList",
1742 &resValRet, &fontResourceReturn);
1745 XtSetArg(uiArgs[i], XmNdefaultFontList,
1746 (XmFontList) fontResourceReturn.addr);i++;
1747 XtSetValues(smGD.topLevelWid, uiArgs, i);
1750 * Overwrite the old font preferences, otherwise,
1751 * they'll come back to haunt us if the user logs in again
1752 * under the current language. We need to get the font
1753 * resources which have just been loaded, then overlay
1754 * them onto the _DT_SM_PREFERENCES root property to make
1755 * sure we get them back when we login again.
1757 for (i = 0; i < XtNumber(fonttype); i++)
1759 resRet = XrmGetResource(smBase, fonttype[i], fontclass[i],
1760 &resValRet, &fontResourceReturn);
1764 (char *)SM_MALLOC(fontResourceReturn.size + 30);
1765 bzero(resdata, fontResourceReturn.size + 30);
1766 strcat(resdata, fonttype[i]);
1767 strcat(resdata, ": ");
1768 strcat(resdata, fontResourceReturn.addr);
1769 strcat(resdata, "\n");
1770 _DtAddResString(smGD.display, resdata, _DT_ATR_PREFS);
1775 XrmMergeDatabases(smBase, &(smGD.display->db));
1776 SM_FREE((char *)data);
1780 SM_FREE((char*) fontPath);
1787 /*************************************<->*************************************
1794 * Reads through the client file and restores its contents. A client file
1795 * consists of hints for the workspace manager, actual client commands, and
1796 * remote execution commands. All commands are processed accordingly.
1797 * If this is the first DT 3.0 session for a DT 2.0 user then we will
1798 * also launch the helpviewer. If this is the first DT 3.0 session for a
1799 * DT 2.0 user then we will also run convertVS.sh to change all
1800 * occurances of /usr/bin/X11/hpterm to .../dt/bin/hpterm,
1801 * /usr/bin/X11/xterm to .../dt/bin/xterm and
1802 * /usr/bin/X11/xload to .../dt/bin/xload.
1813 * Any information read from the client file will be mucked with during
1814 * processing, and should not try to be mucked with again.
1816 * WARNING: This routine closes cfileP - not the calling routine
1817 * DOUBLE-WARNING: This routine starts the window manager
1819 *************************************<->***********************************/
1821 RestoreClients( void )
1823 unsigned char *lineP, *string;
1824 char *pch, *dispPtr = NULL;
1825 char *dispEnv, *dispSav, *dispEnvHelpview, *dispSavHelpview;
1826 unsigned char *hostPtr=NULL, *cmdPtr=NULL, *hintPtr = NULL;
1827 unsigned char *remoteDisplay;
1830 unsigned char tmpChar[35];
1831 int screenNum = 0, i, j, chlen, numClientsExec;
1832 int numRemoteDone = 0;
1834 Boolean clientsDone = False, wmHandshake = False, cmdInvInit = False;
1835 XClientMessageEvent smToWmMessage;
1838 * These variables are needed to buffer up the commands and then
1839 * execute them (also buffer up hints then put them on the root window
1841 unsigned char *hintsBuf[MAX_SCREENS_SAVED];
1842 unsigned char *cmdBuf[MAX_SCREENS_SAVED];
1843 unsigned int maxHintsSize[MAX_SCREENS_SAVED];
1844 unsigned int actHintsSize[MAX_SCREENS_SAVED];
1845 unsigned int numHints[MAX_SCREENS_SAVED];
1846 unsigned int maxCmdSize[MAX_SCREENS_SAVED];
1847 unsigned int actCmdSize[MAX_SCREENS_SAVED];
1848 unsigned int numCmd[MAX_SCREENS_SAVED];
1849 unsigned int maxRemoteSize[MAX_SCREENS_SAVED];
1852 * Initialize the buffers and their sizes to null and 0. Because of
1853 * all possible combinations - buffers aren't malloc'd until they're
1856 for(i = 0;i<smGD.numSavedScreens;i++)
1860 remoteBuf[i] = NULL;
1861 maxHintsSize[i] = 0;
1862 actHintsSize[i] = 0;
1867 maxRemoteSize[i] = 0;
1868 actRemoteSize[i] = 0;
1872 * Save the contents of the DISPLAY environment variable so that it
1873 * can be restored when we're through
1875 dispEnv = getenv(DISPLAY_NAME);
1878 dispSav = (char *) SM_MALLOC(((strlen(dispEnv) +
1879 strlen(DISPLAY_NAME_EQUAL)) * sizeof(char) + 1));
1880 sprintf(dispSav, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
1888 displayName = strdup(smGD.display->display_name);
1889 remoteDisplay = (unsigned char *)
1890 SM_MALLOC(sizeof(unsigned char) * (strlen(displayName) + 101));
1893 * Create the display name for locally executing clients
1919 * Create the display name for remotely executing clients.
1920 * These two may or may not be the same
1922 DtGetShortHostname((char *)remoteDisplay, 100);
1925 * Add the display qualifications to the host name
1926 * screen is added at execution time
1928 strcat((char *)remoteDisplay, (char *)dispPtr);
1931 * Intern the atom needed to put the hints on the root window
1932 * This has to be done here because InitProtocol has not been called yet
1934 XaWmDtHints = XInternAtom(smGD.display, _XA_DT_SESSION_HINTS, False);
1936 while(GetNextLine() != NULL)
1939 string = GetSmartString(&lineP);
1940 if( string != NULL && !strcmp((char *)string, "dtsmcmd"))
1942 while((string = GetSmartString(&lineP)) != NULL )
1944 if(!strcmp((char *)string, "-host"))
1947 * Extract a host pointer - host pointers
1948 * only exist on remote executions
1950 string = GetSmartString(&lineP);
1955 if(!strcmp((char *)string, "-cmd"))
1958 * Extract the command pointer from the
1961 string = GetSmartString(&lineP);
1966 if(!strcmp((char *)string, "-screen"))
1969 * Extract the screen number from the command
1971 string = GetSmartString(&lineP);
1972 screenNum = atoi((char *)string);
1977 if(!strcmp((char *)string, "-hints"))
1980 * Extract the hints string
1982 string = GetSmartString(&lineP);
1991 * Now put our information in buffers and reinitialize the pointers
1995 if(FillHintBuf(hintPtr, hintsBuf, maxHintsSize,
1996 actHintsSize, screenNum, numHints) != 0)
1999 * Free all malloc'd buffers and exit
2001 for(i = 0;i < smGD.numSavedScreens;i++)
2003 if(actHintsSize[i] > 0)
2005 SM_FREE((char *) hintsBuf[i]);
2007 if(actCmdSize[i] > 0)
2009 SM_FREE((char *) cmdBuf[i]);
2011 if(actRemoteSize[i] > 0)
2013 SM_FREE((char *) remoteBuf[i]);
2022 if((cmdPtr != NULL) && (hostPtr == NULL))
2024 if(FillCmdBuf(cmdPtr, cmdBuf, maxCmdSize,
2025 actCmdSize,screenNum, &numCmd[screenNum]) != 0)
2028 * Free all malloc'd buffers and exit
2030 for(i = 0;i < smGD.numSavedScreens;i++)
2032 if(actHintsSize[i] > 0)
2034 SM_FREE((char *) hintsBuf[i]);
2036 if(actCmdSize[i] > 0)
2038 SM_FREE((char *) cmdBuf[i]);
2040 if(actRemoteSize[i] > 0)
2042 SM_FREE((char *) remoteBuf[i]);
2051 if((cmdPtr != NULL) && (hostPtr != NULL))
2053 if(FillRemoteBuf(cmdPtr, hostPtr, remoteDisplay,
2054 remoteBuf, maxRemoteSize,
2055 actRemoteSize, screenNum) != 0)
2058 * Free all malloc'd buffers and exit
2060 for(i = 0;i < smGD.numSavedScreens;i++)
2062 if(actHintsSize[i] > 0)
2064 SM_FREE((char *) hintsBuf[i]);
2066 if(actCmdSize[i] > 0)
2068 SM_FREE((char *) cmdBuf[i]);
2070 if(actRemoteSize[i] > 0)
2072 SM_FREE((char *) remoteBuf[i]);
2082 screenNum = XDefaultScreen(smGD.display);
2087 * All done with file so close it off and set descriptor to NULL -
2088 * This is done so that parsing routines can be used with a buffer later
2094 * Now execute all the buffers, put all hints on the root windows
2095 * Do all remote executions
2097 for(i = 0;i < smGD.numSavedScreens;i++)
2100 * Put the root window property on each root window
2102 if(actHintsSize[i] > 0)
2105 * Append number of hints to front of buffer
2107 sprintf((char *)tmpChar, "%d", numHints[i]);
2108 strncpy((char *)hintsBuf[i], (char *)tmpChar,
2109 strlen((char *)tmpChar));
2110 XChangeProperty(smGD.display, RootWindow(smGD.display, i),
2111 XaWmDtHints, XA_STRING, 8, PropModeReplace,
2112 hintsBuf[i], actHintsSize[i]);
2113 SM_FREE((char *) hintsBuf[i]);
2114 XSync(smGD.display, 0);
2122 * Now exec on the local clients - we're doing contention management
2123 * to make sure the system doesn't get swamped
2127 while((actCmdSize[i] == 0) && (i < smGD.numSavedScreens))
2132 envVal = SM_MALLOC(BUFSIZ);
2133 if(i >= smGD.numSavedScreens)
2139 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2147 * Keep forking one client after the other until the
2148 * memory utilization gets beyond the threshold -
2149 * (but only if the capability exists) Then go to
2150 * window manager handshaking
2152 #ifdef DEBUG_CONT_MANAGEMENT
2153 if(smRes.contManagement & SM_CM_SYSTEM)
2155 fprintf(stderr, "SM_CM_SYSTEM flag set in smRes.contManagement\n");
2157 if(smRes.contManagement & SM_CM_HANDSHAKE)
2159 fprintf(stderr, "SM_CM_HANDSHAKE flag set in smRes.contManagement\n");
2161 #endif /* DEBUG_CONT */
2163 if((smRes.contManagement & SM_CM_SYSTEM) &&
2164 ((GetMemoryUtilization() != MEM_NOT_AVAILABLE) &&
2165 (clientsDone == False)))
2167 while((GetMemoryUtilization() == MEM_NOT_FULL) &&
2168 (clientsDone == False))
2172 CreateExecString((char *) lineP);
2173 if(smExecArray[0] != NULL)
2175 (void) StartClient(smExecArray[0], (char **)smExecArray, NULL,
2176 NULL, NULL, False, False, -1);
2181 * When all the clients have been exec'd for this screen
2184 if(numClientsExec >= numCmd[i])
2186 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2187 envVal, displayName);
2194 * After we've checked memory utilization - finish up
2195 * by handshaking with the worksapce manager - if it's there
2197 if(clientsDone == False)
2199 if((smGD.dtwmRunning) && (smRes.contManagement & SM_CM_HANDSHAKE))
2202 * Get the window id of the workspace manager and tell it
2203 * to start messaging
2205 _DtGetMwmWindow(smGD.display, RootWindow(smGD.display, 0),
2207 smToWmMessage.type = ClientMessage;
2208 smToWmMessage.window = dtwmWin;
2209 smToWmMessage.message_type = XaSmWmProtocol;
2210 smToWmMessage.format = 32;
2211 smToWmMessage.data.l[0] = XaSmStartAckWindow;
2212 smToWmMessage.data.l[1] = CurrentTime;
2213 if (XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2214 (XEvent *) &smToWmMessage) != 0)
2217 XSync(smGD.display, 0);
2223 * Start a client - and wait for the workspace manager to
2224 * map a window to start a new client
2226 while(clientsDone == False)
2230 CreateExecString((char *) lineP);
2231 if(smExecArray[0] != NULL)
2233 (void) StartClient(smExecArray[0], smExecArray,
2234 NULL, NULL, NULL, False, False, -1);
2238 * If we're handshaking with the workspace manager
2239 * wait for the client to be mapped before starting
2242 if(wmHandshake == True)
2250 * When all the clients have been exec'd for this screen
2253 if(numClientsExec >= numCmd[i])
2255 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2256 envVal, displayName);
2261 if(wmHandshake == True)
2264 * If we are handshaking - tell the workspace manager to
2267 smToWmMessage.type = ClientMessage;
2268 smToWmMessage.window = dtwmWin;
2269 smToWmMessage.message_type = XaSmWmProtocol;
2270 smToWmMessage.format = 32;
2271 smToWmMessage.data.l[0] = XaSmStopAckWindow;
2272 smToWmMessage.data.l[0] = CurrentTime;
2273 XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2274 (XEvent *) &smToWmMessage);
2279 for(i = 0;i < smGD.numSavedScreens;i++)
2281 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2287 * Send out all the remote execution commands for the screen to
2288 * the command invoker. On failure - do a remsh instead
2290 if(actRemoteSize[i] > 0)
2293 * Initialize the command invoker - if not done
2295 if(cmdInvInit == False)
2297 _DtInitializeCommandInvoker(smGD.display,
2305 * Set up the display environment variable so that the
2306 * application comes back to the right screen
2308 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2312 parseP = remoteBuf[i];
2313 while(numRemoteExecs > 0 && GetNextLine() != NULL)
2316 * Get the host and the command and send them off
2317 * On failure of the command invoker do a remsh
2320 string = GetSmartString(&lineP);
2322 string = GetSmartString(&lineP);
2325 remoteBufPtr[numRemoteDone].cmdPtr = cmdPtr;
2326 remoteBufPtr[numRemoteDone].hostPtr = hostPtr;
2328 _DtCommandInvokerExecute(DtSTART_SESSION, NULL, NULL, NULL,
2329 "-", (char *) hostPtr, (char *) cmdPtr,
2330 RemoteRequestSucceeded, NULL,
2331 RemoteRequestFailed,
2332 &remoteBufPtr[numRemoteDone]);
2336 * If there is no more room in the remote client
2337 * array - quit exec'ing remote clients
2339 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2341 PrintError(DtError, GETMESSAGE(16, 5, "You have reached the maximum allowed number of remote clients. No further remote clients will be restored."));
2351 * Now return the display variable back to the display that was
2352 * originally opened (the default display)
2360 FixEnvironmentData();
2365 } /* END OF FUNCTION RestoreClients */
2369 /*************************************<->*************************************
2371 * StartEtc ( exiting )
2376 * Call the StartClient routine to fork and exec either the sessionetc file
2377 * (if exiting==False) or the sessionexit file (if exiting==True).
2389 *************************************<->***********************************/
2391 StartEtc( Boolean exiting )
2398 execArray[0] = smGD.exitPath;
2399 execArray[1] = smExitFile;
2401 execArray[0] = smGD.etcPath;
2402 execArray[1] = smEtcFile;
2404 execArray[2] = '\0';
2406 if ((status=stat(execArray[0], &buf)) != -1)
2408 StartClient(execArray[0], execArray, NULL, NULL, NULL, False, False, -1);
2413 /*************************************<->*************************************
2420 * Returns the next line from an fopened configuration file or a newline-
2421 * embedded configuration string.
2426 * cfileP = (global) file pointer to fopened configuration file or NULL
2427 * line = (global) line buffer
2428 * linec = (global) line count
2429 * parseP = (global) parse string pointer if cfileP == NULL
2434 * line = (global) next line
2435 * linec = (global) line count incremented
2436 * parseP = (global) parse string pointer incremented
2437 * Return = line or NULL if file or string is exhausted.
2442 * If there are more than MAXLINE characters on a line in the file cfileP the
2443 * excess are truncated.
2444 * Assumes the line buffer is long enough for any parse string line.
2445 * Code stolen from dtmwm
2447 *************************************<->***********************************/
2448 static unsigned char *
2451 unsigned char *string;
2457 /* read fopened file */
2459 string = (unsigned char *) fgets((char *)line, fileSize, cfileP);
2461 else if ((parseP != NULL) && (*parseP != 0))
2462 /* read parse string */
2466 while ((*parseP != 0) &&
2467 ((chlen = mblen ((char *) parseP, MB_CUR_MAX)) > 0) &&
2469 /* copy all but NULL and newlines to line buffer */
2473 *(string++) = *(parseP++);
2477 while ((*parseP != NULL) && (*parseP != '\n'))
2478 /* copy all but NULL and newlines to line buffer */
2480 *(string++) = *(parseP++);
2484 if (*parseP == '\n')
2497 } /* END OF FUNCTION GetNextLine */
2501 /*************************************<->*************************************
2503 * PeekAhead (currentChar, currentLev)
2508 * Returns a new level value if this is a new nesting level of quoted string
2509 * Otherwise it returns a zero
2514 * currentChar = current position in the string
2515 * currentLev = current level of nesting
2520 * Returns either a new level of nesting or zero if the character is copied in
2526 *************************************<->***********************************/
2529 unsigned char *currentChar,
2530 unsigned int currentLev )
2532 Boolean done = False;
2533 unsigned int tmpLev = 1;
2537 while (((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) &&
2538 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
2543 if(((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
2544 ((*currentChar == '"') || (*currentChar == '\\')))
2547 if(*currentChar == '"')
2558 while((*currentChar != NULL) && (done == False) &&
2559 ((*currentChar == '"') || (*currentChar == '\\')))
2562 if((*currentChar != NULL) &&
2563 ((*currentChar == '"') || (*currentChar == '\\')))
2566 if(*currentChar == '"')
2576 #endif /*MULTIBYTE*/
2579 * Figure out if this is truly a new level of nesting - else ignore it
2580 * This section probably could do some error checking and return -1
2581 * If so, change type of routine from unsigned int to int
2595 /*************************************<->*************************************
2597 * GetSmartString (linePP)
2602 * Returns the next quoted or whitespace-terminated nonquoted string in the
2604 * Additional functionality added to GetString in that anything in a
2605 * quoted string is considered sacred and nothing will be stripped from
2606 * the middle of a quoted string.
2611 * linePP = pointer to current line buffer pointer.
2616 * linePP = pointer to revised line buffer pointer.
2622 * May alter the line buffer contents.
2623 * Handles quoted strings and characters, removing trailing whitespace from
2625 * Returns NULL string if the line is empty or is a comment.
2626 * Code stolen from dtmwm.
2628 *************************************<->***********************************/
2630 static unsigned char *
2632 unsigned char **linePP )
2634 unsigned char *lineP = *linePP;
2635 unsigned char *endP;
2636 unsigned char *curP;
2637 unsigned char *lnwsP;
2638 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
2642 /* get rid of leading white space */
2643 ScanWhitespace (&lineP);
2646 * Return NULL if line is empty, whitespace, or begins with a comment.
2648 if((chlen = mblen ((char *) lineP, MB_CUR_MAX)) < 1)
2654 if ((chlen == 1) && (*lineP == '"'))
2657 quoteLevel[level] = 1;
2659 * Start beyond double quote and find the end of the quoted string.
2660 * '\' quotes the next character - but is not stripped out.
2661 * Otherwise, matching double quote or NULL terminates the string.
2663 * We use lnwsP to point to the last non-whitespace character in the
2664 * quoted string. When we have found the end of the quoted string,
2665 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2666 * This removes any trailing whitespace without overwriting the
2667 * matching quote, needed later. If the quoted string was all
2668 * whitespace, then this will write a NULL at the beginning of the
2669 * string that will be returned -- OK.
2671 lnwsP = lineP++; /* lnwsP points to first '"' */
2672 curP = endP = lineP; /* other pointers point beyond */
2674 while ((*endP = *curP) &&
2675 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2676 ((chlen > 1) || (*curP != '"')))
2677 /* Haven't found matching quote yet.
2678 * First byte of next character has been copied to endP.
2682 if ((chlen == 1) && (*endP == '\\') &&
2683 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2686 * Check to see if this is a quoted quote - if it is
2687 * strip off a level - if not - it's sacred leave it alone
2689 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2692 if(quoteLevel[level] >= checkLev)
2694 if (level > 0) level--;
2696 else if (level < MAX_QUOTE_DEPTH)
2699 quoteLevel[level] = checkLev;
2702 for(i = 0;i < (checkLev - 2);i++)
2704 *endP++ = *curP++;curP++;
2711 /* Singlebyte character: character copy finished. */
2713 if (isspace (*endP))
2714 /* whitespace character: leave lnwsP unchanged. */
2719 /* non-whitespace character: point lnwsP to it. */
2725 /* Multibyte (nonwhitespace) character: point lnwsP to it.
2726 * Finish character byte copy.
2739 /* get rid of leading white space */
2740 ScanWhitespace (&lineP);
2742 /* Return NULL if line is empty, or whitespace */
2752 quoteLevel[level] = 1;
2754 * Start beyond double quote and find the end of the quoted string.
2755 * '\' quotes the next character.
2756 * Otherwise, matching double quote or NULL terminates the string.
2758 * We use lnwsP to point to the last non-whitespace character in the
2759 * quoted string. When we have found the end of the quoted string,
2760 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2761 * This removes any trailing whitespace without overwriting the
2762 * matching quote, needed later. If the quoted string was all
2763 * whitespace, then this will write a NULL at the beginning of the
2764 * string that will be returned -- OK.
2766 lnwsP = lineP++; /* lnwsP points to first '"' */
2767 curP = endP = lineP; /* other pointers point beyond */
2769 while ((*endP = *curP) && (*endP != '"'))
2770 /* haven't found matching quote yet */
2772 /* point curP to next character */
2774 if ((*endP == '\\') && (*curP != NULL))
2775 /* shift quoted nonNULL character down and curP ahead */
2778 * Check to see if this is a quoted quote - if it is
2779 * strip off a level - if not - it's sacred leave it alone
2781 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2784 if(quoteLevel[level] >= checkLev)
2786 if (level > 0) level--;
2788 else if (level < MAX_QUOTE_DEPTH)
2791 quoteLevel[level] = checkLev;
2794 for(i = 0;i < (checkLev - 2);i++)
2796 *endP++ = *curP++;curP++;
2802 if (isspace (*endP))
2803 /* whitespace character: leave lnwsP unchanged. */
2808 /* non-whitespace character: point lnwsP to it. */
2816 * Found matching quote or NULL.
2817 * NULL out any trailing whitespace.
2828 /* Unquoted string */
2831 * Find the end of the nonquoted string.
2832 * '\' quotes the next character.
2833 * Otherwise, whitespace, NULL, terminates the string.
2835 curP = endP = lineP;
2838 while ((*endP = *curP) &&
2839 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2840 ((chlen > 1) || (!isspace (*curP))))
2841 /* Haven't found whitespace yet.
2842 * First byte of next character has been copied to endP.
2846 if ((chlen == 1) && (*endP == '\\') &&
2847 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2849 * copy first byte of quoted nonNULL character down.
2850 * point curP to next byte
2857 /* Multibyte character: finish character copy. */
2866 while ((*endP = *curP) && !isspace (*endP))
2868 /* point curP to next character */
2870 if ((*endP == '\\') && (*curP != NULL))
2871 /* shift quoted nonNULL character down and curP ahead */
2881 * Two cases for *endP:
2883 * matching quote -> write NULL over char and point beyond
2884 * NULL -> point to NULL
2889 *endP = 0; /* write NULL over terminator */
2890 *linePP = ++curP; /* point beyond terminator */
2896 return ((unsigned char *)lineP);
2898 } /* END OF FUNCTION GetString */
2903 /*************************************<->*************************************
2905 * ScanWhitespace(linePP)
2910 * Scan the string, skipping over all white space characters.
2915 * linePP = nonNULL pointer to current line buffer pointer
2920 * linePP = nonNULL pointer to revised line buffer pointer
2925 * Assumes linePP is nonNULL
2926 * Code Stolen from dtmwm
2928 *************************************<->***********************************/
2931 unsigned char **linePP )
2934 while (*linePP && (mblen ((char *) *linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
2936 while (*linePP && isspace (**linePP))
2942 } /* END OF FUNCTION ScanWhitespace */
2946 /*************************************<->*************************************
2948 * FillHintBuf(newHint, hintBuf, maxSize, actSize, screen, numHints)
2953 * Put the new hint into the hint buffer. Each hint is separated by a
2959 * newHint = hint to add to the buffer
2960 * hintBuf = an array of buffers - one for each screen
2961 * maxSize = array of buffers of the current malloced size of each hintBuf
2962 * actSize = array of space currently used by each hintBuf
2963 * screen = screen number for this hint
2964 * numHints = array of the number of hints for each screen
2965 * smGD.numSavedScreens = (global) checked to make sure this hint should be
2970 * hintBuf[screen] = updated hint buf for this screen (newHint added)
2971 * maxSize[screen] = enlarged if not big enough or malloced if not done before
2972 * actSize[screen] = updated size of the hints buffer
2973 * numHints[screen] = updated by 1 if this hint is added
2979 *************************************<->***********************************/
2982 unsigned char *newHint,
2983 unsigned char **hintBuf,
2984 unsigned int *maxSize,
2985 unsigned int *actSize,
2986 unsigned int screen,
2987 unsigned int *numHints)
2989 static int hintBufSize = 5000;
2992 * If the screen that this hint was meant for is not in the current
2993 * set of available screens, don't save it
2995 if(screen >= smGD.numSavedScreens)
3001 * Check to see if this buffer has been malloc'd before - if it hasn't
3002 * malloc it. If it has - check to make sure it's big enough to hold the
3005 if(maxSize[screen] == 0)
3007 hintBuf[screen] = (unsigned char *) SM_MALLOC(hintBufSize * sizeof(char));
3008 if(hintBuf[screen] == NULL)
3010 actSize[screen] = 0;
3011 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3014 maxSize[screen] = hintBufSize * sizeof(char);
3017 * Now reserve 4 bytes for the length
3019 strcpy((char *)hintBuf[screen], " \n");
3023 if((actSize[screen] + strlen((char *)newHint) + 2) >= maxSize[screen])
3025 hintBuf[screen] = (unsigned char *)
3026 SM_REALLOC((char *) hintBuf[screen],
3030 if(hintBuf[screen] == NULL)
3032 actSize[screen] = 0;
3033 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3036 maxSize[screen] = maxSize[screen] + (hintBufSize * sizeof(char));
3041 * add the new hint AFTER the last newline
3043 strcat((char *)hintBuf[screen], (char *)newHint);
3044 strcat((char *)hintBuf[screen], "\n");
3045 actSize[screen] = strlen((char *)hintBuf[screen]);
3046 numHints[screen] += 1;
3053 /*************************************<->*************************************
3055 * FillCmdBuf(newCmd, cmdBuf, maxSize, actSize, screen)
3060 * Put a new command into the command buffer. The command buffer is just
3061 * one big long string of stuff to be executed.
3066 * newCmd = command to add to the buffer
3067 * cmdBuf = an array of buffers - one for each screen
3068 * maxSize = array of buffers of the current malloced size of each cmdBuf
3069 * actSize = array of space currently used by each cmdBuf
3070 * screen = screen number for this command
3071 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3076 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3077 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3078 * actSize[screen] = updated size of the command buffer
3084 *************************************<->***********************************/
3087 unsigned char *newCmd,
3088 unsigned char **cmdBuf,
3089 unsigned int *maxSize,
3090 unsigned int *actSize,
3091 unsigned int screen,
3092 unsigned int *numCmd )
3094 static int cmdBufSize = 5000;
3097 * If the screen that this command was meant for is not in the current
3098 * set of available screens, don't save it
3100 if(screen >= smGD.numSavedScreens)
3106 * Check to see if this buffer has been malloc'd before - if it hasn't
3107 * malloc it. If it has - check to make sure it's big enough to hold the
3110 if(maxSize[screen] == 0)
3112 cmdBuf[screen] = (unsigned char *) SM_MALLOC(cmdBufSize * sizeof(char));
3113 if(cmdBuf[screen] == NULL)
3115 actSize[screen] = 0;
3116 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3119 maxSize[screen] = cmdBufSize * sizeof(char);
3123 if((actSize[screen] + strlen((char *)newCmd)) >= maxSize[screen])
3125 cmdBuf[screen] = (unsigned char *) SM_REALLOC((char *)cmdBuf[screen],
3129 if(cmdBuf[screen] == NULL)
3131 actSize[screen] = 0;
3132 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3135 maxSize[screen] = maxSize[screen] + (cmdBufSize * sizeof(char));
3139 if(actSize[screen] == 0)
3141 strcpy((char *)cmdBuf[screen], (char *)newCmd);
3145 strcat((char *)cmdBuf[screen], (char *)newCmd);
3148 *numCmd = *numCmd + 1;
3149 strcat((char *)cmdBuf[screen], "\n");
3150 actSize[screen] = strlen((char *)cmdBuf[screen]);
3157 /*************************************<->*************************************
3159 * FillRemoteBuf(newCmd, hostName, displayName, remoteBuf,
3160 * maxSize, actSize, screen)
3165 * Put a new command into the remote execution buffer. The command buffer is
3166 * just one big long string of stuff to be executed.
3171 * newCmd = command to add to the buffer
3172 * hostName = host where command is to be executed from
3173 * displayName = display where host is to be executed to
3174 * remoteBuf = an array of buffers - one for each screen
3175 * maxSize = array of buffers of the current malloced size of each cmdBuf
3176 * actSize = array of space currently used by each cmdBuf
3177 * screen = screen number for this command
3178 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3183 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3184 * in remote format (host name and display name)
3185 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3186 * actSize[screen] = updated size of the command buffer
3192 *************************************<->***********************************/
3195 unsigned char *newCmd,
3196 unsigned char *hostName,
3197 unsigned char *displayName,
3198 unsigned char *remoteBuf[] ,
3199 unsigned int *maxSize ,
3200 unsigned int *actSize ,
3201 unsigned int screen )
3203 unsigned char *string;
3204 static int remoteBufSize = 5000;
3207 * If the screen that this command was meant for is not in the current
3208 * set of available screens, don't save it
3210 if(screen >= smGD.numSavedScreens)
3216 * Check to see if this buffer has been malloc'd before - if it hasn't
3217 * malloc it. If it has - check to make sure it's big enough to hold the
3220 if(maxSize[screen] == 0)
3222 remoteBuf[screen] = (unsigned char *)
3223 SM_MALLOC(remoteBufSize * sizeof(char));
3224 if(remoteBuf[screen] == NULL)
3226 actSize[screen] = 0;
3227 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3230 maxSize[screen] = remoteBufSize * sizeof(char);
3234 if((actSize[screen] + strlen((char *)newCmd) +
3235 strlen((char *)hostName) +
3236 strlen((char *)displayName) +
3237 strlen("-display ") + 5) >= maxSize[screen])
3239 remoteBuf[screen] = (unsigned char *)
3240 SM_REALLOC((char *)remoteBuf[screen],
3242 (remoteBufSize * sizeof(char)));
3243 if(remoteBuf[screen] == NULL)
3245 actSize[screen] = 0;
3246 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3249 maxSize[screen] = maxSize[screen] + (remoteBufSize * sizeof(char));
3253 if(actSize[screen] == 0)
3256 * If the buffer is empty fill it with the initial contents
3258 strcpy((char *)remoteBuf[screen], (char *)hostName);
3259 strcat((char *)remoteBuf[screen], " ");
3264 * if this buffer is not emtpy
3265 * add the new command BEFORE the last null terminator
3266 * Commands for remote executions are separated by newlines
3268 strcat((char *)remoteBuf[screen], "\n");
3269 strcat((char *)remoteBuf[screen], (char *)hostName);
3273 * Copy the command in - quote it
3275 strcat((char *)remoteBuf[screen], " \"");
3276 string = GetSmartString(&newCmd);
3277 strcat((char *)remoteBuf[screen], (char *)string);
3278 strcat((char *)remoteBuf[screen], " ");
3281 * Once display name has been put in place - concatenate the
3282 * rest of the command
3284 while((string = GetSmartString(&newCmd)) != NULL )
3286 strcat((char *)remoteBuf[screen], " ");
3287 strcat((char *)remoteBuf[screen], (char *)string);
3291 * Now close off the command with a quote
3293 strcat((char *)remoteBuf[screen], "\"");
3295 actSize[screen] = strlen((char *)remoteBuf[screen]);
3298 * Bump the remote command counter
3306 /*************************************<->*************************************
3308 * CreateExecString(execString)
3313 * Create a string that can be fed to a fork and exec by breaking it up
3314 * into argc and argv
3319 * execString = whole command
3323 * smExecArray = global modified to contain pointers to argc and argv
3329 *************************************<->***********************************/
3337 static int iSizeArgv = ARG_AMT;
3342 if (smExecArray == NULL)
3344 smExecArray = (char **) XtMalloc (ARG_AMT * sizeof(char *));
3346 string = (char *) GetSmartString((unsigned char **) &execString);
3347 while(string != NULL)
3349 smExecArray[argc] = string;
3351 if (argc >= iSizeArgv)
3353 iSizeArgv += ARG_AMT;
3354 smExecArray = (char **)
3355 XtRealloc ((char *)smExecArray, (iSizeArgv * sizeof(char *)));
3357 string = (char *) GetSmartString((unsigned char **) &execString);
3361 * If the last string is a background character
3366 if(!strcmp((char *)smExecArray[argc - 1], "&"))
3368 smExecArray[argc - 1] = '\0';
3372 smExecArray[argc] = '\0';
3374 } /* END OF FUNCTION CreateExecString */
3378 * SetTemporaryDisplay - does a putenv of the current value of the
3379 * DISPLAY environment variable but with the given screen number.
3385 SetTemporaryDisplay (
3388 static char * tmpDisplay = NULL;
3389 static int lastScreen = -1;
3392 if (screenNum == -1)
3395 if (!savedDisplay) {
3398 if ((dispEnv = getenv (DISPLAY_NAME)) == NULL)
3400 savedDisplay = XtMalloc (strlen (DISPLAY_NAME_EQUAL) +
3401 strlen (dispEnv) + 2);
3404 sprintf (savedDisplay, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
3407 if (lastScreen == screenNum && tmpDisplay != NULL) {
3408 putenv (tmpDisplay);
3411 lastScreen = screenNum;
3416 tmpDisplay = XtMalloc (strlen (savedDisplay) + 4);
3419 strcpy (tmpDisplay, savedDisplay);
3422 if (pch = strrchr (tmpDisplay, ':')) {
3425 if (pch2 = strchr (pch, '.'))
3427 pch3 = XtMalloc (strlen (tmpDisplay) + 4);
3430 sprintf (pch3, "%s.%d", tmpDisplay, screenNum);
3431 strcpy (tmpDisplay, pch3);
3432 XtFree ((char *) pch3);
3434 putenv (tmpDisplay);
3440 * RestoreDisplay - does a putenv of the global variable savedDisplay
3446 if (screenNum != -1 && savedDisplay)
3447 putenv (savedDisplay);
3451 /*************************************<->*************************************
3453 * StartClient - calls StartLocalClient or StartRemoteClient depending
3454 * on the value of hostName.
3458 * Starts a local or remote application
3462 * program = execArray[0]
3463 * execArray = command to fork and exec
3464 * hostName = the name of the host where program should be executed
3465 * cwd = directory to chdir to before doing the exec
3466 * envp = the envrironment variables to add to the child processes env
3467 * checkCwd = if True and cwd is NULL, a message will be logged; if
3468 * False, cwd will not be checked and the cwd will be set to $HOME
3469 * useIgnoreEnvironmentResource = if True, the variables listed in the
3470 * IgnoreEnvironment resource will be removed from 'environ' before
3471 * execArray is exec'd
3472 * screen = if set to -1, it will be ignored; otherwise, the screen
3473 * number will be used to define DISPLAY for the duration of this
3474 * function - DISPLAY will be reset before the function returns.
3478 * Returns True if the command is successfully executed; False otherwise.
3482 * localHost - is modified
3484 *************************************<->***********************************/
3493 Boolean useIgnoreEnvironmentResource,
3496 static char * defaultCwd = NULL;
3497 Boolean cwdNull = False;
3498 Boolean startStatus;
3500 SetTemporaryDisplay (screen);
3502 if (!ignoreEnvPtr && useIgnoreEnvironmentResource) {
3503 if (smRes.ignoreEnvironment)
3504 ignoreEnvPtr = _DtVectorizeInPlace (
3505 smRes.ignoreEnvironment, ',');
3510 char *tstr = getenv("HOME");
3513 int slen = strlen(tstr) + 1;
3514 defaultCwd = XtCalloc(1, slen);
3515 strncpy(defaultCwd, tstr, slen - 1);
3518 defaultCwd = getcwd (NULL, MAXPATHLEN + 1);
3520 (void) gethostname (localHost, MAXHOSTNAMELEN);
3528 if (!hostName || (_DtIsSameHost (localHost, hostName)))
3529 startStatus = StartLocalClient (program, execArray,
3530 cwd, envp, checkCwd,
3531 useIgnoreEnvironmentResource);
3533 startStatus = StartRemoteClient (program, execArray, hostName,
3535 useIgnoreEnvironmentResource);
3537 RestoreDisplay (screen);
3539 return (startStatus);
3542 /*************************************<->*************************************
3548 * Starts a local application.
3551 * Returns True if the command is successfully executed; False otherwise.
3553 *************************************<->***********************************/
3561 Boolean useIgnoreEnvironmentResource)
3565 char clientMessage[MAXPATHLEN + 30];
3566 char **tmpEnv, **ppchar;
3569 * Fork and exec the client process
3571 clientFork = vfork();
3574 * If the fork fails - Send out an error and return
3578 PrintErrnoError(DtError, smNLS.cantForkClientString);
3583 * Fork succeeded - now do the exec
3587 SetSIGPIPEToDefault ();
3590 * Log a warning if the given cwd is not valid
3594 if ((chdir (cwd)) == -1)
3598 tmpCwd = getcwd (NULL, MAXPATHLEN + 1);
3600 LogCWDMessage (cwd, program, tmpCwd);
3605 * Add envp to the client's environ if the variable
3606 * is not in the ignoreEnvironment list
3608 if (useIgnoreEnvironmentResource && envp) {
3611 tmpEnv = RemoveEnvironmentVars (envp);
3615 for (ppchar = tmpEnv; ppchar && *ppchar; ppchar++)
3616 putenv (strdup (*ppchar));
3621 * Set the gid of the process back from bin
3624 setregid(smGD.runningGID, smGD.runningGID);
3626 setgid(smGD.runningGID);
3627 setegid(smGD.runningGID);
3631 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3633 #if defined(__osf__) || defined(CSRG_BASED)
3637 #endif /* __osf__ */
3639 MarkFileDescriptors (3, F_SETFD, 1);
3641 execStatus = execvp(program, execArray);
3644 sprintf(clientMessage, ((char *)GETMESSAGE(16, 3, "Unable to exec %s.")), execArray[0]);
3645 PrintErrnoError(DtError, clientMessage);
3653 /*************************************<->*************************************
3659 * Starts a remote application.
3662 * Returns True if the command is successfully executed; False otherwise.
3664 *************************************<->***********************************/
3672 Boolean useIgnoreEnvironmentResource)
3675 SPC_Channel_Ptr channel;
3677 char errorMessage[1024];
3679 static Boolean cmdInvokerInitialized = False;
3680 char ** tmpEnv = envp;
3682 ioMode = SPCIO_NOIO | SPCIO_FORCE_CONTEXT;
3684 if (!cmdInvokerInitialized) {
3685 _DtInitializeCommandInvoker(smGD.display,
3689 cmdInvokerInitialized = True;
3692 (void) strcpy (errorMessage, "");
3694 channel = (SPC_Channel_Ptr) _DtSPCOpen (hostName, ioMode, errorMessage);
3695 if (channel == SPC_ERROR) {
3696 message = strdup ((char *) GETMESSAGE (40, 13,
3697 "The following application cannot be started on host '%s'\nbecause this host cannot be reached from host '%s':\n\n %s"));
3700 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3701 message, hostName, localHost, program);
3707 netfile = tt_host_file_netfile (hostName, cwd);
3708 if (tt_pointer_error (netfile) != TT_OK) {
3710 message = strdup ((char *) GETMESSAGE (40, 14,
3711 "An attempt to start application '%s'\non host '%s' failed because the following directory\ncould not be translated into cannonical form:\n\n %s\n\n[%s]"));
3714 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3715 message, program, hostName, cwd,
3716 tt_status_message (tt_pointer_error (
3724 * Add envp to the client's environ if the variable
3725 * is not in the ignoreEnvironment list
3727 if (useIgnoreEnvironmentResource && ignoreEnvPtr && envp)
3728 tmpEnv = RemoveEnvironmentVars (envp);
3730 if ((_DtSPCSpawn (program, netfile, execArray, tmpEnv, channel,
3731 hostName, NULL, cwd, errorMessage)) == SPC_ERROR) {
3732 DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMessage);
3734 XtFree ((char *) tmpEnv);
3740 XtFree ((char *) tmpEnv);
3746 /*************************************<->*************************************
3753 * Fork and exec the default window manager
3766 *************************************<->***********************************/
3775 * These lines were added to support the builtin
3780 char *displayName,*dpy;
3782 hostName = SM_MALLOC(MAXPATHSM);
3783 displayName = SM_MALLOC(MAXPATHSM);
3785 if( gethostname(hostName, (sizeof(hostName) - 1) ) == 0)
3787 hostName[MAXPATHSM - 1] = '\0';
3788 dpy = getenv(DISPLAY_NAME);
3789 homeDir = getenv("HOME");
3792 strcpy(displayName, dpy);
3793 dpy = strchr(displayName, ':');
3798 sprintf(tmpExecWmFile, "%s/.dt/bin/%s/%s/dtwm", homeDir,
3799 hostName,displayName);
3800 if (access(tmpExecWmFile,X_OK) != 0)
3802 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3806 localWmLaunched = True;
3807 if (!smGD.userSetWaitWmTimeout)
3809 smRes.waitWmTimeout = 60000;
3815 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3820 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3824 SM_FREE(displayName);
3826 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3827 * End of lines were added to support the builtin
3831 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3836 * Fork and exec the client process
3838 clientFork = vfork();
3841 * If the fork fails - Send out an error and return
3845 PrintErrnoError(DtError, smNLS.cantForkClientString);
3850 * Fork succeeded - now do the exec
3854 SetSIGPIPEToDefault ();
3858 * Set the gid of the process back from bin
3861 setregid(smGD.runningGID, smGD.runningGID);
3863 setgid(smGD.runningGID);
3864 setegid(smGD.runningGID);
3867 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3869 #if defined(__osf__) || defined(CSRG_BASED)
3873 #endif /* __osf__ */
3875 MarkFileDescriptors (3, F_SETFD, 1);
3878 * These lines were added to support the builtin
3881 * execStatus = execlp(".../dt/bin/dtwm", "dtwm", (char *) 0);
3884 execStatus = execlp(tmpExecWmFile, "dtwm", (char *) 0);
3887 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3888 * End of lines were added to support the builtin
3892 if(execStatus != 0 && (!localWmLaunched))
3894 PrintErrnoError(DtError, GETMESSAGE(16, 4, "Unable to exec process /usr/dt/bin/dtwm. No window manager will be started."));
3901 /*************************************<->*************************************
3908 * Fork a copy of ourselves and kill the parent off so that scripts starting
3909 * up the session manager can continue.
3921 *************************************<->***********************************/
3929 * Fork and exec the client process
3931 clientFork = fork();
3934 * If the fork fails - We have to exit so that the rest of the
3935 * script can continue
3939 PrintErrnoError(DtError, smNLS.cantForkClientString);
3944 * Fork succeeded - now kill the parent
3952 * Disassociate from parent
3954 #if defined(__osf__) || defined(CSRG_BASED)
3958 #endif /* __osf__ */
3963 /*************************************<->*************************************
3970 * This routine waits for the window manager to start. It uses a
3971 * resource (waitWmTimeout) with a dynamic default to determine how many
3972 * seconds to wait for WM start and then starts clients.
3977 * appContext = application context for the window
3978 * window = window id for the
3987 *************************************<->***********************************/
3992 XtIntervalId wmTimerId;
3994 XtAddEventHandler(smGD.topLevelWid,
3997 (XtEventHandler)HandleWMClientMessage,
4001 * Set a timer which stops the block on waiting for the
4002 * window manager to start
4005 wmTimerId = XtAppAddTimeOut(smGD.appCon,
4006 smRes.waitWmTimeout,
4007 WaitWMTimeout, NULL);
4009 while((smGD.dtwmRunning == False) && (wmTimeout == False))
4011 XtAppProcessEvent(smGD.appCon, XtIMAll);
4014 XtRemoveTimeOut(wmTimerId);
4015 XtRemoveEventHandler(smGD.topLevelWid,
4018 (XtEventHandler)HandleWMClientMessage,
4022 } /* END OF FUNCTION WaitForWM */
4025 /*************************************<->*************************************
4032 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
4033 * for the window manager to get started.
4042 * wmTimeout = (global) flag that stops the loop
4047 *************************************<->***********************************/
4050 XtPointer client_data,
4055 } /* END OF FUNCTION WaitWMTimeout */
4059 /*************************************<->*************************************
4061 * HandleWMClientMessage
4066 * This is the event handler registered to receive the client message
4067 * from dtwm when dtwm is ready for business
4070 *************************************<->***********************************/
4072 HandleWMClientMessage( Widget smWidget,
4076 if (event->type == ClientMessage)
4078 ProcessClientMessage(event);
4081 } /* END OF FUNCTION HandleWMClientMessage */
4086 /*************************************<->*************************************
4088 * FixEnvironmentData
4093 * If DISPLAY variable exists in the environment - remove it
4102 * wmTimeout = (global) flag that stops the loop
4107 *************************************<->***********************************/
4109 FixEnvironmentData( void )
4113 extern char **environ; /* MODIFIED - DISPLAY is remove if found. */
4115 for (i=0, ppchar = environ; *ppchar; ppchar++, i++)
4117 if ((strncmp (*ppchar, DISPLAY_NAME_EQUAL, strlen(DISPLAY_NAME_EQUAL))) == 0)
4120 * Change the DISPLAY environment variable.
4122 for (; *ppchar; ppchar++, i++)
4124 environ[i]=environ[i+1];
4133 /*************************************<->*************************************
4140 * After one screen is finished - set up the info for the next
4145 * cmdBuf - Buffer that holds all the invocation information
4146 * screen - Pointer to the screen number that we're currently working on
4147 * env - used to set up the environment for changing the display var
4148 * displayName - name of the current display
4152 * cmdBuf - old buffers are freed
4153 * screen - updated to point to the new screen info
4154 * done - tells whether the clients are done being exec'd
4155 * linec - *GLOBAL* sets line being read from
4161 *************************************<->***********************************/
4163 ResetScreenInfo(unsigned char **cmdBuf,
4165 unsigned int *cmdSize,
4170 SM_FREE((char *) cmdBuf[*screen]);
4172 while((cmdSize[*screen] == 0) && (*screen < smGD.numSavedScreens))
4177 if(*screen >= smGD.numSavedScreens)
4183 sprintf((char *)env,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, *screen);
4187 parseP = cmdBuf[*screen];
4193 /*************************************<->*************************************
4195 * RemoteRequestFailed ()
4200 * If a request to the command invoker fails, this callback will be called.
4201 * It will then try to execute the command by performing a remsh on it.
4214 *************************************<->***********************************/
4216 RemoteRequestFailed(char *message,
4219 static char *cmdBuf = NULL;
4220 static char *tmpCmdBuf = NULL;
4221 char *errorString = NULL;
4224 static int cmdBufSize = 0;
4227 RemoteReq *tmpReq = (RemoteReq *) client_data;
4230 * If the memory for the buffer has not been malloced - do so
4234 cmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4237 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4240 cmdBufSize = 200 + 1;
4242 tmpCmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4243 if(tmpCmdBuf == NULL)
4245 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4250 * Copy in the host and command field and execute the command
4253 tmpSize = (strlen(REMOTE_CMD_STRING) +
4254 strlen((char *) tmpReq->hostPtr) +
4255 strlen((char *) tmpReq->cmdPtr) + 1);
4257 if(tmpSize >= cmdBufSize)
4259 cmdBuf = SM_REALLOC(cmdBuf, (tmpSize) * sizeof(char));
4263 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4267 cmdBufSize = tmpSize;
4269 if(tmpCmdBuf != NULL)
4271 tmpCmdBuf = SM_REALLOC(tmpCmdBuf, (tmpSize) * sizeof(char));
4272 if(tmpCmdBuf == NULL)
4274 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4279 sprintf(cmdBuf, REMOTE_CMD_STRING, tmpReq->hostPtr, tmpReq->cmdPtr);
4282 * save cmdBuf for error message, cmdBuf is changed
4283 * by CreateExecString
4285 if (tmpCmdBuf != NULL)
4287 strcpy(tmpCmdBuf,cmdBuf);
4290 CreateExecString(cmdBuf);
4291 if(smExecArray[0] != NULL)
4293 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
4294 NULL, False, False, -1);
4296 if (tmpCmdBuf != NULL)
4298 tmpString = GETMESSAGE(16, 8,
4299 "An attempt to restore the following\ncommand (using the DT remote execution process)\non host \"%s\" failed:\n\n %s\n\nThe following execution string will be tried:\n\n %s\n\n");
4302 (char *)SM_MALLOC((strlen(tmpString) +
4303 strlen((char *)tmpReq->hostPtr) +
4304 strlen((char *)tmpReq->cmdPtr) +
4305 strlen(tmpCmdBuf) + 1 ) *
4308 if(errorString == NULL)
4310 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4314 sprintf(errorString, tmpString, tmpReq->hostPtr,
4315 tmpReq->cmdPtr, tmpCmdBuf );
4316 PrintError(DtError, errorString);
4317 SM_FREE(errorString);
4322 * Now check to make sure that this isn't the last remote request.
4323 * If so, free the data
4327 if(numRemoteExecs == 0)
4329 for(i = 0;i < smGD.numSavedScreens;i++)
4331 if(actRemoteSize[i] > 0)
4333 SM_FREE((char *) remoteBuf[i]);
4343 /*************************************<->*************************************
4345 * RemoteRequestSucceeded ()
4350 * If a request to the command invoker succeeds, this callback will be called.
4351 * It decrements the remote execution counter, and frees the info if
4352 * remote executions are finished
4365 *************************************<->***********************************/
4367 RemoteRequestSucceeded(char *message,
4374 if(numRemoteExecs == 0)
4376 for(i = 0;i < smGD.numSavedScreens;i++)
4378 if(actRemoteSize[i] > 0)
4380 SM_FREE((char *) remoteBuf[i]);
4386 /**************************************************************************
4390 **************************************************************************/
4394 char * databaseName)
4397 XSMPClientDBRecPtr pXSMPRec;
4398 ProxyClientDBRecPtr pProxyRec;
4403 if ((inputDB = OpenInputClientDB (databaseName,
4405 &smXSMP.dbSessionId)) == NULL) {
4406 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogError, 1);
4410 if (!smXSMP.dbVersion) {
4411 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 2);
4412 smXSMP.dbVersion = SM_VENDOR_NAME;
4415 if (!smXSMP.dbSessionId) {
4416 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 3);
4417 smXSMP.dbSessionId = SM_RELEASE_NAME;
4421 * First start the XSMP clients
4425 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4428 if (!CheckRequiredProperties (pXSMPRec, databaseName)) {
4429 FreeXSMPClientDBRec (pXSMPRec);
4433 if (StartXSMPClient (pXSMPRec, databaseName)) {
4435 XSMPClientDBRecPtr tmpRecPtr;
4437 pXSMPRec->next = NULL;
4439 if (!smXSMP.xsmpDbList) {
4440 smXSMP.xsmpDbList = pXSMPRec;
4445 * Find the end of the list
4447 for (tmpRecPtr = smXSMP.xsmpDbList;
4448 tmpRecPtr && tmpRecPtr->next != NULL;
4449 tmpRecPtr = tmpRecPtr->next);
4451 tmpRecPtr->next = pXSMPRec;
4454 FreeXSMPClientDBRec (pXSMPRec);
4458 * Now start the Proxy clients
4460 for (i = 0; ; i++) {
4462 if ((pProxyRec = GetProxyClientDBRec (inputDB)) == NULL)
4465 if (!CheckRequiredFields (pProxyRec, databaseName, i)) {
4466 FreeProxyClientDBRec (pProxyRec);
4470 (void) StartProxyClient (pProxyRec);
4472 FreeProxyClientDBRec (pProxyRec);
4475 (void) CloseClientDB (inputDB, False);
4483 XSMPClientDBRecPtr pDbRec,
4484 char * databaseName)
4486 return (StartClient (pDbRec->restartCommand[0],
4487 pDbRec->restartCommand,
4490 pDbRec->environment,
4493 pDbRec->screenNum));
4499 ProxyClientDBRecPtr pDbRec)
4501 return (StartClient (pDbRec->command[0],
4508 pDbRec->screenNum));
4513 ExecuteCommandProperty (
4515 ClientRecPtr pClientRec)
4518 char ** envp = NULL;
4520 PropertyRecPtr pPropRec;
4524 if ((pPropRec = GetPropertyRec (pClientRec, commandName)) == NULL)
4527 argv = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4532 for (i = 0; i < pPropRec->prop.num_vals; i++)
4533 argv[i] = pPropRec->prop.vals[i].value;
4534 argv[pPropRec->prop.num_vals] = NULL;
4536 cwd = GetArrayPropertyValue (pClientRec, SmCurrentDirectory);
4539 if ((pPropRec = GetPropertyRec (pClientRec, SmEnvironment)) != NULL) {
4540 envp = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4545 for (i = 0; i < pPropRec->prop.num_vals; i++)
4546 envp[i] = pPropRec->prop.vals[i].value;
4547 envp[pPropRec->prop.num_vals] = NULL;
4550 retValue = StartClient (argv[0], argv,
4551 pClientRec->clientHost,
4554 pClientRec->screenNum);
4556 XtFree ((char *) argv);
4558 XtFree ((char *) envp);
4564 /*************************************<->*************************************
4566 * ExecuteDiscardCommands -
4568 * Description: Executes all of the DiscardCommand properties in the
4569 * given client database
4573 *************************************<->***********************************/
4575 ExecuteDiscardCommands (
4579 XSMPClientDBRecPtr pXSMPRec;
4580 char * version = NULL;
4584 if ((inputDB = OpenInputClientDB (db, &version, &id )) == NULL) {
4585 str = strdup ((char *) GETMESSAGE (40, 26,
4586 "The following client database cannot be opened:\n\n %s\n\nThe 'DiscardCommand' properties cannot be run."));
4589 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str, db);
4595 XtFree ((char *) version);
4597 XtFree ((char *) id);
4600 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4603 if (!pXSMPRec->discardCommand)
4606 if (!StartClient (pXSMPRec->discardCommand[0],
4607 pXSMPRec->discardCommand,
4608 pXSMPRec->clientHost,
4610 pXSMPRec->environment,
4613 pXSMPRec->screenNum)) {
4614 str = strdup ((char *) GETMESSAGE (40, 27,
4615 "An attempt to execute the 'DiscardCommand' property for\napplication '%s' failed."));
4618 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
4623 FreeXSMPClientDBRec (pXSMPRec);
4626 (void) CloseClientDB (inputDB, False);
4631 CheckRequiredProperties (
4632 XSMPClientDBRecPtr pDbRec,
4633 char * databaseName)
4635 Boolean propsOK = True;
4637 if (!pDbRec->program) {
4638 LogMissingPropertyMessage (pDbRec, SmProgram,
4639 databaseName, DtMsgLogError);
4643 if (!pDbRec->restartCommand) {
4644 LogMissingPropertyMessage (pDbRec, SmRestartCommand,
4645 databaseName, DtMsgLogError);
4654 CheckRequiredFields (
4655 ProxyClientDBRecPtr pDbRec,
4656 char * databaseName,
4661 if (!pDbRec->command) {
4663 message = strdup ((char *) GETMESSAGE (40, 11,
4664 "The required resource '%s' is missing for client '%d'\nin the file '%s'."));
4669 DtMsgLogMessage (smGD.programName, DtMsgLogError, message,
4670 SmProgram, clientNum, databaseName);
4682 LogXSMPOpenDatabaseFailure (
4683 char * databaseName,
4684 DtMsgLogType msgType,
4687 char * message = NULL;
4692 case 1: data = databaseName;
4694 message = strdup ((char *) GETMESSAGE (40, msgNum,
4695 "The following session database could not be opened:\n\n '%s'"));
4698 case 2: data = versionStr;
4700 message = strdup ((char *) GETMESSAGE (40, msgNum,
4701 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4704 case 3: data = dtsessionIDStr;
4706 message = strdup ((char *) GETMESSAGE (40, msgNum,
4707 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4715 DtMsgLogMessage (smGD.programName, msgType, message, data);
4717 DtMsgLogMessage (smGD.programName, msgType, message,
4718 data, databaseName);
4725 LogMissingPropertyMessage (
4726 XSMPClientDBRecPtr pDbRec,
4728 char * databaseName,
4729 DtMsgLogType msgType)
4733 message = strdup ((char *) GETMESSAGE (40, 10,
4734 "The required property '%s' is missing for client\n\n %s\n\nin the file '%s'."));
4739 DtMsgLogMessage (smGD.programName, msgType, message,
4740 propName, pDbRec->clientId, databaseName);
4754 message = strdup ((char *) GETMESSAGE (40, 12,
4755 "The directory '%s'\nis not available for application '%s'.\n\nThe following directory will be used:\n\n %s"));
4760 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, message,
4761 badDir, appName, goodDir);
4768 char ** RemoveEnvironmentVars (
4772 char ** retEnv = NULL;
4773 char **ppchar, **ppchar2;
4780 for (count = 0, ppchar = envp; ppchar && *ppchar; count++, ppchar++) ;
4782 retEnv = (char **) XtMalloc ((count + 1) * sizeof (char *));
4786 if (!ignoreEnvPtr) {
4787 for (count = 0, ppchar = envp; ppchar && *ppchar;
4788 count++, ppchar++) {
4789 retEnv[count] = *ppchar;
4791 retEnv[count] = NULL;
4796 for (count = 0, ppchar = envp; ppchar && *ppchar; ppchar++) {
4800 for (ppchar2 = ignoreEnvPtr; ppchar2 && *ppchar2; ppchar2++) {
4802 if ((!strncmp (*ppchar, *ppchar2, strlen (*ppchar2))) &&
4803 (((*ppchar)[strlen(*ppchar2)]) == '=')) {
4809 retEnv[count] = *ppchar;
4813 retEnv[count] = NULL;
4819 * MarkFileDescriptors - mark file descriptiors start_fd through open_max
4820 * with the given "cmd" and "data".
4822 * The code for calculating open_max was taken from DtSvc/DtUtil1/CmdMain.c
4825 MarkFileDescriptors (
4833 open_max = sysconf(_SC_OPEN_MAX);
4835 if (open_max == -1) {
4839 #if defined(USL) || defined(__uxp__) || defined(_AIX)
4840 open_max = FOPEN_MAX;
4842 open_max = FD_SETSIZE;
4844 #endif /* _SUN_OS */
4847 for (i = start_fd; i < open_max; i++)
4848 (void) fcntl (i, cmd, data);