1 /* $TOG: SmRestore.c /main/26 1998/12/14 20:13:07 mgreess $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
4 * (c) Copyright 1993, 1994 International Business Machines Corp. *
5 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
6 * (c) Copyright 1993, 1994 Novell, Inc. *
8 /*************************************<+>*************************************
9 *****************************************************************************
13 ** Project: HP DT Session Manager (dtsession)
17 ** This file contains functions that are in charge of restoring state.
18 ** When the session manager is first started, it restores the state that
19 ** was either last saved (home state), or last exited (current state). The
20 ** state restored depends on values the user has configured.
24 *******************************************************************
25 ** (c) Copyright Hewlett-Packard Company, 1990. All rights are
26 ** reserved. Copying or other reproduction of this program
27 ** except for archival purposes is prohibited without prior
28 ** written consent of Hewlett-Packard Company.
29 ********************************************************************
33 *****************************************************************************
34 *************************************<+>*************************************/
39 #ifdef _SUN_OS /* to get the define for NOFILE */
40 #include <sys/param.h>
42 #include <sys/types.h>
45 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
47 #include <sys/socket.h>
48 #include <netinet/in.h>
53 #include <X11/Intrinsic.h>
54 #include <X11/Xutil.h>
55 #include <X11/Xatom.h>
56 #include <X11/StringDefs.h>
57 #include <X11/keysymdef.h>
58 #include <X11/SM/SMlib.h>
62 # define Va_start(a,b) va_start(a,b)
65 #include <Dt/Message.h>
66 #include <Dt/CommandM.h>
67 #include <Dt/Connect.h>
70 #include <Dt/UserMsg.h>
71 #include <Dt/SessionM.h>
72 #include <Dt/EnvControlP.h>
73 #include <Dt/Utility.h>
74 #include <Dt/MsgLog.h>
76 #include <Dt/CmdInv.h>
79 #include "SmResource.h"
82 #include "SmRestore.h"
83 #include "SmProtocol.h"
84 #include "SmConMgmt.h"
87 #include "SmGlobals.h"
93 #include <X11/Xlibint.h>
99 static const char * DISPLAY_NAME_EQUAL = "DISPLAY=";
100 static const char * DISPLAY_NAME = "DISPLAY";
101 static char * savedDisplay = NULL;
107 #define MAXPATHSM 1023
108 #define MAX_QUOTE_DEPTH 10
110 #define SM_MAX_ARGS MAXLINE
112 #if defined (SVR4) || defined (__osf__)
113 #define REMOTE_CMD_STRING "rsh %s -n %s &"
115 #define REMOTE_CMD_STRING "remsh %s -n %s &"
124 unsigned char *hostPtr;
125 unsigned char *cmdPtr;
129 * Variables global to this module only
131 static XtResource settingsResources[] =
133 {SmNaccelNum, SmCaccelNum, XtRInt, sizeof(int),
134 XtOffset(SessionSettingsPtr, accelNum),
135 XtRImmediate, (XtPointer) -1},
136 {SmNaccelDenom, SmCaccelDenom, XtRInt, sizeof(int),
137 XtOffset(SessionSettingsPtr, accelDenom),
138 XtRImmediate, (XtPointer) -1},
139 {SmNthreshold, SmCthreshold, XtRInt, sizeof(int),
140 XtOffset(SessionSettingsPtr, threshold),
141 XtRImmediate, (XtPointer) -1},
143 {SmNtimeout, SmCtimeout, XtRInt, sizeof(int),
144 XtOffset(SessionSettingsPtr, timeout),
145 XtRImmediate, (XtPointer) -1},
146 {SmNinterval, SmCinterval, XtRInt, sizeof(int),
147 XtOffset(SessionSettingsPtr, interval),
148 XtRImmediate, (XtPointer) -1},
149 {SmNpreferBlank, SmCpreferBlank, XtRInt, sizeof(int),
150 XtOffset(SessionSettingsPtr, preferBlank),
151 XtRImmediate, (XtPointer) 0},
152 {SmNallowExp, SmCallowExp, XtRInt, sizeof(int),
153 XtOffset(SessionSettingsPtr, allowExp),
154 XtRImmediate, (XtPointer) 0},
156 {SmNfontPath, SmCfontPath, XtRString, sizeof(String),
157 XtOffset(SessionSettingsPtr, fontDirs), XtRString, (XtPointer) ""},
159 {SmNkeyClick, SmCkeyClick, XtRInt, sizeof(int),
160 XtOffset(SessionSettingsPtr, kbdState.key_click_percent),
161 XtRImmediate, (XtPointer) -1},
162 {SmNbellPercent, SmCbellPercent, XtRInt, sizeof(int),
163 XtOffset(SessionSettingsPtr, kbdState.bell_percent),
164 XtRImmediate, (XtPointer) -1},
165 {SmNbellPitch, SmCbellPitch, XtRInt, sizeof(int),
166 XtOffset(SessionSettingsPtr, kbdState.bell_pitch),
167 XtRImmediate, (XtPointer) -1},
168 {SmNbellDuration, SmCbellDuration, XtRInt, sizeof(int),
169 XtOffset(SessionSettingsPtr, kbdState.bell_duration),
170 XtRImmediate, (XtPointer) -1},
171 {SmNledMask, SmCledMask, XtRInt, sizeof(int),
172 XtOffset(SessionSettingsPtr, kbdState.led_mask),
173 XtRImmediate, (XtPointer) 0},
174 {SmNglobalRepeats, SmCglobalRepeats, XtRInt, sizeof(int),
175 XtOffset(SessionSettingsPtr, kbdState.global_auto_repeat),
176 XtRImmediate, (XtPointer) 2},
177 {SmNautoRepeats, SmCautoRepeats, XtRString, sizeof(String),
178 XtOffset(SessionSettingsPtr, autoRepeats), XtRString, (XtPointer) ""},
180 {SmNbuttonMap, SmCbuttonMap, XtRString, sizeof(String),
181 XtOffset(SessionSettingsPtr, buttonMap), XtRString, (XtPointer) ""},
183 {SmNnumKeyCode, SmCnumKeyCode, XtRInt, sizeof(int),
184 XtOffset(SessionSettingsPtr, numKeyCode), XtRImmediate, (XtPointer) 0},
185 {SmNkeySymsPerKey, SmCkeySymsPerKey, XtRInt, sizeof(int),
186 XtOffset(SessionSettingsPtr, keySymPerCode),
187 XtRImmediate, (XtPointer) 0},
188 {SmNkeySyms, SmCkeySyms, XtRString, sizeof(String),
189 XtOffset(SessionSettingsPtr, keySyms), XtRString, (XtPointer) ""},
191 {SmNmaxKeyPerMod, SmCmaxKeyPerMod, XtRInt, sizeof(int),
192 XtOffset(SessionSettingsPtr, maxKeyPerMod),
193 XtRImmediate, (XtPointer) 0},
194 {SmNmodMap, SmCmodMap, XtRString, sizeof(String),
195 XtOffset(SessionSettingsPtr, modSyms),
196 XtRString, (XtPointer) ""},
198 {SmNdidQuerySettings, SmCdidQuerySettings, XtRBoolean, sizeof(Boolean),
199 XtOffset(SessionSettingsPtr, didQuery),
200 XtRImmediate, (XtPointer) False},
201 {SmNshutDownState, SmCshutDownState, XtRInt, sizeof(int),
202 XtOffset(SessionSettingsPtr, confirmMode),
203 XtRImmediate, (XtPointer) 1},
204 {SmNshutDownMode, SmCshutDownMode, XtRInt, sizeof(int),
205 XtOffset(SessionSettingsPtr, startState),
206 XtRImmediate, (XtPointer) 4},
210 * Variables used for parsing code
213 static unsigned char fallBackLine[MAXLINE+2]; /* line buffer */
214 static unsigned char *line; /* line buffer */
215 static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
216 static int linec = 0; /* line counter for parser */
217 static unsigned char *parseP = NULL; /* pointer to parse string */
218 static int fileSize = 0;
219 char **smExecArray = NULL;
222 * Variables used for remote execution
224 static int numRemoteExecs = 0;
225 unsigned char *remoteBuf[MAX_SCREENS_SAVED];
226 unsigned int actRemoteSize[MAX_SCREENS_SAVED];
227 RemoteReq remoteBufPtr[MAX_REMOTE_CLIENTS];
228 static char localHost[MAXHOSTNAMELEN];
229 static char ** ignoreEnvPtr = NULL;
232 * Timeout for workspace manager handshake
234 static Boolean wmTimeout;
237 * These lines were added to support the builtin
241 char tmpExecWmFile[MAXPATHSM+1];
242 static Boolean localWmLaunched = False;
245 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
246 * End of lines were added to support the builtin
261 "*XmTextField*FontList",
262 "*DtEditor*textFontList",
267 static char *fontclass[] = {
275 "*XmTextField*FontList",
276 "*DtEditor*textFontList",
285 static int RestoreSettings( void ) ;
286 static int RestoreClients( void ) ;
287 static unsigned char * GetNextLine( void ) ;
288 static unsigned int PeekAhead( unsigned char *, unsigned int ) ;
289 static unsigned char * GetSmartString( unsigned char **) ;
290 static void ForkWM( void ) ;
291 static int FillCmdBuf( unsigned char *, unsigned char **,
292 unsigned int *, unsigned int *,
293 unsigned int, unsigned int *) ;
294 static int FillRemoteBuf( unsigned char *, unsigned char *,
295 unsigned char *, unsigned char **,
296 unsigned int *, unsigned int *, unsigned int) ;
297 static int FillHintBuf(unsigned char *, unsigned char **,
298 unsigned int *, unsigned int *,
299 unsigned int, unsigned int *);
300 static void WaitForWM( void ) ;
301 static void HandleWMClientMessage(Widget smWidget, XtPointer dummy,
303 static void WaitWMTimeout( XtPointer , XtIntervalId *) ;
304 static void FixEnvironmentData( void ) ;
305 static void ResetScreenInfo(unsigned char **,
306 int *, unsigned int *,
309 static void RemoteRequestFailed(char *, void *);
310 static void RemoteRequestSucceeded(char *, void *);
312 static void SetTemporaryDisplay (
315 static void RestoreDisplay (
318 static Boolean StartLocalClient (
324 Boolean useIgnoreEnvResource);
326 static Boolean StartRemoteClient (
332 Boolean useIgnoreEnvResource);
334 static Boolean CheckRequiredProperties (
335 XSMPClientDBRecPtr pDbRec,
336 char * databaseName);
338 static Boolean CheckRequiredFields (
339 ProxyClientDBRecPtr pDbRec,
343 static void LogXSMPOpenDatabaseFailure (
345 DtMsgLogType msgType,
348 static void LogMissingPropertyMessage (
349 XSMPClientDBRecPtr pDbRec,
352 DtMsgLogType msgType);
354 static void LogCWDMessage (
359 static char ** RemoveEnvironmentVars (
362 static void MarkFileDescriptors (
368 /*************************************<->*************************************
375 * Sets _DT_SM_STATE_INFO for dtstyle indicating compatibility mode
388 * The only thing dtstyle should be looking at is the compatMode
390 *************************************<->***********************************/
392 SetCompatState( void )
397 * BEFORE any clients are started
398 * set a property on the top level window
399 * which lets the style manager know what state the sm is in
401 state.flags = SM_STATE_ALL;
402 state.smStartState = 0;
403 state.smConfirmMode = 0;
404 state.smCompatMode = True;
405 state.smSendSettings = False;
406 state.smCoverScreen = True;
407 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
408 state.smCycleTimeout = 0;
409 state.smLockTimeout = 0;
410 state.smSaverTimeout = 0;
412 state.smDisplaySpecific = smGD.displaySpecific;
414 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
416 XFlush(smGD.display);
420 } /* END OF FUNCTION SetCompatState */
423 /*************************************<->*************************************
430 * This function fiddles with our signal handling and calls the
431 * system() function to invoke a unix command.
436 * pchCmd = string with the command we want to exec.
444 * The system() command is touchy about the SIGCLD behavior. Restore
445 * the default SIGCLD handler during the time we run system().
447 *************************************<->***********************************/
450 SystemCmd (char *pchCmd)
452 void (*signalHandler) ();
454 signalHandler = (void (*)())signal (SIGCLD, SIG_DFL);
458 signal (SIGCLD, signalHandler);
459 } /* END OF FUNTION SystemCmd */
463 /*************************************<->*************************************
479 * When this routine is finished, all settings and resources will be restored.
480 * Clients may not be, as they are actually restored by different processes.
482 *************************************<->***********************************/
488 char convertCommand[MAXPATHSM+1];
490 Boolean fixedBuffer = False;
493 Boolean useXrmDB = False;
496 * Restore all the X settings which were active at the time of shutdown
500 if (smGD.sessionType == HOME_SESSION)
501 smSettings.startState = DtSM_HOME_STATE;
503 smSettings.startState = DtSM_CURRENT_STATE;
506 * BEFORE any clients are started
507 * set a property on the top level window
508 * which lets the style manager know what state the sm is in
510 state.flags = SM_STATE_ALL;
511 state.smStartState = smSettings.startState;
512 state.smConfirmMode = smSettings.confirmMode;
513 state.smCompatMode = smGD.compatMode;
514 state.smSendSettings = !smRes.querySettings;
515 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
516 state.smCycleTimeout = smSaverRes.cycleTimeout;
517 state.smLockTimeout = smSaverRes.lockTimeout;
518 state.smSaverTimeout = smSaverRes.saverTimeout;
519 state.smRandom = smSaverRes.random;
520 state.smDisplaySpecific = smGD.displaySpecific;
522 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
524 saver.saverList = smGD.saverList;
525 _DtSetSmSaver(smGD.display, smGD.topLevelWindow, &saver);
528 * Set up the Property telling all applications what session is being
531 XaSmRestoreMode = XInternAtom(smGD.display, _XA_DT_RESTORE_MODE, False);
532 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
533 XaSmRestoreMode, XA_STRING, 8, PropModeReplace,
534 (unsigned char *)smGD.restoreSession, strlen(smGD.restoreSession));
535 XFlush(smGD.display);
538 * Check the session database and either parse it as an
539 * Xrm-database or the CDE1.0 format
541 if ((pchar = strrchr (smGD.clientPath, '/')) != NULL)
544 if ((*pchar != '\0') && (!strcmp (pchar, SM_CLIENT_FILE2)))
550 return (StartXSMPSession (smGD.clientPath));
554 * Malloc line for parsing.
556 status = stat(smGD.clientPath, &buf);
559 fileSize = buf.st_size;
562 if (fileSize < MAXLINE + 1)
564 fileSize = MAXLINE + 1;
567 line = (unsigned char *) malloc ((fileSize + 1) * sizeof(char *));
571 fileSize = MAXLINE + 1;
574 cfileP = fopen(smGD.clientPath, "r");
577 PrintErrnoError(DtError, smNLS.cantOpenFileString);
578 if (!fixedBuffer && line)
580 SM_FREE((char *)line);
587 if (!fixedBuffer && line)
589 SM_FREE((char *)line);
598 /*************************************<->*************************************
605 * Start up the window manager. The default is to start dtmwm unless
606 * another one is specified in a resource.
619 * When this routine is finished, all settings and resources will be restored.
620 * Clients may not be, as they are actually restored by different processes.
622 *************************************<->***********************************/
626 char wmStartupErrorString[(2 * MAXPATHSM) + 1];
627 char localWmErrorString[(2 * MAXPATHSM) + 1];
628 Boolean goodWmStartup = True;
631 if((smGD.wmStartup == NULL) || (*smGD.wmStartup == NULL))
637 CreateExecString(smGD.wmStartup);
640 * check to see if the wmStartup string exists and is
643 status = access(smExecArray[0], F_OK | X_OK);
646 goodWmStartup = False;
647 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
650 if(smExecArray[0] != NULL)
652 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
653 NULL, False, False, -1);
658 * We used to start the message server before the window
659 * manager and then if the message server did not start
660 * we would exit. Now we start the window manager, then
661 * start the message server and then wait for the window
662 * manager. This seems to improve performance.
667 if (goodWmStartup == False)
669 sprintf(wmStartupErrorString, GETMESSAGE(16, 7,
670 "The wmStartupCommand resource is set to:\n\n"
672 "This file does not exist or is not executable.\n"
673 CDE_INSTALLATION_TOP "/bin/dtwm will be started "
676 PrintError(DtError, wmStartupErrorString);
682 * These lines were added to support the builtin
686 if (localWmLaunched && wmTimeout)
688 if (!smGD.userSetWaitWmTimeout)
690 smRes.waitWmTimeout = smGD.savedWaitWmTimeout;
693 localWmLaunched = False;
695 * A special version of a built-in Xterminal dtwm
696 * was attempted and failed.
697 * Try to launch .../dt/bin/dtwm instead
700 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
701 if(smExecArray[0] != NULL)
703 (void) StartClient(smExecArray[0], smExecArray, NULL,
704 NULL, NULL, False, False, -1);
707 sprintf(localWmErrorString, GETMESSAGE(16, 9,
708 "The following window manager did not start:\n\n"
710 "This message indicates you tried to start a\n"
711 "window manager that is built into an X terminal.\n"
712 "This will only work with X terminals that support this protocol.\n"
713 CDE_INSTALLATION_TOP "/bin/dtwm will be started instead.\n"),
715 PrintError(DtError, localWmErrorString);
718 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
719 * End of lines were added to support the builtin
728 /*************************************<->*************************************
735 * Reloads RESOURCE_MANAGER during running session
747 *************************************<->***********************************/
750 ReloadResources(void)
753 * Load sys.resources and .Xdefaults
755 RestoreResources(True,
762 * Merge _DT_SM_PREFERENCES
764 RestorePreferences(NULL);
770 /*************************************<->*************************************
772 * RestoreResources (errorHandlerInstalled, options ... )
777 * Calls routines responsible for restoring resources.
778 * Resources are restored by a fork and exec of dtsession_res.
791 * When this routine is finished, all settings and resources will be restored.
792 * Clients may not be, as they are actually restored by different processes.
794 *************************************<->***********************************/
797 RestoreResources( Boolean errorHandlerInstalled, ... )
800 int childStatus, execStatus, i;
806 * Check for alternate resource loader.
808 if ((pgrm = getenv("DTLOADRESOURCES")) == NULL)
810 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
814 * By convention, exec() wants arg0 to be the program name. Ex: if pgrm
815 * is /usr/dt/bin/dtsession_res, the program name is dtsession_res.
816 * If all else fails, use pgrm.
818 argv[0] = (p = strrchr(pgrm, '/')) != NULL && *(p+1) != '\0' ? p+1 : pgrm;
821 Va_start(args,errorHandlerInstalled);
825 argv[i] = va_arg(args, char *);
831 * if an error handler is installed - remove it
833 if(errorHandlerInstalled)
835 sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
839 * Fork and exec the xrdb process to load in the file created by
840 * writing out the resource manager string generated by the last
841 * session termination.
844 for(i = 0;(i < 10) && ((forkrc = vfork()) < 0);i++)
855 PrintErrnoError(DtError, smNLS.cantForkClientString);
860 * Fork succeeded - now do the exec
864 SetSIGPIPEToDefault ();
868 * Set the gid of the process back from bin
871 setregid(smGD.runningGID, smGD.runningGID);
873 setgid(smGD.runningGID);
874 setegid(smGD.runningGID);
883 MarkFileDescriptors (3, F_SETFD, 1);
885 execStatus = execv(pgrm, argv);
889 char clientMessage[MAXPATHLEN + 256];
891 sprintf(clientMessage, ((char *)GETMESSAGE(16, 1, "Unable to exec process %s. No session resources will be restored.")), pgrm);
892 PrintErrnoError(DtError, clientMessage);
897 while(wait(&childStatus) != forkrc);
900 * if an error handler is installed - remove it
902 if(errorHandlerInstalled)
904 sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
911 /*************************************<->*************************************
913 * RestorePreferences ( filename)
919 * This routine has two roles:
921 * 1) If 'filename' specified, the content of filename is read, and
922 * _DT_SM_PREFERENCES is populated with its content. This is used
923 * at session startup to set the initial state of _DT_SM_PREFERENCES.
925 * 2) If 'filename' is NULL, the content of _DT_SM_PREFERENCES is
926 * merged into RESOURCE_MANAGER. This is used when resources are
927 * reloaded at user request during a session.
940 *************************************<->***********************************/
952 struct stat statinfo;
954 if(access(filename,R_OK) != 0)
960 * Determine size of file.
962 if (stat(filename, &statinfo) == -1)
970 if ((data = (char *)SM_MALLOC(statinfo.st_size + 1)) == NULL)
976 * Read file into memory.
978 if ((fp = fopen(filename, "r")) == NULL)
984 size = fread(data, 1, statinfo.st_size, fp);
986 if (size == statinfo.st_size)
989 * Merge .Xdefaults string into RESOURCE_MANAGER database, and
990 * also convert to Xrm database form for later subtraction.
993 _DtAddResString(smGD.display, data, _DT_ATR_PREFS);
1001 * Read string from _DT_SM_PREFERENCES
1003 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1006 * Merge string into RESOURCE_MANAGER
1008 _DtAddResString(smGD.display, data, _DT_ATR_RESMGR);
1017 /*************************************<->*************************************
1019 * RestoreSettings ()
1024 * In charge of restoring all settings. Settings are stored in resource
1025 * format so it gets the values by getting the resource values stored in
1026 * a resource file that was created by the session manager.
1031 * smGD.settingPath = path that points to the settings resource file.
1040 * This routine messes with the actual strings returned by the resource
1041 * manager by tokenizing them, so these session settings resources should
1042 * not be accessed again.
1044 *************************************<->***********************************/
1046 RestoreSettings( void )
1048 XrmDatabase smBase = NULL;
1049 XKeyboardControl kbdControl;
1051 char **restorePtrArray, **tmpRestore;
1052 char *restoreCharArray;
1053 int numArgs, ptrSize, charSize;
1056 KeySym *tmpSyms, codeSym;
1059 XModifierKeymap restoreMod;
1063 restorePtrArray = (char **) SM_MALLOC (ptrSize * sizeof(char *));
1064 restoreCharArray = (char *) SM_MALLOC (charSize * sizeof(char));
1065 if((restorePtrArray == NULL) || (restoreCharArray == NULL))
1067 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1069 if(restorePtrArray != NULL)
1071 SM_FREE((char *) restorePtrArray);
1075 if(restoreCharArray != NULL)
1077 SM_FREE(restoreCharArray);
1084 * Load the resources from the SM database file
1086 if (smGD.settingPath[0] != NULL)
1088 smBase = XrmGetFileDatabase(smGD.settingPath);
1092 PrintError(DtError, GETMESSAGE(16, 2, "Invalid client settings file. No settings restored."));
1097 XrmMergeDatabases(smBase, &(smGD.display->db));
1102 * Retrieve the session settings file from the database
1104 XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smSettings,
1105 settingsResources, XtNumber(settingsResources),
1109 * Copy any string resources since they may be overwritten in
1112 smGD.fontDirs = SmNewString(smSettings.fontDirs);
1113 smGD.autoRepeats = SmNewString(smSettings.autoRepeats);
1114 smGD.buttonMap = SmNewString(smSettings.buttonMap);
1115 smGD.keySyms = SmNewString(smSettings.keySyms);
1116 smGD.modSyms = SmNewString(smSettings.modSyms);
1120 * This is provided for backward compatibility sake. The values that
1121 * confirmMode can take have changed
1123 if(smSettings.confirmMode == DtSM_ASK_STATE)
1125 smSettings.confirmMode = DtSM_VERBOSE_MODE;
1129 * If the user has previously used the "query" method, and now wishes
1130 * to use "only what I've customized" method, then we have to start
1131 * from scratch. So don't set anything until customizer tells me to
1133 if((smSettings.didQuery == True) && (smRes.querySettings == False))
1135 SM_FREE((char *) restorePtrArray);
1136 SM_FREE(restoreCharArray);
1141 * Restore pointer control settings
1143 if((smSettings.accelNum > -1 ) || (smSettings.threshold > -1))
1145 XChangePointerControl(smGD.display, True, True,
1146 smSettings.accelNum,
1147 smSettings.accelDenom,
1148 smSettings.threshold);
1149 smToSet.pointerChange = True;
1153 smToSet.pointerChange = False;
1157 * Restore screen saver settings if any are set to non-default
1160 if ((smSettings.timeout > -1) || (smSettings.interval > -1) ||
1161 (smSaverRes.saverTimeout > -1) || (smSaverRes.lockTimeout > -1) ||
1162 (smSaverRes.cycleTimeout > -1))
1166 * For the time between Screen Savers, use the cycleTimeout
1167 * if the user has set this value. Otherwise, use the interval
1168 * value that was set when the session was saved.
1170 if (smSaverRes.cycleTimeout < 0)
1172 screenSaverVals.smInterval = smSettings.interval;
1176 screenSaverVals.smInterval = smSaverRes.cycleTimeout;
1180 * For the screen saver time, use the minimum of the values set for
1181 * saverTimeout or lockTimeout if the user has set one of these
1184 * Otherwise, use the Timeout value that was set when the
1185 * session was saved.
1187 * If it is not set, then use the minimum of the values set for
1188 * saverTimeout or lockTimeout. Set timeout to the Timeout value
1191 if ((smSaverRes.saverTimeout > -1) ||
1192 (smSaverRes.lockTimeout > -1))
1194 if (smSaverRes.saverTimeout > -1)
1196 if ((smSaverRes.lockTimeout > -1) &&
1197 (smSaverRes.lockTimeout < smSaverRes.saverTimeout))
1199 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1203 screenSaverVals.smTimeout = smSaverRes.saverTimeout;
1208 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1213 screenSaverVals.smTimeout = smSettings.timeout;
1215 screenSaverVals.smPreferBlank = smSettings.preferBlank;
1216 screenSaverVals.smAllowExp = smSettings.allowExp;
1218 /* Notify X of the new screen saver values */
1219 XSetScreenSaver(smGD.display, screenSaverVals.smTimeout,
1220 screenSaverVals.smInterval,
1221 screenSaverVals.smPreferBlank,
1222 screenSaverVals.smAllowExp);
1225 * If using timeout or interval values that were
1226 * previously saved, then set flag to indicate that they
1227 * should be saved again when the state for the session
1230 if ((smSettings.timeout > -1) || (smSettings.interval > -1))
1232 smToSet.screenSavChange = True;
1236 smToSet.screenSavChange = False;
1242 smToSet.screenSavChange = False;
1246 * Get the font path. Then set it.
1248 tmpRestore = restorePtrArray;
1250 *tmpRestore = strtok(smGD.fontDirs, ",");
1252 while(*tmpRestore != NULL)
1254 numArgs++; tmpRestore++;
1255 *tmpRestore = strtok(NULL, ",");
1256 if((numArgs >= ptrSize) && (*tmpRestore != NULL))
1259 restorePtrArray = (char **)SM_REALLOC((char *)
1260 restorePtrArray, ptrSize *
1262 if(restorePtrArray == NULL)
1264 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1265 SM_FREE(restoreCharArray);
1273 XSetFontPath(smGD.display, restorePtrArray, numArgs);
1277 * Restore the keyboard control information. In order for it
1278 * to be restored it has to be changed from a XKeyboardState
1279 * format to an XKeyboardControl format.
1281 if((smSettings.kbdState.key_click_percent > -1) ||
1282 (smSettings.kbdState.bell_percent > -1) ||
1283 (smSettings.kbdState.bell_pitch > -1) ||
1284 (smSettings.kbdState.bell_duration > -1))
1288 if((smSettings.kbdState.bell_percent > -1) ||
1289 (smSettings.kbdState.bell_pitch > -1) ||
1290 (smSettings.kbdState.bell_duration > -1))
1292 kbdControl.bell_percent = smSettings.kbdState.bell_percent;
1293 kbdControl.bell_pitch = smSettings.kbdState.bell_pitch;
1294 kbdControl.bell_duration = smSettings.kbdState.bell_duration;
1295 kbdControlMask |= (KBBellPercent | KBBellPitch | KBBellDuration);
1296 smToSet.audioChange = True;
1297 audioVals.smBellPercent = smSettings.kbdState.bell_percent;
1298 audioVals.smBellPitch = smSettings.kbdState.bell_pitch;
1299 audioVals.smBellDuration = smSettings.kbdState.bell_duration;
1303 smToSet.audioChange = False;
1306 if((smSettings.kbdState.key_click_percent > -1) ||
1307 (smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn))
1309 kbdControl.key_click_percent =
1310 smSettings.kbdState.key_click_percent;
1311 kbdControlMask |= KBKeyClickPercent;
1312 smToSet.keyboardChange = True;
1313 keyboardVals.smKeyClickPercent = kbdControl.key_click_percent;
1317 smToSet.keyboardChange = False;
1322 * NOTICE THAT THE LED'S DON'T GET RESET. THIS IS BECAUSE LED STUFF
1323 * IS MACHINE DEPENDENT.
1326 * Set the auto repeat stuff
1328 tmpKey = strtok(smGD.autoRepeats, ",");
1329 if((tmpKey == NULL) &&
1330 ((smSettings.kbdState.global_auto_repeat == AutoRepeatModeOff) ||
1331 (smSettings.kbdState.global_auto_repeat == AutoRepeatModeOn)))
1333 smToSet.keyboardChange = True;
1334 kbdControl.auto_repeat_mode =
1335 smSettings.kbdState.global_auto_repeat;
1336 kbdControlMask |= KBAutoRepeatMode;
1337 XChangeKeyboardControl(smGD.display, kbdControlMask, &kbdControl);
1338 keyboardVals.smGlobalAutoRepeat =
1339 smSettings.kbdState.global_auto_repeat;
1345 smToSet.keyboardChange = True;
1346 kbdControl.auto_repeat_mode = smSettings.kbdState.global_auto_repeat;
1347 kbdControlMask |= KBAutoRepeatMode;
1348 XChangeKeyboardControl(smGD.display,
1349 kbdControlMask, &kbdControl);
1350 kbdControl.auto_repeat_mode = AutoRepeatModeOn;
1351 kbdControlMask = KBAutoRepeatMode | KBKey;
1353 * This is only involked when there is auto repeats set for
1354 * specific keys only. It is VERY SLOW code so unless you
1355 * have to save off auto repeats for single keys - DONT
1357 while(tmpKey != NULL)
1359 kbdControl.key = atoi(tmpKey);
1360 XChangeKeyboardControl(smGD.display,
1361 kbdControlMask, &kbdControl);
1362 tmpKey = strtok(NULL, ",");
1367 if(kbdControlMask != 0)
1369 XChangeKeyboardControl(smGD.display,
1370 kbdControlMask, &kbdControl);
1377 smToSet.audioChange = False;
1378 smToSet.keyboardChange = False;
1382 * Restore the button mappings
1385 tmpKey = strtok(smGD.buttonMap, ",");
1389 smToSet.pointerMapChange = True;
1393 smToSet.pointerMapChange = False;
1396 while(tmpKey != NULL)
1398 restoreCharArray[numArgs] = (char) atoi(tmpKey);
1400 tmpKey = strtok(NULL, ",");
1401 if((numArgs >= charSize) && (tmpKey != NULL))
1404 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1405 charSize * sizeof(char));
1406 if(restoreCharArray == NULL)
1408 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1409 SM_FREE((char *)restorePtrArray);
1417 XSetPointerMapping(smGD.display, (unsigned char *)restoreCharArray, numArgs);
1420 * Copy the pointer map into the saved map for logout
1422 smToSet.numButton = ((numArgs > 5) ? 5 : numArgs);
1423 for(i = 0; i < smToSet.numButton;i++)
1425 smToSet.pointerMap[i] = restoreCharArray[i];
1430 * Restore the key mappings
1432 if(smSettings.numKeyCode > 0)
1434 tmpSyms = (KeySym *) restoreCharArray;
1435 symSize = (charSize * sizeof(char)) / sizeof(KeySym);
1436 tmpKey = strtok(smGD.keySyms, ",");
1437 for(i = 0;tmpKey != NULL;i++)
1439 tmpSyms[i] = (KeySym) atol(tmpKey);
1440 tmpKey = strtok(NULL, ",");
1442 if((numArgs >= symSize) && (tmpKey != NULL))
1445 symSize = (charSize * sizeof(char))/sizeof(KeySym);
1446 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1447 (charSize * sizeof(char)));
1448 if(restoreCharArray == NULL)
1450 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1451 SM_FREE((char *) restorePtrArray);
1454 tmpSyms = (KeySym *) restoreCharArray;
1457 numArgs /= smSettings.keySymPerCode;
1458 XChangeKeyboardMapping(smGD.display, (KeyCode)
1459 smGD.display->min_keycode,
1460 smSettings.keySymPerCode, tmpSyms,
1465 * Restore the modifier mappings
1467 tmpCode = (KeyCode *) restoreCharArray;
1468 tmpKey = strtok(smGD.modSyms, ",");
1471 for(i = 0;i < (8 * smSettings.maxKeyPerMod);i++)
1475 codeSym = (KeySym) atol(tmpKey);
1478 tmpCode[i] = XKeysymToKeycode(smGD.display, codeSym);
1482 tmpCode[i] = (KeyCode) 0;
1487 tmpCode[i] = (KeyCode) 0;
1489 tmpKey = strtok(NULL, ",");
1491 restoreMod.max_keypermod = smSettings.maxKeyPerMod;
1492 restoreMod.modifiermap = tmpCode;
1493 XSetModifierMapping(smGD.display, &restoreMod);
1496 SM_FREE((char *) restorePtrArray);
1497 SM_FREE(restoreCharArray);
1504 /*************************************<->*************************************
1506 * RestoreIndependentResources ()
1511 * In charge of restoring the resources that help make the session more
1512 * resolution and language independent - only restored if they are
1513 * necessary (lang || resolution has changed) and exist
1518 * smResources = global pointer to the resources to be restored by the SM
1528 *************************************<->***********************************/
1530 RestoreIndependentResources( void )
1534 unsigned long nitems, leftover;
1535 unsigned char *data = NULL;
1537 XrmValue fontResourceReturn;
1538 char *currentLangPtr, *resValRet, *sessionType;
1540 int intYRes[2], status,i;
1543 Boolean resIndep = False, resRet;
1546 if(((smGD.sessionLang == NULL) || (*smGD.sessionLang == NULL)) &&
1547 (smRes.displayResolution == 0))
1550 * No saved info to draw from - nothing new is added
1555 currentLangPtr = getenv("LANG");
1557 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1558 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1560 if(fltYRes < MED_RES_Y_RES)
1562 intYRes[0] = LOW_RES_Y_RES;
1563 sessionRes = SM_LOW_RES_EXT;
1567 if(fltYRes >= HIGH_RES_Y_RES)
1569 intYRes[0] = HIGH_RES_Y_RES;
1570 sessionRes = SM_HIGH_RES_EXT;
1574 intYRes[0] = MED_RES_Y_RES;
1575 sessionRes = SM_MED_RES_EXT;
1579 if(smRes.displayResolution < MED_RES_Y_RES)
1581 intYRes[1] = LOW_RES_Y_RES;
1585 if(smRes.displayResolution >= HIGH_RES_Y_RES)
1587 intYRes[1] = HIGH_RES_Y_RES;
1591 intYRes[1] = MED_RES_Y_RES;
1596 * If the resolution or the language has changed -
1597 * load the language/resolution independent fonts if
1598 * they exist in the users home directory or in the system
1600 if((strcmp(currentLangPtr, smGD.sessionLang)) ||
1601 (intYRes[0] != intYRes[1]))
1603 char *fontPath = SM_MALLOC(MAXPATHLEN + 1);
1605 if(smGD.sessionType == HOME_SESSION)
1607 sessionType = SM_HOME_FONT_DIRECTORY;
1611 sessionType = SM_CURRENT_FONT_DIRECTORY;
1614 sprintf(fontPath, "%s/%s/%s/%s.%s", smGD.savePath, sessionType,
1615 currentLangPtr, SM_FONT_FILE, sessionRes);
1616 status = stat(fontPath, &buf);
1620 * User has nothing there - look in the system defaults
1621 * first in the language dep -then in lang independent
1625 if((currentLangPtr != NULL) && (*currentLangPtr != 0))
1627 strcat(fontPath, "/");
1628 strcat(fontPath, currentLangPtr);
1631 strcat(fontPath, "/");
1632 strcat(fontPath, SM_SYSTEM_FONT_FILE);
1636 status = stat(fontPath, &buf);
1639 if((currentLangPtr != NULL) && (*currentLangPtr != 0) &&
1640 (strcmp(currentLangPtr, "C")))
1642 strcpy(fontPath, "/C/");
1643 strcat(fontPath, SM_SYSTEM_FONT_FILE);
1647 status = stat(fontPath, &buf);
1664 strncpy(smGD.fontPath, fontPath, MAXPATHLEN);
1666 if(resIndep == True)
1670 * add the auxillary resources onto the root window
1672 RestoreResources(True, "-merge", "-file", smGD.fontPath, NULL);
1675 * Load the resources from the RESOURCE_MANAGER
1676 * property on the root window
1678 if(XGetWindowProperty(smGD.display, RootWindow(smGD.display, 0),
1679 XA_RESOURCE_MANAGER,0L,
1680 100000000L,False,XA_STRING,&actualType,
1681 &actualFormat,&nitems,&leftover,
1682 (unsigned char**) &data) == Success)
1684 smBase = XrmGetStringDatabase((char *)data);
1693 PrintError(DtError, GETMESSAGE(16, 6, "Invalid display/language independent resource file. No display/language independent resources will be restored."));
1694 SM_FREE((char *)data);
1700 * Get the new fontlist from the resources and
1701 * Put it on the application shell. Then add
1702 * the auxillary resources into the display struct
1704 resRet = XrmGetResource(smBase, "*fontList", "*FontList",
1705 &resValRet, &fontResourceReturn);
1708 XtSetArg(uiArgs[i], XmNdefaultFontList,
1709 (XmFontList) fontResourceReturn.addr);i++;
1710 XtSetValues(smGD.topLevelWid, uiArgs, i);
1713 * Overwrite the old font preferences, otherwise,
1714 * they'll come back to haunt us if the user logs in again
1715 * under the current language. We need to get the font
1716 * resources which have just been loaded, then overlay
1717 * them onto the _DT_SM_PREFERENCES root property to make
1718 * sure we get them back when we login again.
1720 for (i = 0; i < XtNumber(fonttype); i++)
1722 resRet = XrmGetResource(smBase, fonttype[i], fontclass[i],
1723 &resValRet, &fontResourceReturn);
1727 (char *)SM_MALLOC(fontResourceReturn.size + 30);
1728 bzero(resdata, fontResourceReturn.size + 30);
1729 strcat(resdata, fonttype[i]);
1730 strcat(resdata, ": ");
1731 strcat(resdata, fontResourceReturn.addr);
1732 strcat(resdata, "\n");
1733 _DtAddResString(smGD.display, resdata, _DT_ATR_PREFS);
1738 XrmMergeDatabases(smBase, &(smGD.display->db));
1739 SM_FREE((char *)data);
1743 SM_FREE((char*) fontPath);
1750 /*************************************<->*************************************
1757 * Reads through the client file and restores its contents. A client file
1758 * consists of hints for the workspace manager, actual client commands, and
1759 * remote execution commands. All commands are processed accordingly.
1760 * If this is the first DT 3.0 session for a DT 2.0 user then we will
1761 * also launch the helpviewer. If this is the first DT 3.0 session for a
1762 * DT 2.0 user then we will also run convertVS.sh to change all
1763 * occurances of /usr/bin/X11/hpterm to .../dt/bin/hpterm,
1764 * /usr/bin/X11/xterm to .../dt/bin/xterm and
1765 * /usr/bin/X11/xload to .../dt/bin/xload.
1776 * Any information read from the client file will be mucked with during
1777 * processing, and should not try to be mucked with again.
1779 * WARNING: This routine closes cfileP - not the calling routine
1780 * DOUBLE-WARNING: This routine starts the window manager
1782 *************************************<->***********************************/
1784 RestoreClients( void )
1786 unsigned char *lineP, *string;
1787 char *pch, *dispPtr;
1788 char *dispEnv, *dispSav, *dispEnvHelpview, *dispSavHelpview;
1789 unsigned char *hostPtr=NULL, *cmdPtr=NULL, *hintPtr = NULL;
1790 unsigned char *remoteDisplay;
1793 unsigned char tmpChar[35];
1794 int screenNum = 0, i, j, chlen, numClientsExec;
1795 int numRemoteDone = 0;
1797 Boolean clientsDone = False, wmHandshake = False, cmdInvInit = False;
1798 XClientMessageEvent smToWmMessage;
1801 * These variables are needed to buffer up the commands and then
1802 * execute them (also buffer up hints then put them on the root window
1804 unsigned char *hintsBuf[MAX_SCREENS_SAVED];
1805 unsigned char *cmdBuf[MAX_SCREENS_SAVED];
1806 unsigned int maxHintsSize[MAX_SCREENS_SAVED];
1807 unsigned int actHintsSize[MAX_SCREENS_SAVED];
1808 unsigned int numHints[MAX_SCREENS_SAVED];
1809 unsigned int maxCmdSize[MAX_SCREENS_SAVED];
1810 unsigned int actCmdSize[MAX_SCREENS_SAVED];
1811 unsigned int numCmd[MAX_SCREENS_SAVED];
1812 unsigned int maxRemoteSize[MAX_SCREENS_SAVED];
1815 * Initialize the buffers and their sizes to null and 0. Because of
1816 * all possible combinations - buffers aren't malloc'd until they're
1819 for(i = 0;i<smGD.numSavedScreens;i++)
1823 remoteBuf[i] = NULL;
1824 maxHintsSize[i] = 0;
1825 actHintsSize[i] = 0;
1830 maxRemoteSize[i] = 0;
1831 actRemoteSize[i] = 0;
1835 * Save the contents of the DISPLAY environment variable so that it
1836 * can be restored when we're through
1838 dispEnv = getenv(DISPLAY_NAME);
1841 dispSav = (char *) SM_MALLOC(((strlen(dispEnv) +
1842 strlen(DISPLAY_NAME_EQUAL)) * sizeof(char) + 1));
1843 sprintf(dispSav, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
1851 displayName = strdup(smGD.display->display_name);
1852 remoteDisplay = (unsigned char *)
1853 SM_MALLOC(sizeof(unsigned char) * (strlen(displayName) + 101));
1856 * Create the display name for locally executing clients
1882 * Create the display name for remotely executing clients.
1883 * These two may or may not be the same
1885 DtGetShortHostname((char *)remoteDisplay, 100);
1888 * Add the display qualifications to the host name
1889 * screen is added at execution time
1891 strcat((char *)remoteDisplay, (char *)dispPtr);
1894 * Intern the atom needed to put the hints on the root window
1895 * This has to be done here because InitProtocol has not been called yet
1897 XaWmDtHints = XInternAtom(smGD.display, _XA_DT_SESSION_HINTS, False);
1899 while(GetNextLine() != NULL)
1902 string = GetSmartString(&lineP);
1903 if( string != NULL && !strcmp((char *)string, "dtsmcmd"))
1905 while((string = GetSmartString(&lineP)) != NULL )
1907 if(!strcmp((char *)string, "-host"))
1910 * Extract a host pointer - host pointers
1911 * only exist on remote executions
1913 string = GetSmartString(&lineP);
1918 if(!strcmp((char *)string, "-cmd"))
1921 * Extract the command pointer from the
1924 string = GetSmartString(&lineP);
1929 if(!strcmp((char *)string, "-screen"))
1932 * Extract the screen number from the command
1934 string = GetSmartString(&lineP);
1935 screenNum = atoi((char *)string);
1940 if(!strcmp((char *)string, "-hints"))
1943 * Extract the hints string
1945 string = GetSmartString(&lineP);
1954 * Now put our information in buffers and reinitialize the pointers
1958 if(FillHintBuf(hintPtr, hintsBuf, maxHintsSize,
1959 actHintsSize, screenNum, numHints) != 0)
1962 * Free all malloc'd buffers and exit
1964 for(i = 0;i < smGD.numSavedScreens;i++)
1966 if(actHintsSize[i] > 0)
1968 SM_FREE((char *) hintsBuf[i]);
1970 if(actCmdSize[i] > 0)
1972 SM_FREE((char *) cmdBuf[i]);
1974 if(actRemoteSize[i] > 0)
1976 SM_FREE((char *) remoteBuf[i]);
1984 if((cmdPtr != NULL) && (hostPtr == NULL))
1986 if(FillCmdBuf(cmdPtr, cmdBuf, maxCmdSize,
1987 actCmdSize,screenNum, &numCmd[screenNum]) != 0)
1990 * Free all malloc'd buffers and exit
1992 for(i = 0;i < smGD.numSavedScreens;i++)
1994 if(actHintsSize[i] > 0)
1996 SM_FREE((char *) hintsBuf[i]);
1998 if(actCmdSize[i] > 0)
2000 SM_FREE((char *) cmdBuf[i]);
2002 if(actRemoteSize[i] > 0)
2004 SM_FREE((char *) remoteBuf[i]);
2013 if((cmdPtr != NULL) && (hostPtr != NULL))
2015 if(FillRemoteBuf(cmdPtr, hostPtr, remoteDisplay,
2016 remoteBuf, maxRemoteSize,
2017 actRemoteSize, screenNum) != 0)
2020 * Free all malloc'd buffers and exit
2022 for(i = 0;i < smGD.numSavedScreens;i++)
2024 if(actHintsSize[i] > 0)
2026 SM_FREE((char *) hintsBuf[i]);
2028 if(actCmdSize[i] > 0)
2030 SM_FREE((char *) cmdBuf[i]);
2032 if(actRemoteSize[i] > 0)
2034 SM_FREE((char *) remoteBuf[i]);
2043 screenNum = XDefaultScreen(smGD.display);
2048 * All done with file so close it off and set descriptor to NULL -
2049 * This is done so that parsing routines can be used with a buffer later
2055 * Now execute all the buffers, put all hints on the root windows
2056 * Do all remote executions
2058 for(i = 0;i < smGD.numSavedScreens;i++)
2061 * Put the root window property on each root window
2063 if(actHintsSize[i] > 0)
2066 * Append number of hints to front of buffer
2068 sprintf((char *)tmpChar, "%d", numHints[i]);
2069 strncpy((char *)hintsBuf[i], (char *)tmpChar,
2070 strlen((char *)tmpChar));
2071 XChangeProperty(smGD.display, RootWindow(smGD.display, i),
2072 XaWmDtHints, XA_STRING, 8, PropModeReplace,
2073 hintsBuf[i], actHintsSize[i]);
2074 SM_FREE((char *) hintsBuf[i]);
2075 XSync(smGD.display, 0);
2083 * Now exec on the local clients - we're doing contention management
2084 * to make sure the system doesn't get swamped
2088 while((actCmdSize[i] == 0) && (i < smGD.numSavedScreens))
2093 envVal = SM_MALLOC(BUFSIZ);
2094 if(i >= smGD.numSavedScreens)
2100 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2108 * Keep forking one client after the other until the
2109 * memory utilization gets beyond the threshold -
2110 * (but only if the capability exists) Then go to
2111 * window manager handshaking
2113 #ifdef DEBUG_CONT_MANAGEMENT
2114 if(smRes.contManagement & SM_CM_SYSTEM)
2116 fprintf(stderr, "SM_CM_SYSTEM flag set in smRes.contManagement\n");
2118 if(smRes.contManagement & SM_CM_HANDSHAKE)
2120 fprintf(stderr, "SM_CM_HANDSHAKE flag set in smRes.contManagement\n");
2122 #endif /* DEBUG_CONT */
2124 if((smRes.contManagement & SM_CM_SYSTEM) &&
2125 ((GetMemoryUtilization() != MEM_NOT_AVAILABLE) &&
2126 (clientsDone == False)))
2128 while((GetMemoryUtilization() == MEM_NOT_FULL) &&
2129 (clientsDone == False))
2133 CreateExecString((char *) lineP);
2134 if(smExecArray[0] != NULL)
2136 (void) StartClient(smExecArray[0], (char **)smExecArray, NULL,
2137 NULL, NULL, False, False, -1);
2142 * When all the clients have been exec'd for this screen
2145 if(numClientsExec >= numCmd[i])
2147 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2148 envVal, displayName);
2155 * After we've checked memory utilization - finish up
2156 * by handshaking with the worksapce manager - if it's there
2158 if(clientsDone == False)
2160 if((smGD.dtwmRunning) && (smRes.contManagement & SM_CM_HANDSHAKE))
2163 * Get the window id of the workspace manager and tell it
2164 * to start messaging
2166 _DtGetMwmWindow(smGD.display, RootWindow(smGD.display, 0),
2168 smToWmMessage.type = ClientMessage;
2169 smToWmMessage.window = dtwmWin;
2170 smToWmMessage.message_type = XaSmWmProtocol;
2171 smToWmMessage.format = 32;
2172 smToWmMessage.data.l[0] = XaSmStartAckWindow;
2173 smToWmMessage.data.l[1] = CurrentTime;
2174 if (XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2175 (XEvent *) &smToWmMessage) != 0)
2178 XSync(smGD.display, 0);
2184 * Start a client - and wait for the workspace manager to
2185 * map a window to start a new client
2187 while(clientsDone == False)
2191 CreateExecString((char *) lineP);
2192 if(smExecArray[0] != NULL)
2194 (void) StartClient(smExecArray[0], smExecArray,
2195 NULL, NULL, NULL, False, False, -1);
2199 * If we're handshaking with the workspace manager
2200 * wait for the client to be mapped before starting
2203 if(wmHandshake == True)
2211 * When all the clients have been exec'd for this screen
2214 if(numClientsExec >= numCmd[i])
2216 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2217 envVal, displayName);
2222 if(wmHandshake == True)
2225 * If we are handshaking - tell the workspace manager to
2228 smToWmMessage.type = ClientMessage;
2229 smToWmMessage.window = dtwmWin;
2230 smToWmMessage.message_type = XaSmWmProtocol;
2231 smToWmMessage.format = 32;
2232 smToWmMessage.data.l[0] = XaSmStopAckWindow;
2233 smToWmMessage.data.l[0] = CurrentTime;
2234 XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2235 (XEvent *) &smToWmMessage);
2240 for(i = 0;i < smGD.numSavedScreens;i++)
2242 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2248 * Send out all the remote execution commands for the screen to
2249 * the command invoker. On failure - do a remsh instead
2251 if(actRemoteSize[i] > 0)
2254 * Initialize the command invoker - if not done
2256 if(cmdInvInit == False)
2258 _DtInitializeCommandInvoker(smGD.display,
2266 * Set up the display environment variable so that the
2267 * application comes back to the right screen
2269 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2273 parseP = remoteBuf[i];
2274 while(numRemoteExecs > 0 && GetNextLine() != NULL)
2277 * Get the host and the command and send them off
2278 * On failure of the command invoker do a remsh
2281 string = GetSmartString(&lineP);
2283 string = GetSmartString(&lineP);
2286 remoteBufPtr[numRemoteDone].cmdPtr = cmdPtr;
2287 remoteBufPtr[numRemoteDone].hostPtr = hostPtr;
2289 _DtCommandInvokerExecute(DtSTART_SESSION, NULL, NULL, NULL,
2290 "-", (char *) hostPtr, (char *) cmdPtr,
2291 RemoteRequestSucceeded, NULL,
2292 RemoteRequestFailed,
2293 &remoteBufPtr[numRemoteDone]);
2297 * If there is no more room in the remote client
2298 * array - quit exec'ing remote clients
2300 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2302 PrintError(DtError, GETMESSAGE(16, 5, "You have reached the maximum allowed number of remote clients. No further remote clients will be restored."));
2312 * Now return the display variable back to the display that was
2313 * originally opened (the default display)
2321 FixEnvironmentData();
2326 } /* END OF FUNCTION RestoreClients */
2330 /*************************************<->*************************************
2332 * StartEtc ( exiting )
2337 * Call the StartClient routine to fork and exec either the sessionetc file
2338 * (if exiting==False) or the sessionexit file (if exiting==True).
2350 *************************************<->***********************************/
2352 StartEtc( Boolean exiting )
2359 execArray[0] = smGD.exitPath;
2360 execArray[1] = smExitFile;
2362 execArray[0] = smGD.etcPath;
2363 execArray[1] = smEtcFile;
2365 execArray[2] = '\0';
2367 if ((status=stat(execArray[0], &buf)) != -1)
2369 StartClient(execArray[0], execArray, NULL, NULL, NULL, False, False, -1);
2374 /*************************************<->*************************************
2381 * Returns the next line from an fopened configuration file or a newline-
2382 * embedded configuration string.
2387 * cfileP = (global) file pointer to fopened configuration file or NULL
2388 * line = (global) line buffer
2389 * linec = (global) line count
2390 * parseP = (global) parse string pointer if cfileP == NULL
2395 * line = (global) next line
2396 * linec = (global) line count incremented
2397 * parseP = (global) parse string pointer incremented
2398 * Return = line or NULL if file or string is exhausted.
2403 * If there are more than MAXLINE characters on a line in the file cfileP the
2404 * excess are truncated.
2405 * Assumes the line buffer is long enough for any parse string line.
2406 * Code stolen from dtmwm
2408 *************************************<->***********************************/
2409 static unsigned char *
2412 unsigned char *string;
2418 /* read fopened file */
2420 string = (unsigned char *) fgets((char *)line, fileSize, cfileP);
2422 else if ((parseP != NULL) && (*parseP != NULL))
2423 /* read parse string */
2427 while ((*parseP != NULL) &&
2428 ((chlen = mblen ((char *) parseP, MB_CUR_MAX)) > 0) &&
2430 /* copy all but NULL and newlines to line buffer */
2434 *(string++) = *(parseP++);
2438 while ((*parseP != NULL) && (*parseP != '\n'))
2439 /* copy all but NULL and newlines to line buffer */
2441 *(string++) = *(parseP++);
2445 if (*parseP == '\n')
2458 } /* END OF FUNCTION GetNextLine */
2462 /*************************************<->*************************************
2464 * PeekAhead (currentChar, currentLev)
2469 * Returns a new level value if this is a new nesting level of quoted string
2470 * Otherwise it returns a zero
2475 * currentChar = current position in the string
2476 * currentLev = current level of nesting
2481 * Returns either a new level of nesting or zero if the character is copied in
2487 *************************************<->***********************************/
2490 unsigned char *currentChar,
2491 unsigned int currentLev )
2493 Boolean done = False;
2494 unsigned int tmpLev = 1;
2498 while (((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) &&
2499 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
2504 if(((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
2505 ((*currentChar == '"') || (*currentChar == '\\')))
2508 if(*currentChar == '"')
2519 while((*currentChar != NULL) && (done == False) &&
2520 ((*currentChar == '"') || (*currentChar == '\\')))
2523 if((*currentChar != NULL) &&
2524 ((*currentChar == '"') || (*currentChar == '\\')))
2527 if(*currentChar == '"')
2537 #endif /*MULTIBYTE*/
2540 * Figure out if this is truly a new level of nesting - else ignore it
2541 * This section probably could do some error checking and return -1
2542 * If so, change type of routine from unsigned int to int
2556 /*************************************<->*************************************
2558 * GetSmartString (linePP)
2563 * Returns the next quoted or whitespace-terminated nonquoted string in the
2565 * Additional functionality added to GetString in that anything in a
2566 * quoted string is considered sacred and nothing will be stripped from
2567 * the middle of a quoted string.
2572 * linePP = pointer to current line buffer pointer.
2577 * linePP = pointer to revised line buffer pointer.
2583 * May alter the line buffer contents.
2584 * Handles quoted strings and characters, removing trailing whitespace from
2586 * Returns NULL string if the line is empty or is a comment.
2587 * Code stolen from dtmwm.
2589 *************************************<->***********************************/
2591 static unsigned char *
2593 unsigned char **linePP )
2595 unsigned char *lineP = *linePP;
2596 unsigned char *endP;
2597 unsigned char *curP;
2598 unsigned char *lnwsP;
2599 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
2603 /* get rid of leading white space */
2604 ScanWhitespace (&lineP);
2607 * Return NULL if line is empty, whitespace, or begins with a comment.
2609 if((chlen = mblen ((char *) lineP, MB_CUR_MAX)) < 1)
2615 if ((chlen == 1) && (*lineP == '"'))
2618 quoteLevel[level] = 1;
2620 * Start beyond double quote and find the end of the quoted string.
2621 * '\' quotes the next character - but is not stripped out.
2622 * Otherwise, matching double quote or NULL terminates the string.
2624 * We use lnwsP to point to the last non-whitespace character in the
2625 * quoted string. When we have found the end of the quoted string,
2626 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2627 * This removes any trailing whitespace without overwriting the
2628 * matching quote, needed later. If the quoted string was all
2629 * whitespace, then this will write a NULL at the beginning of the
2630 * string that will be returned -- OK.
2632 lnwsP = lineP++; /* lnwsP points to first '"' */
2633 curP = endP = lineP; /* other pointers point beyond */
2635 while ((*endP = *curP) &&
2636 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2637 ((chlen > 1) || (*curP != '"')))
2638 /* Haven't found matching quote yet.
2639 * First byte of next character has been copied to endP.
2643 if ((chlen == 1) && (*endP == '\\') &&
2644 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2647 * Check to see if this is a quoted quote - if it is
2648 * strip off a level - if not - it's sacred leave it alone
2650 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2653 if(quoteLevel[level] >= checkLev)
2655 if (level > 0) level--;
2657 else if (level < MAX_QUOTE_DEPTH)
2660 quoteLevel[level] = checkLev;
2663 for(i = 0;i < (checkLev - 2);i++)
2665 *endP++ = *curP++;curP++;
2672 /* Singlebyte character: character copy finished. */
2674 if (isspace (*endP))
2675 /* whitespace character: leave lnwsP unchanged. */
2680 /* non-whitespace character: point lnwsP to it. */
2686 /* Multibyte (nonwhitespace) character: point lnwsP to it.
2687 * Finish character byte copy.
2700 /* get rid of leading white space */
2701 ScanWhitespace (&lineP);
2703 /* Return NULL if line is empty, or whitespace */
2713 quoteLevel[level] = 1;
2715 * Start beyond double quote and find the end of the quoted string.
2716 * '\' quotes the next character.
2717 * Otherwise, matching double quote or NULL terminates the string.
2719 * We use lnwsP to point to the last non-whitespace character in the
2720 * quoted string. When we have found the end of the quoted string,
2721 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2722 * This removes any trailing whitespace without overwriting the
2723 * matching quote, needed later. If the quoted string was all
2724 * whitespace, then this will write a NULL at the beginning of the
2725 * string that will be returned -- OK.
2727 lnwsP = lineP++; /* lnwsP points to first '"' */
2728 curP = endP = lineP; /* other pointers point beyond */
2730 while ((*endP = *curP) && (*endP != '"'))
2731 /* haven't found matching quote yet */
2733 /* point curP to next character */
2735 if ((*endP == '\\') && (*curP != NULL))
2736 /* shift quoted nonNULL character down and curP ahead */
2739 * Check to see if this is a quoted quote - if it is
2740 * strip off a level - if not - it's sacred leave it alone
2742 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2745 if(quoteLevel[level] >= checkLev)
2747 if (level > 0) level--;
2749 else if (level < MAX_QUOTE_DEPTH)
2752 quoteLevel[level] = checkLev;
2755 for(i = 0;i < (checkLev - 2);i++)
2757 *endP++ = *curP++;curP++;
2763 if (isspace (*endP))
2764 /* whitespace character: leave lnwsP unchanged. */
2769 /* non-whitespace character: point lnwsP to it. */
2777 * Found matching quote or NULL.
2778 * NULL out any trailing whitespace.
2789 /* Unquoted string */
2792 * Find the end of the nonquoted string.
2793 * '\' quotes the next character.
2794 * Otherwise, whitespace, NULL, terminates the string.
2796 curP = endP = lineP;
2799 while ((*endP = *curP) &&
2800 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2801 ((chlen > 1) || (!isspace (*curP))))
2802 /* Haven't found whitespace yet.
2803 * First byte of next character has been copied to endP.
2807 if ((chlen == 1) && (*endP == '\\') &&
2808 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2810 * copy first byte of quoted nonNULL character down.
2811 * point curP to next byte
2818 /* Multibyte character: finish character copy. */
2827 while ((*endP = *curP) && !isspace (*endP))
2829 /* point curP to next character */
2831 if ((*endP == '\\') && (*curP != NULL))
2832 /* shift quoted nonNULL character down and curP ahead */
2842 * Two cases for *endP:
2844 * matching quote -> write NULL over char and point beyond
2845 * NULL -> point to NULL
2850 *endP = NULL; /* write NULL over terminator */
2851 *linePP = ++curP; /* point beyond terminator */
2857 return ((unsigned char *)lineP);
2859 } /* END OF FUNCTION GetString */
2864 /*************************************<->*************************************
2866 * ScanWhitespace(linePP)
2871 * Scan the string, skipping over all white space characters.
2876 * linePP = nonNULL pointer to current line buffer pointer
2881 * linePP = nonNULL pointer to revised line buffer pointer
2886 * Assumes linePP is nonNULL
2887 * Code Stolen from dtmwm
2889 *************************************<->***********************************/
2892 unsigned char **linePP )
2895 while (*linePP && (mblen ((char *) *linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
2897 while (*linePP && isspace (**linePP))
2903 } /* END OF FUNCTION ScanWhitespace */
2907 /*************************************<->*************************************
2909 * FillHintBuf(newHint, hintBuf, maxSize, actSize, screen, numHints)
2914 * Put the new hint into the hint buffer. Each hint is separated by a
2920 * newHint = hint to add to the buffer
2921 * hintBuf = an array of buffers - one for each screen
2922 * maxSize = array of buffers of the current malloced size of each hintBuf
2923 * actSize = array of space currently used by each hintBuf
2924 * screen = screen number for this hint
2925 * numHints = array of the number of hints for each screen
2926 * smGD.numSavedScreens = (global) checked to make sure this hint should be
2931 * hintBuf[screen] = updated hint buf for this screen (newHint added)
2932 * maxSize[screen] = enlarged if not big enough or malloced if not done before
2933 * actSize[screen] = updated size of the hints buffer
2934 * numHints[screen] = updated by 1 if this hint is added
2940 *************************************<->***********************************/
2943 unsigned char *newHint,
2944 unsigned char **hintBuf,
2945 unsigned int *maxSize,
2946 unsigned int *actSize,
2947 unsigned int screen,
2948 unsigned int *numHints)
2950 static int hintBufSize = 5000;
2953 * If the screen that this hint was meant for is not in the current
2954 * set of available screens, don't save it
2956 if(screen >= smGD.numSavedScreens)
2962 * Check to see if this buffer has been malloc'd before - if it hasn't
2963 * malloc it. If it has - check to make sure it's big enough to hold the
2966 if(maxSize[screen] == 0)
2968 hintBuf[screen] = (unsigned char *) SM_MALLOC(hintBufSize * sizeof(char));
2969 if(hintBuf[screen] == NULL)
2971 actSize[screen] = 0;
2972 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
2975 maxSize[screen] = hintBufSize * sizeof(char);
2978 * Now reserve 4 bytes for the length
2980 strcpy((char *)hintBuf[screen], " \n");
2984 if((actSize[screen] + strlen((char *)newHint) + 2) >= maxSize[screen])
2986 hintBuf[screen] = (unsigned char *)
2987 SM_REALLOC((char *) hintBuf[screen],
2991 if(hintBuf[screen] == NULL)
2993 actSize[screen] = 0;
2994 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
2997 maxSize[screen] = maxSize[screen] + (hintBufSize * sizeof(char));
3002 * add the new hint AFTER the last newline
3004 strcat((char *)hintBuf[screen], (char *)newHint);
3005 strcat((char *)hintBuf[screen], "\n");
3006 actSize[screen] = strlen((char *)hintBuf[screen]);
3007 numHints[screen] += 1;
3014 /*************************************<->*************************************
3016 * FillCmdBuf(newCmd, cmdBuf, maxSize, actSize, screen)
3021 * Put a new command into the command buffer. The command buffer is just
3022 * one big long string of stuff to be executed.
3027 * newCmd = command to add to the buffer
3028 * cmdBuf = an array of buffers - one for each screen
3029 * maxSize = array of buffers of the current malloced size of each cmdBuf
3030 * actSize = array of space currently used by each cmdBuf
3031 * screen = screen number for this command
3032 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3037 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3038 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3039 * actSize[screen] = updated size of the command buffer
3045 *************************************<->***********************************/
3048 unsigned char *newCmd,
3049 unsigned char **cmdBuf,
3050 unsigned int *maxSize,
3051 unsigned int *actSize,
3052 unsigned int screen,
3053 unsigned int *numCmd )
3055 static int cmdBufSize = 5000;
3058 * If the screen that this command was meant for is not in the current
3059 * set of available screens, don't save it
3061 if(screen >= smGD.numSavedScreens)
3067 * Check to see if this buffer has been malloc'd before - if it hasn't
3068 * malloc it. If it has - check to make sure it's big enough to hold the
3071 if(maxSize[screen] == 0)
3073 cmdBuf[screen] = (unsigned char *) SM_MALLOC(cmdBufSize * sizeof(char));
3074 if(cmdBuf[screen] == NULL)
3076 actSize[screen] = 0;
3077 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3080 maxSize[screen] = cmdBufSize * sizeof(char);
3084 if((actSize[screen] + strlen((char *)newCmd)) >= maxSize[screen])
3086 cmdBuf[screen] = (unsigned char *) SM_REALLOC((char *)cmdBuf[screen],
3090 if(cmdBuf[screen] == NULL)
3092 actSize[screen] = 0;
3093 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3096 maxSize[screen] = maxSize[screen] + (cmdBufSize * sizeof(char));
3100 if(actSize[screen] == 0)
3102 strcpy((char *)cmdBuf[screen], (char *)newCmd);
3106 strcat((char *)cmdBuf[screen], (char *)newCmd);
3109 *numCmd = *numCmd + 1;
3110 strcat((char *)cmdBuf[screen], "\n");
3111 actSize[screen] = strlen((char *)cmdBuf[screen]);
3118 /*************************************<->*************************************
3120 * FillRemoteBuf(newCmd, hostName, displayName, remoteBuf,
3121 * maxSize, actSize, screen)
3126 * Put a new command into the remote execution buffer. The command buffer is
3127 * just one big long string of stuff to be executed.
3132 * newCmd = command to add to the buffer
3133 * hostName = host where command is to be executed from
3134 * displayName = display where host is to be executed to
3135 * remoteBuf = an array of buffers - one for each screen
3136 * maxSize = array of buffers of the current malloced size of each cmdBuf
3137 * actSize = array of space currently used by each cmdBuf
3138 * screen = screen number for this command
3139 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3144 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3145 * in remote format (host name and display name)
3146 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3147 * actSize[screen] = updated size of the command buffer
3153 *************************************<->***********************************/
3156 unsigned char *newCmd,
3157 unsigned char *hostName,
3158 unsigned char *displayName,
3159 unsigned char *remoteBuf[] ,
3160 unsigned int *maxSize ,
3161 unsigned int *actSize ,
3162 unsigned int screen )
3164 unsigned char *string;
3165 static int remoteBufSize = 5000;
3168 * If the screen that this command was meant for is not in the current
3169 * set of available screens, don't save it
3171 if(screen >= smGD.numSavedScreens)
3177 * Check to see if this buffer has been malloc'd before - if it hasn't
3178 * malloc it. If it has - check to make sure it's big enough to hold the
3181 if(maxSize[screen] == 0)
3183 remoteBuf[screen] = (unsigned char *)
3184 SM_MALLOC(remoteBufSize * sizeof(char));
3185 if(remoteBuf[screen] == NULL)
3187 actSize[screen] = 0;
3188 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3191 maxSize[screen] = remoteBufSize * sizeof(char);
3195 if((actSize[screen] + strlen((char *)newCmd) +
3196 strlen((char *)hostName) +
3197 strlen((char *)displayName) +
3198 strlen("-display ") + 5) >= maxSize[screen])
3200 remoteBuf[screen] = (unsigned char *)
3201 SM_REALLOC((char *)remoteBuf[screen],
3203 (remoteBufSize * sizeof(char)));
3204 if(remoteBuf[screen] == NULL)
3206 actSize[screen] = 0;
3207 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3210 maxSize[screen] = maxSize[screen] + (remoteBufSize * sizeof(char));
3214 if(actSize[screen] == 0)
3217 * If the buffer is empty fill it with the initial contents
3219 strcpy((char *)remoteBuf[screen], (char *)hostName);
3220 strcat((char *)remoteBuf[screen], " ");
3225 * if this buffer is not emtpy
3226 * add the new command BEFORE the last null terminator
3227 * Commands for remote executions are separated by newlines
3229 strcat((char *)remoteBuf[screen], "\n");
3230 strcat((char *)remoteBuf[screen], (char *)hostName);
3234 * Copy the command in - quote it
3236 strcat((char *)remoteBuf[screen], " \"");
3237 string = GetSmartString(&newCmd);
3238 strcat((char *)remoteBuf[screen], (char *)string);
3239 strcat((char *)remoteBuf[screen], " ");
3242 * Once display name has been put in place - concatenate the
3243 * rest of the command
3245 while((string = GetSmartString(&newCmd)) != NULL )
3247 strcat((char *)remoteBuf[screen], " ");
3248 strcat((char *)remoteBuf[screen], (char *)string);
3252 * Now close off the command with a quote
3254 strcat((char *)remoteBuf[screen], "\"");
3256 actSize[screen] = strlen((char *)remoteBuf[screen]);
3259 * Bump the remote command counter
3267 /*************************************<->*************************************
3269 * CreateExecString(execString)
3274 * Create a string that can be fed to a fork and exec by breaking it up
3275 * into argc and argv
3280 * execString = whole command
3284 * smExecArray = global modified to contain pointers to argc and argv
3290 *************************************<->***********************************/
3298 static int iSizeArgv = ARG_AMT;
3303 if (smExecArray == NULL)
3305 smExecArray = (char **) XtMalloc (ARG_AMT * sizeof(char *));
3307 string = (char *) GetSmartString((unsigned char **) &execString);
3308 while(string != NULL)
3310 smExecArray[argc] = string;
3312 if (argc >= iSizeArgv)
3314 iSizeArgv += ARG_AMT;
3315 smExecArray = (char **)
3316 XtRealloc ((char *)smExecArray, (iSizeArgv * sizeof(char *)));
3318 string = (char *) GetSmartString((unsigned char **) &execString);
3322 * If the last string is a background character
3327 if(!strcmp((char *)smExecArray[argc - 1], "&"))
3329 smExecArray[argc - 1] = '\0';
3333 smExecArray[argc] = '\0';
3335 } /* END OF FUNCTION CreateExecString */
3339 * SetTemporaryDisplay - does a putenv of the current value of the
3340 * DISPLAY environment variable but with the given screen number.
3346 SetTemporaryDisplay (
3349 static char * tmpDisplay = NULL;
3350 static int lastScreen = -1;
3353 if (screenNum == -1)
3356 if (!savedDisplay) {
3359 if ((dispEnv = getenv (DISPLAY_NAME)) == NULL)
3361 savedDisplay = XtMalloc (strlen (DISPLAY_NAME_EQUAL) +
3362 strlen (dispEnv) + 2);
3365 sprintf (savedDisplay, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
3368 if (lastScreen == screenNum && tmpDisplay != NULL) {
3369 putenv (tmpDisplay);
3372 lastScreen = screenNum;
3377 tmpDisplay = XtMalloc (strlen (savedDisplay) + 4);
3380 strcpy (tmpDisplay, savedDisplay);
3383 if (pch = strrchr (tmpDisplay, ':')) {
3386 if (pch2 = strchr (pch, '.'))
3388 pch3 = XtMalloc (strlen (tmpDisplay) + 4);
3391 sprintf (pch3, "%s.%d", tmpDisplay, screenNum);
3392 strcpy (tmpDisplay, pch3);
3393 XtFree ((char *) pch3);
3395 putenv (tmpDisplay);
3401 * RestoreDisplay - does a putenv of the global variable savedDisplay
3407 if (screenNum != -1 && savedDisplay)
3408 putenv (savedDisplay);
3412 /*************************************<->*************************************
3414 * StartClient - calls StartLocalClient or StartRemoteClient depending
3415 * on the value of hostName.
3419 * Starts a local or remote application
3423 * program = execArray[0]
3424 * execArray = command to fork and exec
3425 * hostName = the name of the host where program should be executed
3426 * cwd = directory to chdir to before doing the exec
3427 * envp = the envrironment variables to add to the child processes env
3428 * checkCwd = if True and cwd is NULL, a message will be logged; if
3429 * False, cwd will not be checked and the cwd will be set to $HOME
3430 * useIgnoreEnvironmentResource = if True, the variables listed in the
3431 * IgnoreEnvironment resource will be removed from 'environ' before
3432 * execArray is exec'd
3433 * screen = if set to -1, it will be ignored; otherwise, the screen
3434 * number will be used to define DISPLAY for the duration of this
3435 * function - DISPLAY will be reset before the function returns.
3439 * Returns True if the command is successfully executed; False otherwise.
3443 * localHost - is modified
3445 *************************************<->***********************************/
3454 Boolean useIgnoreEnvironmentResource,
3457 static char * defaultCwd = NULL;
3458 Boolean cwdNull = False;
3459 Boolean startStatus;
3461 SetTemporaryDisplay (screen);
3463 if (!ignoreEnvPtr && useIgnoreEnvironmentResource) {
3464 if (smRes.ignoreEnvironment)
3465 ignoreEnvPtr = _DtVectorizeInPlace (
3466 smRes.ignoreEnvironment, ',');
3470 if (getenv ("HOME"))
3471 defaultCwd = strdup (getenv ("HOME"));
3473 defaultCwd = getcwd (NULL, MAXPATHLEN + 1);
3475 (void) gethostname (localHost, MAXHOSTNAMELEN);
3483 if (!hostName || (_DtIsSameHost (localHost, hostName)))
3484 startStatus = StartLocalClient (program, execArray,
3485 cwd, envp, checkCwd,
3486 useIgnoreEnvironmentResource);
3488 startStatus = StartRemoteClient (program, execArray, hostName,
3490 useIgnoreEnvironmentResource);
3492 RestoreDisplay (screen);
3494 return (startStatus);
3497 /*************************************<->*************************************
3503 * Starts a local application.
3506 * Returns True if the command is successfully executed; False otherwise.
3508 *************************************<->***********************************/
3516 Boolean useIgnoreEnvironmentResource)
3520 char clientMessage[MAXPATHLEN + 30];
3521 char **tmpEnv, **ppchar;
3524 * Fork and exec the client process
3526 clientFork = vfork();
3529 * If the fork fails - Send out an error and return
3533 PrintErrnoError(DtError, smNLS.cantForkClientString);
3538 * Fork succeeded - now do the exec
3542 SetSIGPIPEToDefault ();
3545 * Log a warning if the given cwd is not valid
3549 if ((chdir (cwd)) == -1)
3553 tmpCwd = getcwd (NULL, MAXPATHLEN + 1);
3555 LogCWDMessage (cwd, program, tmpCwd);
3560 * Add envp to the client's environ if the variable
3561 * is not in the ignoreEnvironment list
3563 if (useIgnoreEnvironmentResource && envp) {
3566 tmpEnv = RemoveEnvironmentVars (envp);
3570 for (ppchar = tmpEnv; ppchar && *ppchar; *ppchar++)
3571 putenv (strdup (*ppchar));
3576 * Set the gid of the process back from bin
3579 setregid(smGD.runningGID, smGD.runningGID);
3581 setgid(smGD.runningGID);
3582 setegid(smGD.runningGID);
3586 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3592 #endif /* __osf__ */
3594 MarkFileDescriptors (3, F_SETFD, 1);
3596 execStatus = execvp(program, execArray);
3599 sprintf(clientMessage, ((char *)GETMESSAGE(16, 3, "Unable to exec %s.")), execArray[0]);
3600 PrintErrnoError(DtError, clientMessage);
3608 /*************************************<->*************************************
3614 * Starts a remote application.
3617 * Returns True if the command is successfully executed; False otherwise.
3619 *************************************<->***********************************/
3627 Boolean useIgnoreEnvironmentResource)
3630 SPC_Channel_Ptr channel;
3632 char errorMessage[1024];
3634 static Boolean cmdInvokerInitialized = False;
3635 char ** tmpEnv = envp;
3637 ioMode = SPCIO_NOIO | SPCIO_FORCE_CONTEXT;
3639 if (!cmdInvokerInitialized) {
3640 _DtInitializeCommandInvoker(smGD.display,
3644 cmdInvokerInitialized = True;
3647 (void) strcpy (errorMessage, "");
3649 channel = (SPC_Channel_Ptr) _DtSPCOpen (hostName, ioMode, errorMessage);
3650 if (channel == SPC_ERROR) {
3651 message = strdup ((char *) GETMESSAGE (40, 13,
3652 "The following application cannot be started on host '%s'\nbecause this host cannot be reached from host '%s':\n\n %s"));
3655 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3656 message, hostName, localHost, program);
3662 netfile = tt_host_file_netfile (hostName, cwd);
3663 if (tt_pointer_error (netfile) != TT_OK) {
3665 message = strdup ((char *) GETMESSAGE (40, 14,
3666 "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]"));
3669 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3670 message, program, hostName, cwd,
3671 tt_status_message (tt_pointer_error (
3679 * Add envp to the client's environ if the variable
3680 * is not in the ignoreEnvironment list
3682 if (useIgnoreEnvironmentResource && ignoreEnvPtr && envp)
3683 tmpEnv = RemoveEnvironmentVars (envp);
3685 if ((_DtSPCSpawn (program, netfile, execArray, tmpEnv, channel,
3686 hostName, NULL, cwd, errorMessage)) == SPC_ERROR) {
3687 DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMessage);
3689 XtFree ((char *) tmpEnv);
3695 XtFree ((char *) tmpEnv);
3701 /*************************************<->*************************************
3708 * Fork and exec the default window manager
3721 *************************************<->***********************************/
3730 * These lines were added to support the builtin
3735 char *displayName,*dpy;
3737 hostName = SM_MALLOC(MAXPATHSM);
3738 displayName = SM_MALLOC(MAXPATHSM);
3740 if( gethostname(hostName, (sizeof(hostName) - 1) ) == 0)
3742 hostName[MAXPATHSM - 1] = '\0';
3743 dpy = getenv(DISPLAY_NAME);
3744 homeDir = getenv("HOME");
3747 strcpy(displayName, dpy);
3748 dpy = strchr(displayName, ':');
3753 sprintf(tmpExecWmFile, "%s/.dt/bin/%s/%s/dtwm", homeDir,
3754 hostName,displayName);
3755 if (access(tmpExecWmFile,X_OK) != 0)
3757 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3761 localWmLaunched = True;
3762 if (!smGD.userSetWaitWmTimeout)
3764 smRes.waitWmTimeout = 60000;
3770 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3775 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3779 SM_FREE(displayName);
3781 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3782 * End of lines were added to support the builtin
3786 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3791 * Fork and exec the client process
3793 clientFork = vfork();
3796 * If the fork fails - Send out an error and return
3800 PrintErrnoError(DtError, smNLS.cantForkClientString);
3805 * Fork succeeded - now do the exec
3809 SetSIGPIPEToDefault ();
3813 * Set the gid of the process back from bin
3816 setregid(smGD.runningGID, smGD.runningGID);
3818 setgid(smGD.runningGID);
3819 setegid(smGD.runningGID);
3822 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3828 #endif /* __osf__ */
3830 MarkFileDescriptors (3, F_SETFD, 1);
3833 * These lines were added to support the builtin
3836 * execStatus = execlp(".../dt/bin/dtwm", "dtwm", (char *) 0);
3839 execStatus = execlp(tmpExecWmFile, "dtwm", (char *) 0);
3842 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3843 * End of lines were added to support the builtin
3847 if(execStatus != 0 && (!localWmLaunched))
3849 PrintErrnoError(DtError, GETMESSAGE(16, 4, "Unable to exec process /usr/dt/bin/dtwm. No window manager will be started."));
3856 /*************************************<->*************************************
3863 * Fork a copy of ourselves and kill the parent off so that scripts starting
3864 * up the session manager can continue.
3876 *************************************<->***********************************/
3884 * Fork and exec the client process
3886 clientFork = fork();
3889 * If the fork fails - We have to exit so that the rest of the
3890 * script can continue
3894 PrintErrnoError(DtError, smNLS.cantForkClientString);
3899 * Fork succeeded - now kill the parent
3907 * Disassociate from parent
3913 #endif /* __osf__ */
3918 /*************************************<->*************************************
3925 * This routine waits for the window manager to start. It uses a
3926 * resource (waitWmTimeout) with a dynamic default to determine how many
3927 * seconds to wait for WM start and then starts clients.
3932 * appContext = application context for the window
3933 * window = window id for the
3942 *************************************<->***********************************/
3947 XtIntervalId wmTimerId;
3949 XtAddEventHandler(smGD.topLevelWid,
3952 (XtEventHandler)HandleWMClientMessage,
3956 * Set a timer which stops the block on waiting for the
3957 * window manager to start
3960 wmTimerId = XtAppAddTimeOut(smGD.appCon,
3961 smRes.waitWmTimeout,
3962 WaitWMTimeout, NULL);
3964 while((smGD.dtwmRunning == False) && (wmTimeout == False))
3966 XtAppProcessEvent(smGD.appCon, XtIMAll);
3969 XtRemoveTimeOut(wmTimerId);
3970 XtRemoveEventHandler(smGD.topLevelWid,
3973 (XtEventHandler)HandleWMClientMessage,
3977 } /* END OF FUNCTION WaitForWM */
3980 /*************************************<->*************************************
3987 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
3988 * for the window manager to get started.
3997 * wmTimeout = (global) flag that stops the loop
4002 *************************************<->***********************************/
4005 XtPointer client_data,
4010 } /* END OF FUNCTION WaitWMTimeout */
4014 /*************************************<->*************************************
4016 * HandleWMClientMessage
4021 * This is the event handler registered to recieve the client message
4022 * from dtwm when dtwm is ready for business
4025 *************************************<->***********************************/
4027 HandleWMClientMessage( Widget smWidget,
4031 if (event->type == ClientMessage)
4033 ProcessClientMessage(event);
4036 } /* END OF FUNCTION HandleWMClientMessage */
4041 /*************************************<->*************************************
4043 * FixEnvironmentData
4048 * If DISPLAY variable exists in the environment - remove it
4057 * wmTimeout = (global) flag that stops the loop
4062 *************************************<->***********************************/
4064 FixEnvironmentData( void )
4068 extern char **environ; /* MODIFIED - DISPLAY is remove if found. */
4070 for (i=0, ppchar = environ; *ppchar; *ppchar++, i++)
4072 if ((strncmp (*ppchar, DISPLAY_NAME_EQUAL, strlen(DISPLAY_NAME_EQUAL))) == 0)
4075 * Change the DISPLAY environment variable.
4077 for (; *ppchar; *ppchar++, i++)
4079 environ[i]=environ[i+1];
4088 /*************************************<->*************************************
4095 * After one screen is finished - set up the info for the next
4100 * cmdBuf - Buffer that holds all the invocation information
4101 * screen - Pointer to the screen number that we're currently working on
4102 * env - used to set up the environment for changing the display var
4103 * displayName - name of the current display
4107 * cmdBuf - old buffers are freed
4108 * screen - updated to point to the new screen info
4109 * done - tells whether the clients are done being exec'd
4110 * linec - *GLOBAL* sets line being read from
4116 *************************************<->***********************************/
4118 ResetScreenInfo(unsigned char **cmdBuf,
4120 unsigned int *cmdSize,
4125 SM_FREE((char *) cmdBuf[*screen]);
4127 while((cmdSize[*screen] == 0) && (*screen < smGD.numSavedScreens))
4132 if(*screen >= smGD.numSavedScreens)
4138 sprintf((char *)env,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, *screen);
4142 parseP = cmdBuf[*screen];
4148 /*************************************<->*************************************
4150 * RemoteRequestFailed ()
4155 * If a request to the command invoker fails, this callback will be called.
4156 * It will then try to execute the command by performing a remsh on it.
4169 *************************************<->***********************************/
4171 RemoteRequestFailed(char *message,
4174 static char *cmdBuf = NULL;
4175 static char *tmpCmdBuf = NULL;
4176 char *errorString = NULL;
4179 static int cmdBufSize = 0;
4182 RemoteReq *tmpReq = (RemoteReq *) client_data;
4185 * If the memory for the buffer has not been malloced - do so
4189 cmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4192 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4195 cmdBufSize = 200 + 1;
4197 tmpCmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4198 if(tmpCmdBuf == NULL)
4200 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4205 * Copy in the host and command field and execute the command
4208 tmpSize = (strlen(REMOTE_CMD_STRING) +
4209 strlen((char *) tmpReq->hostPtr) +
4210 strlen((char *) tmpReq->cmdPtr) + 1);
4212 if(tmpSize >= cmdBufSize)
4214 cmdBuf = SM_REALLOC(cmdBuf, (tmpSize) * sizeof(char));
4218 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4222 cmdBufSize = tmpSize;
4224 if(tmpCmdBuf != NULL)
4226 tmpCmdBuf = SM_REALLOC(tmpCmdBuf, (tmpSize) * sizeof(char));
4227 if(tmpCmdBuf == NULL)
4229 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4234 sprintf(cmdBuf, REMOTE_CMD_STRING, tmpReq->hostPtr, tmpReq->cmdPtr);
4237 * save cmdBuf for error message, cmdBuf is changed
4238 * by CreateExecString
4240 if (tmpCmdBuf != NULL)
4242 strcpy(tmpCmdBuf,cmdBuf);
4245 CreateExecString(cmdBuf);
4246 if(smExecArray[0] != NULL)
4248 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
4249 NULL, False, False, -1);
4251 if (tmpCmdBuf != NULL)
4253 tmpString = GETMESSAGE(16, 8,
4254 "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");
4257 (char *)SM_MALLOC((strlen(tmpString) +
4258 strlen((char *)tmpReq->hostPtr) +
4259 strlen((char *)tmpReq->cmdPtr) +
4260 strlen(tmpCmdBuf) + 1 ) *
4263 if(errorString == NULL)
4265 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4269 sprintf(errorString, tmpString, tmpReq->hostPtr,
4270 tmpReq->cmdPtr, tmpCmdBuf );
4271 PrintError(DtError, errorString);
4272 SM_FREE(errorString);
4277 * Now check to make sure that this isn't the last remote request.
4278 * If so, free the data
4282 if(numRemoteExecs == 0)
4284 for(i = 0;i < smGD.numSavedScreens;i++)
4286 if(actRemoteSize[i] > 0)
4288 SM_FREE((char *) remoteBuf[i]);
4298 /*************************************<->*************************************
4300 * RemoteRequestSucceeded ()
4305 * If a request to the command invoker succeeds, this callback will be called.
4306 * It decrements the remote execution counter, and frees the info if
4307 * remote executions are finished
4320 *************************************<->***********************************/
4322 RemoteRequestSucceeded(char *message,
4329 if(numRemoteExecs == 0)
4331 for(i = 0;i < smGD.numSavedScreens;i++)
4333 if(actRemoteSize[i] > 0)
4335 SM_FREE((char *) remoteBuf[i]);
4341 /**************************************************************************
4345 **************************************************************************/
4349 char * databaseName)
4352 XSMPClientDBRecPtr pXSMPRec;
4353 ProxyClientDBRecPtr pProxyRec;
4358 if ((inputDB = OpenInputClientDB (databaseName,
4360 &smXSMP.dbSessionId)) == NULL) {
4361 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogError, 1);
4365 if (!smXSMP.dbVersion) {
4366 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 2);
4367 smXSMP.dbVersion = SM_VENDOR_NAME;
4370 if (!smXSMP.dbSessionId) {
4371 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 3);
4372 smXSMP.dbSessionId = SM_RELEASE_NAME;
4376 * First start the XSMP clients
4380 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4383 if (!CheckRequiredProperties (pXSMPRec, databaseName)) {
4384 FreeXSMPClientDBRec (pXSMPRec);
4388 if (StartXSMPClient (pXSMPRec, databaseName)) {
4390 XSMPClientDBRecPtr tmpRecPtr;
4392 pXSMPRec->next = NULL;
4394 if (!smXSMP.xsmpDbList) {
4395 smXSMP.xsmpDbList = pXSMPRec;
4400 * Find the end of the list
4402 for (tmpRecPtr = smXSMP.xsmpDbList;
4403 tmpRecPtr && tmpRecPtr->next != NULL;
4404 tmpRecPtr = tmpRecPtr->next);
4406 tmpRecPtr->next = pXSMPRec;
4409 FreeXSMPClientDBRec (pXSMPRec);
4413 * Now start the Proxy clients
4415 for (i = 0; ; i++) {
4417 if ((pProxyRec = GetProxyClientDBRec (inputDB)) == NULL)
4420 if (!CheckRequiredFields (pProxyRec, databaseName, i)) {
4421 FreeProxyClientDBRec (pProxyRec);
4425 (void) StartProxyClient (pProxyRec);
4427 FreeProxyClientDBRec (pProxyRec);
4430 (void) CloseClientDB (inputDB, False);
4438 XSMPClientDBRecPtr pDbRec,
4439 char * databaseName)
4441 return (StartClient (pDbRec->restartCommand[0],
4442 pDbRec->restartCommand,
4445 pDbRec->environment,
4448 pDbRec->screenNum));
4454 ProxyClientDBRecPtr pDbRec)
4456 return (StartClient (pDbRec->command[0],
4463 pDbRec->screenNum));
4468 ExecuteCommandProperty (
4470 ClientRecPtr pClientRec)
4473 char ** envp = NULL;
4475 PropertyRecPtr pPropRec;
4479 if ((pPropRec = GetPropertyRec (pClientRec, commandName)) == NULL)
4482 argv = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4487 for (i = 0; i < pPropRec->prop.num_vals; i++)
4488 argv[i] = pPropRec->prop.vals[i].value;
4489 argv[pPropRec->prop.num_vals] = NULL;
4491 cwd = GetArrayPropertyValue (pClientRec, SmCurrentDirectory);
4494 if ((pPropRec = GetPropertyRec (pClientRec, SmEnvironment)) != NULL) {
4495 envp = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4500 for (i = 0; i < pPropRec->prop.num_vals; i++)
4501 envp[i] = pPropRec->prop.vals[i].value;
4502 envp[pPropRec->prop.num_vals] = NULL;
4505 retValue = StartClient (argv[0], argv,
4506 pClientRec->clientHost,
4509 pClientRec->screenNum);
4511 XtFree ((char *) argv);
4513 XtFree ((char *) envp);
4519 /*************************************<->*************************************
4521 * ExecuteDiscardCommands -
4523 * Description: Executes all of the DiscardCommand properties in the
4524 * given client database
4528 *************************************<->***********************************/
4530 ExecuteDiscardCommands (
4534 XSMPClientDBRecPtr pXSMPRec;
4535 char * version = NULL;
4539 if ((inputDB = OpenInputClientDB (db, &version, &id )) == NULL) {
4540 str = strdup ((char *) GETMESSAGE (40, 26,
4541 "The following client database cannot be opened:\n\n %s\n\nThe 'DiscardCommand' properties cannot be run."));
4544 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str, db);
4550 XtFree ((char *) version);
4552 XtFree ((char *) id);
4555 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4558 if (!pXSMPRec->discardCommand)
4561 if (!StartClient (pXSMPRec->discardCommand[0],
4562 pXSMPRec->discardCommand,
4563 pXSMPRec->clientHost,
4565 pXSMPRec->environment,
4568 pXSMPRec->screenNum)) {
4569 str = strdup ((char *) GETMESSAGE (40, 27,
4570 "An attempt to execute the 'DiscardCommand' property for\napplication '%s' failed."));
4573 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
4578 FreeXSMPClientDBRec (pXSMPRec);
4581 (void) CloseClientDB (inputDB, False);
4586 CheckRequiredProperties (
4587 XSMPClientDBRecPtr pDbRec,
4588 char * databaseName)
4590 Boolean propsOK = True;
4592 if (!pDbRec->program) {
4593 LogMissingPropertyMessage (pDbRec, SmProgram,
4594 databaseName, DtMsgLogError);
4598 if (!pDbRec->restartCommand) {
4599 LogMissingPropertyMessage (pDbRec, SmRestartCommand,
4600 databaseName, DtMsgLogError);
4609 CheckRequiredFields (
4610 ProxyClientDBRecPtr pDbRec,
4611 char * databaseName,
4616 if (!pDbRec->command) {
4618 message = strdup ((char *) GETMESSAGE (40, 11,
4619 "The required resource '%s' is missing for client '%d'\nin the file '%s'."));
4624 DtMsgLogMessage (smGD.programName, DtMsgLogError, message,
4625 SmProgram, clientNum, databaseName);
4637 LogXSMPOpenDatabaseFailure (
4638 char * databaseName,
4639 DtMsgLogType msgType,
4642 char * message = NULL;
4647 case 1: data = databaseName;
4649 message = strdup ((char *) GETMESSAGE (40, msgNum,
4650 "The following session database could not be opened:\n\n '%s'"));
4653 case 2: data = versionStr;
4655 message = strdup ((char *) GETMESSAGE (40, msgNum,
4656 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4659 case 3: data = dtsessionIDStr;
4661 message = strdup ((char *) GETMESSAGE (40, msgNum,
4662 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4670 DtMsgLogMessage (smGD.programName, msgType, message, data);
4672 DtMsgLogMessage (smGD.programName, msgType, message,
4673 data, databaseName);
4680 LogMissingPropertyMessage (
4681 XSMPClientDBRecPtr pDbRec,
4683 char * databaseName,
4684 DtMsgLogType msgType)
4688 message = strdup ((char *) GETMESSAGE (40, 10,
4689 "The required property '%s' is missing for client\n\n %s\n\nin the file '%s'."));
4694 DtMsgLogMessage (smGD.programName, msgType, message,
4695 propName, pDbRec->clientId, databaseName);
4709 message = strdup ((char *) GETMESSAGE (40, 12,
4710 "The directory '%s'\nis not available for application '%s'.\n\nThe following directory will be used:\n\n %s"));
4715 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, message,
4716 badDir, appName, goodDir);
4723 char ** RemoveEnvironmentVars (
4727 char ** retEnv = NULL;
4728 char **ppchar, **ppchar2;
4735 for (count = 0, ppchar = envp; ppchar && *ppchar; count++, *ppchar++) ;
4737 retEnv = (char **) XtMalloc ((count + 1) * sizeof (char *));
4741 if (!ignoreEnvPtr) {
4742 for (count = 0, ppchar = envp; ppchar && *ppchar;
4743 count++, *ppchar++) {
4744 retEnv[count] = *ppchar;
4746 retEnv[count] = NULL;
4751 for (count = 0, ppchar = envp; ppchar && *ppchar; *ppchar++) {
4755 for (ppchar2 = ignoreEnvPtr; ppchar2 && *ppchar2; *ppchar2++) {
4757 if ((!strncmp (*ppchar, *ppchar2, strlen (*ppchar2))) &&
4758 (((*ppchar)[strlen(*ppchar2)]) == '=')) {
4764 retEnv[count] = *ppchar;
4768 retEnv[count] = NULL;
4774 * MarkFileDescriptors - mark file descriptiors start_fd through open_max
4775 * with the given "cmd" and "data".
4777 * The code for calculating open_max was taken from DtSvc/DtUtil1/CmdMain.c
4780 MarkFileDescriptors (
4788 open_max = sysconf(_SC_OPEN_MAX);
4790 if (open_max == -1) {
4794 #if defined(USL) || defined(__uxp__) || defined(_AIX)
4795 open_max = FOPEN_MAX;
4797 open_max = FD_SETSIZE;
4799 #endif /* _SUN_OS */
4802 for (i = start_fd; i < open_max; i++)
4803 (void) fcntl (i, cmd, data);