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>
67 #include <sys/socket.h>
69 #include <netinet/in.h>
74 #include <X11/Intrinsic.h>
75 #include <X11/Xutil.h>
76 #include <X11/Xatom.h>
77 #include <X11/StringDefs.h>
78 #include <X11/keysymdef.h>
79 #include <X11/SM/SMlib.h>
83 # define Va_start(a,b) va_start(a,b)
86 #include <Dt/Message.h>
87 #include <Dt/CommandM.h>
88 #include <Dt/Connect.h>
91 #include <Dt/UserMsg.h>
92 #include <Dt/SessionM.h>
93 #include <Dt/EnvControlP.h>
94 #include <Dt/Utility.h>
95 #include <Dt/MsgLog.h>
97 #include <Dt/CmdInv.h>
98 #include <Dt/ActionUtilP.h>
101 #include "SmResource.h"
103 #include "SmCommun.h"
104 #include "SmRestore.h"
105 #include "SmProtocol.h"
106 #include "SmConMgmt.h"
109 #include "SmGlobals.h"
114 #include <X11/Xlibint.h>
119 static const char * DISPLAY_NAME_EQUAL = "DISPLAY=";
120 static const char * DISPLAY_NAME = "DISPLAY";
121 static char * savedDisplay = NULL;
127 #define MAXPATHSM 1023
128 #define MAX_QUOTE_DEPTH 10
130 #define SM_MAX_ARGS MAXLINE
133 #define REMOTE_CMD_STRING "rsh %s -n %s &"
135 #define REMOTE_CMD_STRING "remsh %s -n %s &"
144 unsigned char *hostPtr;
145 unsigned char *cmdPtr;
149 * Variables global to this module only
151 static XtResource settingsResources[] =
153 {SmNaccelNum, SmCaccelNum, XtRInt, sizeof(int),
154 XtOffset(SessionSettingsPtr, accelNum),
155 XtRImmediate, (XtPointer) -1},
156 {SmNaccelDenom, SmCaccelDenom, XtRInt, sizeof(int),
157 XtOffset(SessionSettingsPtr, accelDenom),
158 XtRImmediate, (XtPointer) -1},
159 {SmNthreshold, SmCthreshold, XtRInt, sizeof(int),
160 XtOffset(SessionSettingsPtr, threshold),
161 XtRImmediate, (XtPointer) -1},
163 {SmNtimeout, SmCtimeout, XtRInt, sizeof(int),
164 XtOffset(SessionSettingsPtr, timeout),
165 XtRImmediate, (XtPointer) -1},
166 {SmNinterval, SmCinterval, XtRInt, sizeof(int),
167 XtOffset(SessionSettingsPtr, interval),
168 XtRImmediate, (XtPointer) -1},
169 {SmNpreferBlank, SmCpreferBlank, XtRInt, sizeof(int),
170 XtOffset(SessionSettingsPtr, preferBlank),
171 XtRImmediate, (XtPointer) 0},
172 {SmNallowExp, SmCallowExp, XtRInt, sizeof(int),
173 XtOffset(SessionSettingsPtr, allowExp),
174 XtRImmediate, (XtPointer) 0},
176 {SmNfontPath, SmCfontPath, XtRString, sizeof(String),
177 XtOffset(SessionSettingsPtr, fontDirs), XtRString, (XtPointer) ""},
179 {SmNkeyClick, SmCkeyClick, XtRInt, sizeof(int),
180 XtOffset(SessionSettingsPtr, kbdState.key_click_percent),
181 XtRImmediate, (XtPointer) -1},
182 {SmNbellPercent, SmCbellPercent, XtRInt, sizeof(int),
183 XtOffset(SessionSettingsPtr, kbdState.bell_percent),
184 XtRImmediate, (XtPointer) -1},
185 {SmNbellPitch, SmCbellPitch, XtRInt, sizeof(int),
186 XtOffset(SessionSettingsPtr, kbdState.bell_pitch),
187 XtRImmediate, (XtPointer) -1},
188 {SmNbellDuration, SmCbellDuration, XtRInt, sizeof(int),
189 XtOffset(SessionSettingsPtr, kbdState.bell_duration),
190 XtRImmediate, (XtPointer) -1},
191 {SmNledMask, SmCledMask, XtRInt, sizeof(int),
192 XtOffset(SessionSettingsPtr, kbdState.led_mask),
193 XtRImmediate, (XtPointer) 0},
194 {SmNglobalRepeats, SmCglobalRepeats, XtRInt, sizeof(int),
195 XtOffset(SessionSettingsPtr, kbdState.global_auto_repeat),
196 XtRImmediate, (XtPointer) 2},
197 {SmNautoRepeats, SmCautoRepeats, XtRString, sizeof(String),
198 XtOffset(SessionSettingsPtr, autoRepeats), XtRString, (XtPointer) ""},
200 {SmNbuttonMap, SmCbuttonMap, XtRString, sizeof(String),
201 XtOffset(SessionSettingsPtr, buttonMap), XtRString, (XtPointer) ""},
203 {SmNnumKeyCode, SmCnumKeyCode, XtRInt, sizeof(int),
204 XtOffset(SessionSettingsPtr, numKeyCode), XtRImmediate, (XtPointer) 0},
205 {SmNkeySymsPerKey, SmCkeySymsPerKey, XtRInt, sizeof(int),
206 XtOffset(SessionSettingsPtr, keySymPerCode),
207 XtRImmediate, (XtPointer) 0},
208 {SmNkeySyms, SmCkeySyms, XtRString, sizeof(String),
209 XtOffset(SessionSettingsPtr, keySyms), XtRString, (XtPointer) ""},
211 {SmNmaxKeyPerMod, SmCmaxKeyPerMod, XtRInt, sizeof(int),
212 XtOffset(SessionSettingsPtr, maxKeyPerMod),
213 XtRImmediate, (XtPointer) 0},
214 {SmNmodMap, SmCmodMap, XtRString, sizeof(String),
215 XtOffset(SessionSettingsPtr, modSyms),
216 XtRString, (XtPointer) ""},
218 {SmNdidQuerySettings, SmCdidQuerySettings, XtRBoolean, sizeof(Boolean),
219 XtOffset(SessionSettingsPtr, didQuery),
220 XtRImmediate, (XtPointer) False},
221 {SmNshutDownState, SmCshutDownState, XtRInt, sizeof(int),
222 XtOffset(SessionSettingsPtr, confirmMode),
223 XtRImmediate, (XtPointer) 1},
224 {SmNshutDownMode, SmCshutDownMode, XtRInt, sizeof(int),
225 XtOffset(SessionSettingsPtr, startState),
226 XtRImmediate, (XtPointer) 4},
230 * Variables used for parsing code
233 static unsigned char fallBackLine[MAXLINE+2]; /* line buffer */
234 static unsigned char *line; /* line buffer */
235 static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
236 static int linec = 0; /* line counter for parser */
237 static unsigned char *parseP = NULL; /* pointer to parse string */
238 static int fileSize = 0;
239 char **smExecArray = NULL;
242 * Variables used for remote execution
244 static int numRemoteExecs = 0;
245 unsigned char *remoteBuf[MAX_SCREENS_SAVED];
246 unsigned int actRemoteSize[MAX_SCREENS_SAVED];
247 RemoteReq remoteBufPtr[MAX_REMOTE_CLIENTS];
248 static char localHost[MAXHOSTNAMELEN];
249 static char ** ignoreEnvPtr = NULL;
252 * Timeout for workspace manager handshake
254 static Boolean wmTimeout;
257 * These lines were added to support the builtin
261 char tmpExecWmFile[MAXPATHSM+1];
262 static Boolean localWmLaunched = False;
265 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
266 * End of lines were added to support the builtin
281 "*XmTextField*FontList",
282 "*DtEditor*textFontList",
287 static char *fontclass[] = {
295 "*XmTextField*FontList",
296 "*DtEditor*textFontList",
305 static int RestoreSettings( void ) ;
306 static int RestoreClients( void ) ;
307 static unsigned char * GetNextLine( void ) ;
308 static unsigned int PeekAhead( unsigned char *, unsigned int ) ;
309 static unsigned char * GetSmartString( unsigned char **) ;
310 static void ForkWM( void ) ;
311 static int FillCmdBuf( unsigned char *, unsigned char **,
312 unsigned int *, unsigned int *,
313 unsigned int, unsigned int *) ;
314 static int FillRemoteBuf( unsigned char *, unsigned char *,
315 unsigned char *, unsigned char **,
316 unsigned int *, unsigned int *, unsigned int) ;
317 static int FillHintBuf(unsigned char *, unsigned char **,
318 unsigned int *, unsigned int *,
319 unsigned int, unsigned int *);
320 static void WaitForWM( void ) ;
321 static void HandleWMClientMessage(Widget smWidget, XtPointer dummy,
323 static void WaitWMTimeout( XtPointer , XtIntervalId *) ;
324 static void FixEnvironmentData( void ) ;
325 static void ResetScreenInfo(unsigned char **,
326 int *, unsigned int *,
329 static void RemoteRequestFailed(char *, void *);
330 static void RemoteRequestSucceeded(char *, void *);
332 static void SetTemporaryDisplay (
335 int RestorePreferences(char *filename);
337 static void RestoreDisplay (
340 static Boolean StartLocalClient (
346 Boolean useIgnoreEnvResource);
348 static Boolean StartRemoteClient (
354 Boolean useIgnoreEnvResource);
356 static Boolean CheckRequiredProperties (
357 XSMPClientDBRecPtr pDbRec,
358 char * databaseName);
360 static Boolean CheckRequiredFields (
361 ProxyClientDBRecPtr pDbRec,
365 static void LogXSMPOpenDatabaseFailure (
367 DtMsgLogType msgType,
370 static void LogMissingPropertyMessage (
371 XSMPClientDBRecPtr pDbRec,
374 DtMsgLogType msgType);
376 static void LogCWDMessage (
381 static char ** RemoveEnvironmentVars (
384 static void MarkFileDescriptors (
390 /*************************************<->*************************************
397 * Sets _DT_SM_STATE_INFO for dtstyle indicating compatibility mode
410 * The only thing dtstyle should be looking at is the compatMode
412 *************************************<->***********************************/
414 SetCompatState( void )
419 * BEFORE any clients are started
420 * set a property on the top level window
421 * which lets the style manager know what state the sm is in
423 state.flags = SM_STATE_ALL;
424 state.smStartState = 0;
425 state.smConfirmMode = 0;
426 state.smCompatMode = True;
427 state.smSendSettings = False;
428 state.smCoverScreen = True;
429 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
430 state.smCycleTimeout = 0;
431 state.smLockTimeout = 0;
432 state.smSaverTimeout = 0;
434 state.smDisplaySpecific = smGD.displaySpecific;
436 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
438 XFlush(smGD.display);
442 } /* END OF FUNCTION SetCompatState */
445 /*************************************<->*************************************
452 * This function fiddles with our signal handling and calls the
453 * system() function to invoke a unix command.
458 * pchCmd = string with the command we want to exec.
466 * The system() command is touchy about the SIGCLD behavior. Restore
467 * the default SIGCLD handler during the time we run system().
469 *************************************<->***********************************/
472 SystemCmd (char *pchCmd)
474 void (*signalHandler) ();
476 signalHandler = (void (*)())signal (SIGCHLD, SIG_DFL);
480 signal (SIGCHLD, signalHandler);
481 } /* END OF FUNTION SystemCmd */
485 /*************************************<->*************************************
501 * When this routine is finished, all settings and resources will be restored.
502 * Clients may not be, as they are actually restored by different processes.
504 *************************************<->***********************************/
510 char convertCommand[MAXPATHSM+1];
512 Boolean fixedBuffer = False;
515 Boolean useXrmDB = False;
518 * Restore all the X settings which were active at the time of shutdown
522 if (smGD.sessionType == HOME_SESSION)
523 smSettings.startState = DtSM_HOME_STATE;
525 smSettings.startState = DtSM_CURRENT_STATE;
528 * BEFORE any clients are started
529 * set a property on the top level window
530 * which lets the style manager know what state the sm is in
532 state.flags = SM_STATE_ALL;
533 state.smStartState = smSettings.startState;
534 state.smConfirmMode = smSettings.confirmMode;
535 state.smCompatMode = smGD.compatMode;
536 state.smSendSettings = !smRes.querySettings;
537 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
538 state.smCycleTimeout = smSaverRes.cycleTimeout;
539 state.smLockTimeout = smSaverRes.lockTimeout;
540 state.smSaverTimeout = smSaverRes.saverTimeout;
541 state.smRandom = smSaverRes.random;
542 state.smDisplaySpecific = smGD.displaySpecific;
544 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
546 saver.saverList = smGD.saverList;
547 _DtSetSmSaver(smGD.display, smGD.topLevelWindow, &saver);
550 * Set up the Property telling all applications what session is being
553 XaSmRestoreMode = XInternAtom(smGD.display, _XA_DT_RESTORE_MODE, False);
554 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
555 XaSmRestoreMode, XA_STRING, 8, PropModeReplace,
556 (unsigned char *)smGD.restoreSession, strlen(smGD.restoreSession));
557 XFlush(smGD.display);
560 * Check the session database and either parse it as an
561 * Xrm-database or the CDE1.0 format
563 if ((pchar = strrchr (smGD.clientPath, '/')) != NULL)
566 if ((*pchar != '\0') && (!strcmp (pchar, SM_CLIENT_FILE2)))
572 return (StartXSMPSession (smGD.clientPath));
576 * Malloc line for parsing.
578 status = stat(smGD.clientPath, &buf);
581 fileSize = buf.st_size;
584 if (fileSize < MAXLINE + 1)
586 fileSize = MAXLINE + 1;
589 line = malloc(fileSize + 1);
593 fileSize = MAXLINE + 1;
596 cfileP = fopen(smGD.clientPath, "r");
599 PrintErrnoError(DtError, smNLS.cantOpenFileString);
600 if (!fixedBuffer && line)
602 SM_FREE((char *)line);
609 if (!fixedBuffer && line)
611 SM_FREE((char *)line);
620 /*************************************<->*************************************
627 * Start up the window manager. The default is to start dtmwm unless
628 * another one is specified in a resource.
641 * When this routine is finished, all settings and resources will be restored.
642 * Clients may not be, as they are actually restored by different processes.
644 *************************************<->***********************************/
648 char wmStartupErrorString[(2 * MAXPATHSM) + 1];
649 char localWmErrorString[(2 * MAXPATHSM) + 1];
650 Boolean goodWmStartup = True;
653 if((smGD.wmStartup == NULL) || (*smGD.wmStartup == 0))
659 CreateExecString(smGD.wmStartup);
662 * check to see if the wmStartup string exists and is
665 status = access(smExecArray[0], F_OK | X_OK);
668 goodWmStartup = False;
669 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
672 if(smExecArray[0] != NULL)
674 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
675 NULL, False, False, -1);
680 * We used to start the message server before the window
681 * manager and then if the message server did not start
682 * we would exit. Now we start the window manager, then
683 * start the message server and then wait for the window
684 * manager. This seems to improve performance.
689 if (goodWmStartup == False)
691 sprintf(wmStartupErrorString, GETMESSAGE(16, 7,
692 "The wmStartupCommand resource is set to:\n\n"
694 "This file does not exist or is not executable.\n"
695 CDE_INSTALLATION_TOP "/bin/dtwm will be started "
698 PrintError(DtError, wmStartupErrorString);
704 * These lines were added to support the builtin
708 if (localWmLaunched && wmTimeout)
710 if (!smGD.userSetWaitWmTimeout)
712 smRes.waitWmTimeout = smGD.savedWaitWmTimeout;
715 localWmLaunched = False;
717 * A special version of a built-in Xterminal dtwm
718 * was attempted and failed.
719 * Try to launch .../dt/bin/dtwm instead
722 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
723 if(smExecArray[0] != NULL)
725 (void) StartClient(smExecArray[0], smExecArray, NULL,
726 NULL, NULL, False, False, -1);
729 sprintf(localWmErrorString, GETMESSAGE(16, 9,
730 "The following window manager did not start:\n\n"
732 "This message indicates you tried to start a\n"
733 "window manager that is built into an X terminal.\n"
734 "This will only work with X terminals that support this protocol.\n"
735 CDE_INSTALLATION_TOP "/bin/dtwm will be started instead.\n"),
737 PrintError(DtError, localWmErrorString);
740 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
741 * End of lines were added to support the builtin
750 /*************************************<->*************************************
757 * Reloads RESOURCE_MANAGER during running session
769 *************************************<->***********************************/
772 ReloadResources(void)
775 * Load sys.resources and .Xdefaults
777 RestoreResources(True,
784 * Merge _DT_SM_PREFERENCES
786 RestorePreferences(NULL);
792 /*************************************<->*************************************
794 * RestoreResources (errorHandlerInstalled, options ... )
799 * Calls routines responsible for restoring resources.
800 * Resources are restored by a fork and exec of dtsession_res.
813 * When this routine is finished, all settings and resources will be restored.
814 * Clients may not be, as they are actually restored by different processes.
816 *************************************<->***********************************/
819 RestoreResources( Boolean errorHandlerInstalled, ... )
822 int childStatus, execStatus, i;
828 /* JET - this seems like a bad (and unused) idea */
830 * Check for alternate resource loader.
832 if ((pgrm = getenv("DTLOADRESOURCES")) == NULL)
834 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
837 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
841 * By convention, exec() wants arg0 to be the program name. Ex: if pgrm
842 * is /usr/dt/bin/dtsession_res, the program name is dtsession_res.
843 * If all else fails, use pgrm.
845 argv[0] = (p = strrchr(pgrm, '/')) != NULL && *(p+1) != '\0' ? p+1 : pgrm;
848 Va_start(args,errorHandlerInstalled);
852 argv[i] = va_arg(args, char *);
858 * if an error handler is installed - remove it
860 if(errorHandlerInstalled)
862 sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
866 * Fork and exec the xrdb process to load in the file created by
867 * writing out the resource manager string generated by the last
868 * session termination.
871 for(i = 0;(i < 10) && ((forkrc = vfork()) < 0);i++)
882 PrintErrnoError(DtError, smNLS.cantForkClientString);
887 * Fork succeeded - now do the exec
891 SetSIGPIPEToDefault ();
895 * Set the gid of the process back from bin
898 setregid(smGD.runningGID, smGD.runningGID);
900 setgid(smGD.runningGID);
901 setegid(smGD.runningGID);
904 #if defined(CSRG_BASED)
908 #endif /* CSRG_BASED */
910 MarkFileDescriptors (3, F_SETFD, 1);
912 execStatus = execv(pgrm, argv);
916 char clientMessage[MAXPATHLEN + 256];
918 memset(clientMessage, 0, MAXPATHLEN + 256);
919 snprintf(clientMessage, (MAXPATHLEN + 256) - 1,
920 ((char *)GETMESSAGE(16, 1, "Unable to exec process %s. No session resources will be restored.")), pgrm);
921 PrintErrnoError(DtError, clientMessage);
926 while(wait(&childStatus) != forkrc);
929 * if an error handler is installed - remove it
931 if(errorHandlerInstalled)
933 sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
940 /*************************************<->*************************************
942 * RestorePreferences ( filename)
948 * This routine has two roles:
950 * 1) If 'filename' specified, the content of filename is read, and
951 * _DT_SM_PREFERENCES is populated with its content. This is used
952 * at session startup to set the initial state of _DT_SM_PREFERENCES.
954 * 2) If 'filename' is NULL, the content of _DT_SM_PREFERENCES is
955 * merged into RESOURCE_MANAGER. This is used when resources are
956 * reloaded at user request during a session.
969 *************************************<->***********************************/
981 struct stat statinfo;
983 if(access(filename,R_OK) != 0)
989 * Determine size of file.
991 if (stat(filename, &statinfo) == -1)
999 if ((data = (char *)SM_MALLOC(statinfo.st_size + 1)) == NULL)
1005 * Read file into memory.
1007 if ((fp = fopen(filename, "r")) == NULL)
1013 size = fread(data, 1, statinfo.st_size, fp);
1015 if (size == statinfo.st_size)
1018 * Merge .Xdefaults string into RESOURCE_MANAGER database, and
1019 * also convert to Xrm database form for later subtraction.
1022 _DtAddResString(smGD.display, data, _DT_ATR_PREFS);
1030 * Read string from _DT_SM_PREFERENCES
1032 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1035 * Merge string into RESOURCE_MANAGER
1037 _DtAddResString(smGD.display, data, _DT_ATR_RESMGR);
1046 /*************************************<->*************************************
1048 * RestoreSettings ()
1053 * In charge of restoring all settings. Settings are stored in resource
1054 * format so it gets the values by getting the resource values stored in
1055 * a resource file that was created by the session manager.
1060 * smGD.settingPath = path that points to the settings resource file.
1069 * This routine messes with the actual strings returned by the resource
1070 * manager by tokenizing them, so these session settings resources should
1071 * not be accessed again.
1073 *************************************<->***********************************/
1075 RestoreSettings( void )
1077 XrmDatabase smBase = NULL;
1078 XKeyboardControl kbdControl;
1080 char **restorePtrArray, **tmpRestore;
1081 char *restoreCharArray;
1082 int numArgs, ptrSize, charSize;
1085 KeySym *tmpSyms, codeSym;
1088 XModifierKeymap restoreMod;
1092 restorePtrArray = (char **) SM_MALLOC (ptrSize * sizeof(char *));
1093 restoreCharArray = (char *) SM_MALLOC (charSize * sizeof(char));
1094 if((restorePtrArray == NULL) || (restoreCharArray == NULL))
1096 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1098 if(restorePtrArray != NULL)
1100 SM_FREE((char *) restorePtrArray);
1104 if(restoreCharArray != NULL)
1106 SM_FREE(restoreCharArray);
1113 * Load the resources from the SM database file
1115 if (smGD.settingPath[0] != 0)
1117 smBase = XrmGetFileDatabase(smGD.settingPath);
1121 PrintError(DtError, GETMESSAGE(16, 2, "Invalid client settings file. No settings restored."));
1126 XrmMergeDatabases(smBase, &(smGD.display->db));
1131 * Retrieve the session settings file from the database
1133 XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smSettings,
1134 settingsResources, XtNumber(settingsResources),
1138 * Copy any string resources since they may be overwritten in
1141 smGD.fontDirs = SmNewString(smSettings.fontDirs);
1142 smGD.autoRepeats = SmNewString(smSettings.autoRepeats);
1143 smGD.buttonMap = SmNewString(smSettings.buttonMap);
1144 smGD.keySyms = SmNewString(smSettings.keySyms);
1145 smGD.modSyms = SmNewString(smSettings.modSyms);
1149 * This is provided for backward compatibility sake. The values that
1150 * confirmMode can take have changed
1152 if(smSettings.confirmMode == DtSM_ASK_STATE)
1154 smSettings.confirmMode = DtSM_VERBOSE_MODE;
1158 * If the user has previously used the "query" method, and now wishes
1159 * to use "only what I've customized" method, then we have to start
1160 * from scratch. So don't set anything until customizer tells me to
1162 if((smSettings.didQuery == True) && (smRes.querySettings == False))
1164 SM_FREE((char *) restorePtrArray);
1165 SM_FREE(restoreCharArray);
1170 * Restore pointer control settings
1172 if((smSettings.accelNum > -1 ) || (smSettings.threshold > -1))
1174 XChangePointerControl(smGD.display, True, True,
1175 smSettings.accelNum,
1176 smSettings.accelDenom,
1177 smSettings.threshold);
1178 smToSet.pointerChange = True;
1182 smToSet.pointerChange = False;
1186 * Restore screen saver settings if any are set to non-default
1189 if ((smSettings.timeout > -1) || (smSettings.interval > -1) ||
1190 (smSaverRes.saverTimeout > -1) || (smSaverRes.lockTimeout > -1) ||
1191 (smSaverRes.cycleTimeout > -1))
1195 * For the time between Screen Savers, use the cycleTimeout
1196 * if the user has set this value. Otherwise, use the interval
1197 * value that was set when the session was saved.
1199 if (smSaverRes.cycleTimeout < 0)
1201 screenSaverVals.smInterval = smSettings.interval;
1205 screenSaverVals.smInterval = smSaverRes.cycleTimeout;
1209 * For the screen saver time, use the minimum of the values set for
1210 * saverTimeout or lockTimeout if the user has set one of these
1213 * Otherwise, use the Timeout value that was set when the
1214 * session was saved.
1216 * If it is not set, then use the minimum of the values set for
1217 * saverTimeout or lockTimeout. Set timeout to the Timeout value
1220 if ((smSaverRes.saverTimeout > -1) ||
1221 (smSaverRes.lockTimeout > -1))
1223 if (smSaverRes.saverTimeout > -1)
1225 if ((smSaverRes.lockTimeout > -1) &&
1226 (smSaverRes.lockTimeout < smSaverRes.saverTimeout))
1228 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1232 screenSaverVals.smTimeout = smSaverRes.saverTimeout;
1237 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1242 screenSaverVals.smTimeout = smSettings.timeout;
1244 screenSaverVals.smPreferBlank = smSettings.preferBlank;
1245 screenSaverVals.smAllowExp = smSettings.allowExp;
1247 /* Notify X of the new screen saver values */
1248 XSetScreenSaver(smGD.display, screenSaverVals.smTimeout,
1249 screenSaverVals.smInterval,
1250 screenSaverVals.smPreferBlank,
1251 screenSaverVals.smAllowExp);
1254 * If using timeout or interval values that were
1255 * previously saved, then set flag to indicate that they
1256 * should be saved again when the state for the session
1259 if ((smSettings.timeout > -1) || (smSettings.interval > -1))
1261 smToSet.screenSavChange = True;
1265 smToSet.screenSavChange = False;
1271 smToSet.screenSavChange = False;
1275 * Get the font path. Then set it.
1277 tmpRestore = restorePtrArray;
1279 *tmpRestore = strtok(smGD.fontDirs, ",");
1281 while(*tmpRestore != NULL)
1283 numArgs++; tmpRestore++;
1284 *tmpRestore = strtok(NULL, ",");
1285 if((numArgs >= ptrSize) && (*tmpRestore != NULL))
1288 restorePtrArray = (char **)SM_REALLOC((char *)
1289 restorePtrArray, ptrSize *
1291 if(restorePtrArray == NULL)
1293 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1294 SM_FREE(restoreCharArray);
1302 XSetFontPath(smGD.display, restorePtrArray, numArgs);
1306 * Restore the keyboard control information. In order for it
1307 * to be restored it has to be changed from a XKeyboardState
1308 * format to an XKeyboardControl format.
1310 if((smSettings.kbdState.key_click_percent > -1) ||
1311 (smSettings.kbdState.bell_percent > -1) ||
1312 (smSettings.kbdState.bell_pitch > -1) ||
1313 (smSettings.kbdState.bell_duration > -1))
1317 if((smSettings.kbdState.bell_percent > -1) ||
1318 (smSettings.kbdState.bell_pitch > -1) ||
1319 (smSettings.kbdState.bell_duration > -1))
1321 kbdControl.bell_percent = smSettings.kbdState.bell_percent;
1322 kbdControl.bell_pitch = smSettings.kbdState.bell_pitch;
1323 kbdControl.bell_duration = smSettings.kbdState.bell_duration;
1324 kbdControlMask |= (KBBellPercent | KBBellPitch | KBBellDuration);
1325 smToSet.audioChange = True;
1326 audioVals.smBellPercent = smSettings.kbdState.bell_percent;
1327 audioVals.smBellPitch = smSettings.kbdState.bell_pitch;
1328 audioVals.smBellDuration = smSettings.kbdState.bell_duration;
1332 smToSet.audioChange = False;
1335 if((smSettings.kbdState.key_click_percent > -1) ||
1336 (smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn))
1338 kbdControl.key_click_percent =
1339 smSettings.kbdState.key_click_percent;
1340 kbdControlMask |= KBKeyClickPercent;
1341 smToSet.keyboardChange = True;
1342 keyboardVals.smKeyClickPercent = kbdControl.key_click_percent;
1346 smToSet.keyboardChange = False;
1351 * NOTICE THAT THE LED'S DON'T GET RESET. THIS IS BECAUSE LED STUFF
1352 * IS MACHINE DEPENDENT.
1355 * Set the auto repeat stuff
1357 tmpKey = strtok(smGD.autoRepeats, ",");
1358 if((tmpKey == NULL) &&
1359 ((smSettings.kbdState.global_auto_repeat == AutoRepeatModeOff) ||
1360 (smSettings.kbdState.global_auto_repeat == AutoRepeatModeOn)))
1362 smToSet.keyboardChange = True;
1363 kbdControl.auto_repeat_mode =
1364 smSettings.kbdState.global_auto_repeat;
1365 kbdControlMask |= KBAutoRepeatMode;
1366 XChangeKeyboardControl(smGD.display, kbdControlMask, &kbdControl);
1367 keyboardVals.smGlobalAutoRepeat =
1368 smSettings.kbdState.global_auto_repeat;
1374 smToSet.keyboardChange = True;
1375 kbdControl.auto_repeat_mode = smSettings.kbdState.global_auto_repeat;
1376 kbdControlMask |= KBAutoRepeatMode;
1377 XChangeKeyboardControl(smGD.display,
1378 kbdControlMask, &kbdControl);
1379 kbdControl.auto_repeat_mode = AutoRepeatModeOn;
1380 kbdControlMask = KBAutoRepeatMode | KBKey;
1382 * This is only involked when there is auto repeats set for
1383 * specific keys only. It is VERY SLOW code so unless you
1384 * have to save off auto repeats for single keys - DON'T
1386 while(tmpKey != NULL)
1388 kbdControl.key = atoi(tmpKey);
1389 XChangeKeyboardControl(smGD.display,
1390 kbdControlMask, &kbdControl);
1391 tmpKey = strtok(NULL, ",");
1396 if(kbdControlMask != 0)
1398 XChangeKeyboardControl(smGD.display,
1399 kbdControlMask, &kbdControl);
1406 smToSet.audioChange = False;
1407 smToSet.keyboardChange = False;
1411 * Restore the button mappings
1414 tmpKey = strtok(smGD.buttonMap, ",");
1418 smToSet.pointerMapChange = True;
1422 smToSet.pointerMapChange = False;
1425 while(tmpKey != NULL)
1427 restoreCharArray[numArgs] = (char) atoi(tmpKey);
1429 tmpKey = strtok(NULL, ",");
1430 if((numArgs >= charSize) && (tmpKey != NULL))
1433 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1434 charSize * sizeof(char));
1435 if(restoreCharArray == NULL)
1437 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1438 SM_FREE((char *)restorePtrArray);
1446 XSetPointerMapping(smGD.display, (unsigned char *)restoreCharArray, numArgs);
1449 * Copy the pointer map into the saved map for logout
1451 smToSet.numButton = ((numArgs > 5) ? 5 : numArgs);
1452 for(i = 0; i < smToSet.numButton;i++)
1454 smToSet.pointerMap[i] = restoreCharArray[i];
1459 * Restore the key mappings
1461 if(smSettings.numKeyCode > 0)
1463 tmpSyms = (KeySym *) restoreCharArray;
1464 symSize = (charSize * sizeof(char)) / sizeof(KeySym);
1465 tmpKey = strtok(smGD.keySyms, ",");
1466 for(i = 0;tmpKey != NULL;i++)
1468 tmpSyms[i] = (KeySym) atol(tmpKey);
1469 tmpKey = strtok(NULL, ",");
1471 if((numArgs >= symSize) && (tmpKey != NULL))
1474 symSize = (charSize * sizeof(char))/sizeof(KeySym);
1475 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1476 (charSize * sizeof(char)));
1477 if(restoreCharArray == NULL)
1479 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1480 SM_FREE((char *) restorePtrArray);
1483 tmpSyms = (KeySym *) restoreCharArray;
1486 numArgs /= smSettings.keySymPerCode;
1487 XChangeKeyboardMapping(smGD.display, (KeyCode)
1488 smGD.display->min_keycode,
1489 smSettings.keySymPerCode, tmpSyms,
1494 * Restore the modifier mappings
1496 tmpCode = (KeyCode *) restoreCharArray;
1497 tmpKey = strtok(smGD.modSyms, ",");
1500 for(i = 0;i < (8 * smSettings.maxKeyPerMod);i++)
1504 codeSym = (KeySym) atol(tmpKey);
1507 tmpCode[i] = XKeysymToKeycode(smGD.display, codeSym);
1511 tmpCode[i] = (KeyCode) 0;
1516 tmpCode[i] = (KeyCode) 0;
1518 tmpKey = strtok(NULL, ",");
1520 restoreMod.max_keypermod = smSettings.maxKeyPerMod;
1521 restoreMod.modifiermap = tmpCode;
1522 XSetModifierMapping(smGD.display, &restoreMod);
1525 SM_FREE((char *) restorePtrArray);
1526 SM_FREE(restoreCharArray);
1533 /*************************************<->*************************************
1535 * RestoreIndependentResources ()
1540 * In charge of restoring the resources that help make the session more
1541 * resolution and language independent - only restored if they are
1542 * necessary (lang || resolution has changed) and exist
1547 * smResources = global pointer to the resources to be restored by the SM
1557 *************************************<->***********************************/
1559 RestoreIndependentResources( void )
1563 unsigned long nitems, leftover;
1564 unsigned char *data = NULL;
1566 XrmValue fontResourceReturn;
1567 char *currentLangPtr, *resValRet, *sessionType;
1569 int intYRes[2], status,i;
1572 Boolean resIndep = False, resRet;
1575 if(((smGD.sessionLang == NULL) || (*smGD.sessionLang == 0)) &&
1576 (smRes.displayResolution == 0))
1579 * No saved info to draw from - nothing new is added
1584 currentLangPtr = getenv("LANG");
1586 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1587 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1589 if(fltYRes < MED_RES_Y_RES)
1591 intYRes[0] = LOW_RES_Y_RES;
1592 sessionRes = SM_LOW_RES_EXT;
1596 if(fltYRes >= HIGH_RES_Y_RES)
1598 intYRes[0] = HIGH_RES_Y_RES;
1599 sessionRes = SM_HIGH_RES_EXT;
1603 intYRes[0] = MED_RES_Y_RES;
1604 sessionRes = SM_MED_RES_EXT;
1608 if(smRes.displayResolution < MED_RES_Y_RES)
1610 intYRes[1] = LOW_RES_Y_RES;
1614 if(smRes.displayResolution >= HIGH_RES_Y_RES)
1616 intYRes[1] = HIGH_RES_Y_RES;
1620 intYRes[1] = MED_RES_Y_RES;
1625 * If the resolution or the language has changed -
1626 * load the language/resolution independent fonts if
1627 * they exist in the users home directory or in the system
1629 if((strcmp(currentLangPtr, smGD.sessionLang)) ||
1630 (intYRes[0] != intYRes[1]))
1632 char *fontPath = SM_MALLOC(MAXPATHLEN + 1);
1634 if(smGD.sessionType == HOME_SESSION)
1636 sessionType = SM_HOME_FONT_DIRECTORY;
1640 sessionType = SM_CURRENT_FONT_DIRECTORY;
1643 memset(fontPath, 0, MAXPATHLEN + 1);
1644 snprintf(fontPath, MAXPATHLEN, "%s/%s/%s/%s.%s",
1645 smGD.savePath, sessionType,
1646 currentLangPtr, SM_FONT_FILE, sessionRes);
1647 status = stat(fontPath, &buf);
1651 * User has nothing there - look in the system defaults
1652 * first in the language dep -then in lang independent
1654 memset(fontPath, 0, MAXPATHLEN + 1);
1656 if((currentLangPtr != NULL) && (*currentLangPtr != 0))
1658 strcat(fontPath, "/");
1659 strncat(fontPath, currentLangPtr, MAXPATHLEN);
1662 strncat(fontPath, "/", MAXPATHLEN);
1663 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1667 status = stat(fontPath, &buf);
1670 if((currentLangPtr != NULL) && (*currentLangPtr != 0) &&
1671 (strcmp(currentLangPtr, "C")))
1673 memset(fontPath, 0, MAXPATHLEN + 1);
1674 strcpy(fontPath, "/C/");
1675 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1679 status = stat(fontPath, &buf);
1696 strncpy(smGD.fontPath, fontPath, MAXPATHLEN);
1698 if(resIndep == True)
1702 * add the auxillary resources onto the root window
1704 RestoreResources(True, "-merge", "-file", smGD.fontPath, NULL);
1707 * Load the resources from the RESOURCE_MANAGER
1708 * property on the root window
1710 if(XGetWindowProperty(smGD.display, RootWindow(smGD.display, 0),
1711 XA_RESOURCE_MANAGER,0L,
1712 100000000L,False,XA_STRING,&actualType,
1713 &actualFormat,&nitems,&leftover,
1714 (unsigned char**) &data) == Success)
1716 smBase = XrmGetStringDatabase((char *)data);
1725 PrintError(DtError, GETMESSAGE(16, 6, "Invalid display/language independent resource file. No display/language independent resources will be restored."));
1726 SM_FREE((char *)data);
1732 * Get the new fontlist from the resources and
1733 * Put it on the application shell. Then add
1734 * the auxillary resources into the display struct
1736 resRet = XrmGetResource(smBase, "*fontList", "*FontList",
1737 &resValRet, &fontResourceReturn);
1740 XtSetArg(uiArgs[i], XmNdefaultFontList,
1741 (XmFontList) fontResourceReturn.addr);i++;
1742 XtSetValues(smGD.topLevelWid, uiArgs, i);
1745 * Overwrite the old font preferences, otherwise,
1746 * they'll come back to haunt us if the user logs in again
1747 * under the current language. We need to get the font
1748 * resources which have just been loaded, then overlay
1749 * them onto the _DT_SM_PREFERENCES root property to make
1750 * sure we get them back when we login again.
1752 for (i = 0; i < XtNumber(fonttype); i++)
1754 resRet = XrmGetResource(smBase, fonttype[i], fontclass[i],
1755 &resValRet, &fontResourceReturn);
1759 (char *)SM_MALLOC(fontResourceReturn.size + 30);
1760 bzero(resdata, fontResourceReturn.size + 30);
1761 strcat(resdata, fonttype[i]);
1762 strcat(resdata, ": ");
1763 strcat(resdata, fontResourceReturn.addr);
1764 strcat(resdata, "\n");
1765 _DtAddResString(smGD.display, resdata, _DT_ATR_PREFS);
1770 XrmMergeDatabases(smBase, &(smGD.display->db));
1771 SM_FREE((char *)data);
1775 SM_FREE((char*) fontPath);
1782 /*************************************<->*************************************
1789 * Reads through the client file and restores its contents. A client file
1790 * consists of hints for the workspace manager, actual client commands, and
1791 * remote execution commands. All commands are processed accordingly.
1792 * If this is the first DT 3.0 session for a DT 2.0 user then we will
1793 * also launch the helpviewer. If this is the first DT 3.0 session for a
1794 * DT 2.0 user then we will also run convertVS.sh to change all
1795 * occurrences of /usr/bin/X11/hpterm to .../dt/bin/hpterm,
1796 * /usr/bin/X11/xterm to .../dt/bin/xterm and
1797 * /usr/bin/X11/xload to .../dt/bin/xload.
1808 * Any information read from the client file will be mucked with during
1809 * processing, and should not try to be mucked with again.
1811 * WARNING: This routine closes cfileP - not the calling routine
1812 * DOUBLE-WARNING: This routine starts the window manager
1814 *************************************<->***********************************/
1816 RestoreClients( void )
1818 unsigned char *lineP, *string;
1819 char *pch, *dispPtr = NULL;
1820 char *dispEnv, *dispSav, *dispEnvHelpview, *dispSavHelpview;
1821 unsigned char *hostPtr=NULL, *cmdPtr=NULL, *hintPtr = NULL;
1822 unsigned char *remoteDisplay;
1825 unsigned char tmpChar[35];
1826 int screenNum = 0, i, j, chlen, numClientsExec;
1827 int numRemoteDone = 0;
1829 Boolean clientsDone = False, wmHandshake = False, cmdInvInit = False;
1830 XClientMessageEvent smToWmMessage;
1833 * These variables are needed to buffer up the commands and then
1834 * execute them (also buffer up hints then put them on the root window
1836 unsigned char *hintsBuf[MAX_SCREENS_SAVED];
1837 unsigned char *cmdBuf[MAX_SCREENS_SAVED];
1838 unsigned int maxHintsSize[MAX_SCREENS_SAVED];
1839 unsigned int actHintsSize[MAX_SCREENS_SAVED];
1840 unsigned int numHints[MAX_SCREENS_SAVED];
1841 unsigned int maxCmdSize[MAX_SCREENS_SAVED];
1842 unsigned int actCmdSize[MAX_SCREENS_SAVED];
1843 unsigned int numCmd[MAX_SCREENS_SAVED];
1844 unsigned int maxRemoteSize[MAX_SCREENS_SAVED];
1847 * Initialize the buffers and their sizes to null and 0. Because of
1848 * all possible combinations - buffers aren't malloc'd until they're
1851 for(i = 0;i<smGD.numSavedScreens;i++)
1855 remoteBuf[i] = NULL;
1856 maxHintsSize[i] = 0;
1857 actHintsSize[i] = 0;
1862 maxRemoteSize[i] = 0;
1863 actRemoteSize[i] = 0;
1867 * Save the contents of the DISPLAY environment variable so that it
1868 * can be restored when we're through
1870 dispEnv = getenv(DISPLAY_NAME);
1873 dispSav = (char *) SM_MALLOC(((strlen(dispEnv) +
1874 strlen(DISPLAY_NAME_EQUAL)) * sizeof(char) + 1));
1875 sprintf(dispSav, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
1883 displayName = strdup(smGD.display->display_name);
1884 remoteDisplay = (unsigned char *)
1885 SM_MALLOC(sizeof(unsigned char) * (strlen(displayName) + 101));
1888 * Create the display name for locally executing clients
1914 * Create the display name for remotely executing clients.
1915 * These two may or may not be the same
1917 DtGetShortHostname((char *)remoteDisplay, 100);
1920 * Add the display qualifications to the host name
1921 * screen is added at execution time
1923 strcat((char *)remoteDisplay, (char *)dispPtr);
1926 * Intern the atom needed to put the hints on the root window
1927 * This has to be done here because InitProtocol has not been called yet
1929 XaWmDtHints = XInternAtom(smGD.display, _XA_DT_SESSION_HINTS, False);
1931 while(GetNextLine() != NULL)
1934 string = GetSmartString(&lineP);
1935 if( string != NULL && !strcmp((char *)string, "dtsmcmd"))
1937 while((string = GetSmartString(&lineP)) != NULL )
1939 if(!strcmp((char *)string, "-host"))
1942 * Extract a host pointer - host pointers
1943 * only exist on remote executions
1945 string = GetSmartString(&lineP);
1950 if(!strcmp((char *)string, "-cmd"))
1953 * Extract the command pointer from the
1956 string = GetSmartString(&lineP);
1961 if(!strcmp((char *)string, "-screen"))
1964 * Extract the screen number from the command
1966 string = GetSmartString(&lineP);
1967 screenNum = atoi((char *)string);
1972 if(!strcmp((char *)string, "-hints"))
1975 * Extract the hints string
1977 string = GetSmartString(&lineP);
1986 * Now put our information in buffers and reinitialize the pointers
1990 if(FillHintBuf(hintPtr, hintsBuf, maxHintsSize,
1991 actHintsSize, screenNum, numHints) != 0)
1994 * Free all malloc'd buffers and exit
1996 for(i = 0;i < smGD.numSavedScreens;i++)
1998 if(actHintsSize[i] > 0)
2000 SM_FREE((char *) hintsBuf[i]);
2002 if(actCmdSize[i] > 0)
2004 SM_FREE((char *) cmdBuf[i]);
2006 if(actRemoteSize[i] > 0)
2008 SM_FREE((char *) remoteBuf[i]);
2017 if((cmdPtr != NULL) && (hostPtr == NULL))
2019 if(FillCmdBuf(cmdPtr, cmdBuf, maxCmdSize,
2020 actCmdSize,screenNum, &numCmd[screenNum]) != 0)
2023 * Free all malloc'd buffers and exit
2025 for(i = 0;i < smGD.numSavedScreens;i++)
2027 if(actHintsSize[i] > 0)
2029 SM_FREE((char *) hintsBuf[i]);
2031 if(actCmdSize[i] > 0)
2033 SM_FREE((char *) cmdBuf[i]);
2035 if(actRemoteSize[i] > 0)
2037 SM_FREE((char *) remoteBuf[i]);
2046 if((cmdPtr != NULL) && (hostPtr != NULL))
2048 if(FillRemoteBuf(cmdPtr, hostPtr, remoteDisplay,
2049 remoteBuf, maxRemoteSize,
2050 actRemoteSize, screenNum) != 0)
2053 * Free all malloc'd buffers and exit
2055 for(i = 0;i < smGD.numSavedScreens;i++)
2057 if(actHintsSize[i] > 0)
2059 SM_FREE((char *) hintsBuf[i]);
2061 if(actCmdSize[i] > 0)
2063 SM_FREE((char *) cmdBuf[i]);
2065 if(actRemoteSize[i] > 0)
2067 SM_FREE((char *) remoteBuf[i]);
2077 screenNum = XDefaultScreen(smGD.display);
2082 * All done with file so close it off and set descriptor to NULL -
2083 * This is done so that parsing routines can be used with a buffer later
2089 * Now execute all the buffers, put all hints on the root windows
2090 * Do all remote executions
2092 for(i = 0;i < smGD.numSavedScreens;i++)
2095 * Put the root window property on each root window
2097 if(actHintsSize[i] > 0)
2100 * Append number of hints to front of buffer
2102 sprintf((char *)tmpChar, "%d", numHints[i]);
2103 strncpy((char *)hintsBuf[i], (char *)tmpChar,
2104 strlen((char *)tmpChar));
2105 XChangeProperty(smGD.display, RootWindow(smGD.display, i),
2106 XaWmDtHints, XA_STRING, 8, PropModeReplace,
2107 hintsBuf[i], actHintsSize[i]);
2108 SM_FREE((char *) hintsBuf[i]);
2109 XSync(smGD.display, 0);
2117 * Now exec on the local clients - we're doing contention management
2118 * to make sure the system doesn't get swamped
2122 while((actCmdSize[i] == 0) && (i < smGD.numSavedScreens))
2127 envVal = SM_MALLOC(BUFSIZ);
2128 if(i >= smGD.numSavedScreens)
2134 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2142 * Keep forking one client after the other until the
2143 * memory utilization gets beyond the threshold -
2144 * (but only if the capability exists) Then go to
2145 * window manager handshaking
2147 #ifdef DEBUG_CONT_MANAGEMENT
2148 if(smRes.contManagement & SM_CM_SYSTEM)
2150 fprintf(stderr, "SM_CM_SYSTEM flag set in smRes.contManagement\n");
2152 if(smRes.contManagement & SM_CM_HANDSHAKE)
2154 fprintf(stderr, "SM_CM_HANDSHAKE flag set in smRes.contManagement\n");
2156 #endif /* DEBUG_CONT */
2158 if((smRes.contManagement & SM_CM_SYSTEM) &&
2159 ((GetMemoryUtilization() != MEM_NOT_AVAILABLE) &&
2160 (clientsDone == False)))
2162 while((GetMemoryUtilization() == MEM_NOT_FULL) &&
2163 (clientsDone == False))
2167 CreateExecString((char *) lineP);
2168 if(smExecArray[0] != NULL)
2170 (void) StartClient(smExecArray[0], (char **)smExecArray, NULL,
2171 NULL, NULL, False, False, -1);
2176 * When all the clients have been exec'd for this screen
2179 if(numClientsExec >= numCmd[i])
2181 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2182 envVal, displayName);
2189 * After we've checked memory utilization - finish up
2190 * by handshaking with the worksapce manager - if it's there
2192 if(clientsDone == False)
2194 if((smGD.dtwmRunning) && (smRes.contManagement & SM_CM_HANDSHAKE))
2197 * Get the window id of the workspace manager and tell it
2198 * to start messaging
2200 _DtGetMwmWindow(smGD.display, RootWindow(smGD.display, 0),
2202 smToWmMessage.type = ClientMessage;
2203 smToWmMessage.window = dtwmWin;
2204 smToWmMessage.message_type = XaSmWmProtocol;
2205 smToWmMessage.format = 32;
2206 smToWmMessage.data.l[0] = XaSmStartAckWindow;
2207 smToWmMessage.data.l[1] = CurrentTime;
2208 if (XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2209 (XEvent *) &smToWmMessage) != 0)
2212 XSync(smGD.display, 0);
2218 * Start a client - and wait for the workspace manager to
2219 * map a window to start a new client
2221 while(clientsDone == False)
2225 CreateExecString((char *) lineP);
2226 if(smExecArray[0] != NULL)
2228 (void) StartClient(smExecArray[0], smExecArray,
2229 NULL, NULL, NULL, False, False, -1);
2233 * If we're handshaking with the workspace manager
2234 * wait for the client to be mapped before starting
2237 if(wmHandshake == True)
2245 * When all the clients have been exec'd for this screen
2248 if(numClientsExec >= numCmd[i])
2250 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2251 envVal, displayName);
2256 if(wmHandshake == True)
2259 * If we are handshaking - tell the workspace manager to
2262 smToWmMessage.type = ClientMessage;
2263 smToWmMessage.window = dtwmWin;
2264 smToWmMessage.message_type = XaSmWmProtocol;
2265 smToWmMessage.format = 32;
2266 smToWmMessage.data.l[0] = XaSmStopAckWindow;
2267 smToWmMessage.data.l[0] = CurrentTime;
2268 XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2269 (XEvent *) &smToWmMessage);
2274 for(i = 0;i < smGD.numSavedScreens;i++)
2276 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2282 * Send out all the remote execution commands for the screen to
2283 * the command invoker. On failure - do a remsh instead
2285 if(actRemoteSize[i] > 0)
2288 * Initialize the command invoker - if not done
2290 if(cmdInvInit == False)
2292 _DtInitializeCommandInvoker(smGD.display,
2300 * Set up the display environment variable so that the
2301 * application comes back to the right screen
2303 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2307 parseP = remoteBuf[i];
2308 while(numRemoteExecs > 0 && GetNextLine() != NULL)
2311 * Get the host and the command and send them off
2312 * On failure of the command invoker do a remsh
2315 string = GetSmartString(&lineP);
2317 string = GetSmartString(&lineP);
2320 remoteBufPtr[numRemoteDone].cmdPtr = cmdPtr;
2321 remoteBufPtr[numRemoteDone].hostPtr = hostPtr;
2323 _DtCommandInvokerExecute(DtSTART_SESSION, NULL, NULL, NULL,
2324 "-", (char *) hostPtr, (char *) cmdPtr,
2325 RemoteRequestSucceeded, NULL,
2326 RemoteRequestFailed,
2327 &remoteBufPtr[numRemoteDone]);
2331 * If there is no more room in the remote client
2332 * array - quit exec'ing remote clients
2334 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2336 PrintError(DtError, GETMESSAGE(16, 5, "You have reached the maximum allowed number of remote clients. No further remote clients will be restored."));
2346 * Now return the display variable back to the display that was
2347 * originally opened (the default display)
2355 FixEnvironmentData();
2360 } /* END OF FUNCTION RestoreClients */
2364 /*************************************<->*************************************
2366 * StartEtc ( exiting )
2371 * Call the StartClient routine to fork and exec either the sessionetc file
2372 * (if exiting==False) or the sessionexit file (if exiting==True).
2384 *************************************<->***********************************/
2386 StartEtc( Boolean exiting )
2393 execArray[0] = smGD.exitPath;
2394 execArray[1] = smExitFile;
2396 execArray[0] = smGD.etcPath;
2397 execArray[1] = smEtcFile;
2399 execArray[2] = '\0';
2401 if ((status=stat(execArray[0], &buf)) != -1)
2403 StartClient(execArray[0], execArray, NULL, NULL, NULL, False, False, -1);
2408 /*************************************<->*************************************
2415 * Returns the next line from an fopened configuration file or a newline-
2416 * embedded configuration string.
2421 * cfileP = (global) file pointer to fopened configuration file or NULL
2422 * line = (global) line buffer
2423 * linec = (global) line count
2424 * parseP = (global) parse string pointer if cfileP == NULL
2429 * line = (global) next line
2430 * linec = (global) line count incremented
2431 * parseP = (global) parse string pointer incremented
2432 * Return = line or NULL if file or string is exhausted.
2437 * If there are more than MAXLINE characters on a line in the file cfileP the
2438 * excess are truncated.
2439 * Assumes the line buffer is long enough for any parse string line.
2440 * Code stolen from dtmwm
2442 *************************************<->***********************************/
2443 static unsigned char *
2446 unsigned char *string;
2452 /* read fopened file */
2454 string = (unsigned char *) fgets((char *)line, fileSize, cfileP);
2456 else if ((parseP != NULL) && (*parseP != 0))
2457 /* read parse string */
2461 while ((*parseP != 0) &&
2462 ((chlen = mblen ((char *) parseP, MB_CUR_MAX)) > 0) &&
2464 /* copy all but NULL and newlines to line buffer */
2468 *(string++) = *(parseP++);
2472 while ((*parseP != NULL) && (*parseP != '\n'))
2473 /* copy all but NULL and newlines to line buffer */
2475 *(string++) = *(parseP++);
2479 if (*parseP == '\n')
2492 } /* END OF FUNCTION GetNextLine */
2496 /*************************************<->*************************************
2498 * PeekAhead (currentChar, currentLev)
2503 * Returns a new level value if this is a new nesting level of quoted string
2504 * Otherwise it returns a zero
2509 * currentChar = current position in the string
2510 * currentLev = current level of nesting
2515 * Returns either a new level of nesting or zero if the character is copied in
2521 *************************************<->***********************************/
2524 unsigned char *currentChar,
2525 unsigned int currentLev )
2527 Boolean done = False;
2528 unsigned int tmpLev = 1;
2532 while (((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) &&
2533 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
2538 if(((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
2539 ((*currentChar == '"') || (*currentChar == '\\')))
2542 if(*currentChar == '"')
2553 while((*currentChar != NULL) && (done == False) &&
2554 ((*currentChar == '"') || (*currentChar == '\\')))
2557 if((*currentChar != NULL) &&
2558 ((*currentChar == '"') || (*currentChar == '\\')))
2561 if(*currentChar == '"')
2571 #endif /*MULTIBYTE*/
2574 * Figure out if this is truly a new level of nesting - else ignore it
2575 * This section probably could do some error checking and return -1
2576 * If so, change type of routine from unsigned int to int
2590 /*************************************<->*************************************
2592 * GetSmartString (linePP)
2597 * Returns the next quoted or whitespace-terminated nonquoted string in the
2599 * Additional functionality added to GetString in that anything in a
2600 * quoted string is considered sacred and nothing will be stripped from
2601 * the middle of a quoted string.
2606 * linePP = pointer to current line buffer pointer.
2611 * linePP = pointer to revised line buffer pointer.
2617 * May alter the line buffer contents.
2618 * Handles quoted strings and characters, removing trailing whitespace from
2620 * Returns NULL string if the line is empty or is a comment.
2621 * Code stolen from dtmwm.
2623 *************************************<->***********************************/
2625 static unsigned char *
2627 unsigned char **linePP )
2629 unsigned char *lineP = *linePP;
2630 unsigned char *endP;
2631 unsigned char *curP;
2632 unsigned char *lnwsP;
2633 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
2637 /* get rid of leading white space */
2638 ScanWhitespace (&lineP);
2641 * Return NULL if line is empty, whitespace, or begins with a comment.
2643 if((chlen = mblen ((char *) lineP, MB_CUR_MAX)) < 1)
2649 if ((chlen == 1) && (*lineP == '"'))
2652 quoteLevel[level] = 1;
2654 * Start beyond double quote and find the end of the quoted string.
2655 * '\' quotes the next character - but is not stripped out.
2656 * Otherwise, matching double quote or NULL terminates the string.
2658 * We use lnwsP to point to the last non-whitespace character in the
2659 * quoted string. When we have found the end of the quoted string,
2660 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2661 * This removes any trailing whitespace without overwriting the
2662 * matching quote, needed later. If the quoted string was all
2663 * whitespace, then this will write a NULL at the beginning of the
2664 * string that will be returned -- OK.
2666 lnwsP = lineP++; /* lnwsP points to first '"' */
2667 curP = endP = lineP; /* other pointers point beyond */
2669 while ((*endP = *curP) &&
2670 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2671 ((chlen > 1) || (*curP != '"')))
2672 /* Haven't found matching quote yet.
2673 * First byte of next character has been copied to endP.
2677 if ((chlen == 1) && (*endP == '\\') &&
2678 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2681 * Check to see if this is a quoted quote - if it is
2682 * strip off a level - if not - it's sacred leave it alone
2684 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2687 if(quoteLevel[level] >= checkLev)
2689 if (level > 0) level--;
2691 else if (level < MAX_QUOTE_DEPTH)
2694 quoteLevel[level] = checkLev;
2697 for(i = 0;i < (checkLev - 2);i++)
2699 *endP++ = *curP++;curP++;
2706 /* Singlebyte character: character copy finished. */
2708 if (isspace (*endP))
2709 /* whitespace character: leave lnwsP unchanged. */
2714 /* non-whitespace character: point lnwsP to it. */
2720 /* Multibyte (nonwhitespace) character: point lnwsP to it.
2721 * Finish character byte copy.
2734 /* get rid of leading white space */
2735 ScanWhitespace (&lineP);
2737 /* Return NULL if line is empty, or whitespace */
2747 quoteLevel[level] = 1;
2749 * Start beyond double quote and find the end of the quoted string.
2750 * '\' quotes the next character.
2751 * Otherwise, matching double quote or NULL terminates the string.
2753 * We use lnwsP to point to the last non-whitespace character in the
2754 * quoted string. When we have found the end of the quoted string,
2755 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2756 * This removes any trailing whitespace without overwriting the
2757 * matching quote, needed later. If the quoted string was all
2758 * whitespace, then this will write a NULL at the beginning of the
2759 * string that will be returned -- OK.
2761 lnwsP = lineP++; /* lnwsP points to first '"' */
2762 curP = endP = lineP; /* other pointers point beyond */
2764 while ((*endP = *curP) && (*endP != '"'))
2765 /* haven't found matching quote yet */
2767 /* point curP to next character */
2769 if ((*endP == '\\') && (*curP != NULL))
2770 /* shift quoted nonNULL character down and curP ahead */
2773 * Check to see if this is a quoted quote - if it is
2774 * strip off a level - if not - it's sacred leave it alone
2776 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2779 if(quoteLevel[level] >= checkLev)
2781 if (level > 0) level--;
2783 else if (level < MAX_QUOTE_DEPTH)
2786 quoteLevel[level] = checkLev;
2789 for(i = 0;i < (checkLev - 2);i++)
2791 *endP++ = *curP++;curP++;
2797 if (isspace (*endP))
2798 /* whitespace character: leave lnwsP unchanged. */
2803 /* non-whitespace character: point lnwsP to it. */
2811 * Found matching quote or NULL.
2812 * NULL out any trailing whitespace.
2823 /* Unquoted string */
2826 * Find the end of the nonquoted string.
2827 * '\' quotes the next character.
2828 * Otherwise, whitespace, NULL, terminates the string.
2830 curP = endP = lineP;
2833 while ((*endP = *curP) &&
2834 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2835 ((chlen > 1) || (!isspace (*curP))))
2836 /* Haven't found whitespace yet.
2837 * First byte of next character has been copied to endP.
2841 if ((chlen == 1) && (*endP == '\\') &&
2842 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2844 * copy first byte of quoted nonNULL character down.
2845 * point curP to next byte
2852 /* Multibyte character: finish character copy. */
2861 while ((*endP = *curP) && !isspace (*endP))
2863 /* point curP to next character */
2865 if ((*endP == '\\') && (*curP != NULL))
2866 /* shift quoted nonNULL character down and curP ahead */
2876 * Two cases for *endP:
2878 * matching quote -> write NULL over char and point beyond
2879 * NULL -> point to NULL
2884 *endP = 0; /* write NULL over terminator */
2885 *linePP = ++curP; /* point beyond terminator */
2891 return ((unsigned char *)lineP);
2893 } /* END OF FUNCTION GetString */
2898 /*************************************<->*************************************
2900 * ScanWhitespace(linePP)
2905 * Scan the string, skipping over all white space characters.
2910 * linePP = nonNULL pointer to current line buffer pointer
2915 * linePP = nonNULL pointer to revised line buffer pointer
2920 * Assumes linePP is nonNULL
2921 * Code Stolen from dtmwm
2923 *************************************<->***********************************/
2926 unsigned char **linePP )
2929 while (*linePP && (mblen ((char *) *linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
2931 while (*linePP && isspace (**linePP))
2937 } /* END OF FUNCTION ScanWhitespace */
2941 /*************************************<->*************************************
2943 * FillHintBuf(newHint, hintBuf, maxSize, actSize, screen, numHints)
2948 * Put the new hint into the hint buffer. Each hint is separated by a
2954 * newHint = hint to add to the buffer
2955 * hintBuf = an array of buffers - one for each screen
2956 * maxSize = array of buffers of the current malloced size of each hintBuf
2957 * actSize = array of space currently used by each hintBuf
2958 * screen = screen number for this hint
2959 * numHints = array of the number of hints for each screen
2960 * smGD.numSavedScreens = (global) checked to make sure this hint should be
2965 * hintBuf[screen] = updated hint buf for this screen (newHint added)
2966 * maxSize[screen] = enlarged if not big enough or malloced if not done before
2967 * actSize[screen] = updated size of the hints buffer
2968 * numHints[screen] = updated by 1 if this hint is added
2974 *************************************<->***********************************/
2977 unsigned char *newHint,
2978 unsigned char **hintBuf,
2979 unsigned int *maxSize,
2980 unsigned int *actSize,
2981 unsigned int screen,
2982 unsigned int *numHints)
2984 static int hintBufSize = 5000;
2987 * If the screen that this hint was meant for is not in the current
2988 * set of available screens, don't save it
2990 if(screen >= smGD.numSavedScreens)
2996 * Check to see if this buffer has been malloc'd before - if it hasn't
2997 * malloc it. If it has - check to make sure it's big enough to hold the
3000 if(maxSize[screen] == 0)
3002 hintBuf[screen] = (unsigned char *) SM_MALLOC(hintBufSize * sizeof(char));
3003 if(hintBuf[screen] == NULL)
3005 actSize[screen] = 0;
3006 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3009 maxSize[screen] = hintBufSize * sizeof(char);
3012 * Now reserve 4 bytes for the length
3014 strcpy((char *)hintBuf[screen], " \n");
3018 if((actSize[screen] + strlen((char *)newHint) + 2) >= maxSize[screen])
3020 hintBuf[screen] = (unsigned char *)
3021 SM_REALLOC((char *) hintBuf[screen],
3025 if(hintBuf[screen] == NULL)
3027 actSize[screen] = 0;
3028 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3031 maxSize[screen] = maxSize[screen] + (hintBufSize * sizeof(char));
3036 * add the new hint AFTER the last newline
3038 strcat((char *)hintBuf[screen], (char *)newHint);
3039 strcat((char *)hintBuf[screen], "\n");
3040 actSize[screen] = strlen((char *)hintBuf[screen]);
3041 numHints[screen] += 1;
3048 /*************************************<->*************************************
3050 * FillCmdBuf(newCmd, cmdBuf, maxSize, actSize, screen)
3055 * Put a new command into the command buffer. The command buffer is just
3056 * one big long string of stuff to be executed.
3061 * newCmd = command to add to the buffer
3062 * cmdBuf = an array of buffers - one for each screen
3063 * maxSize = array of buffers of the current malloced size of each cmdBuf
3064 * actSize = array of space currently used by each cmdBuf
3065 * screen = screen number for this command
3066 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3071 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3072 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3073 * actSize[screen] = updated size of the command buffer
3079 *************************************<->***********************************/
3082 unsigned char *newCmd,
3083 unsigned char **cmdBuf,
3084 unsigned int *maxSize,
3085 unsigned int *actSize,
3086 unsigned int screen,
3087 unsigned int *numCmd )
3089 static int cmdBufSize = 5000;
3092 * If the screen that this command was meant for is not in the current
3093 * set of available screens, don't save it
3095 if(screen >= smGD.numSavedScreens)
3101 * Check to see if this buffer has been malloc'd before - if it hasn't
3102 * malloc it. If it has - check to make sure it's big enough to hold the
3105 if(maxSize[screen] == 0)
3107 cmdBuf[screen] = (unsigned char *) SM_MALLOC(cmdBufSize * sizeof(char));
3108 if(cmdBuf[screen] == NULL)
3110 actSize[screen] = 0;
3111 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3114 maxSize[screen] = cmdBufSize * sizeof(char);
3118 if((actSize[screen] + strlen((char *)newCmd)) >= maxSize[screen])
3120 cmdBuf[screen] = (unsigned char *) SM_REALLOC((char *)cmdBuf[screen],
3124 if(cmdBuf[screen] == NULL)
3126 actSize[screen] = 0;
3127 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3130 maxSize[screen] = maxSize[screen] + (cmdBufSize * sizeof(char));
3134 if(actSize[screen] == 0)
3136 strcpy((char *)cmdBuf[screen], (char *)newCmd);
3140 strcat((char *)cmdBuf[screen], (char *)newCmd);
3143 *numCmd = *numCmd + 1;
3144 strcat((char *)cmdBuf[screen], "\n");
3145 actSize[screen] = strlen((char *)cmdBuf[screen]);
3152 /*************************************<->*************************************
3154 * FillRemoteBuf(newCmd, hostName, displayName, remoteBuf,
3155 * maxSize, actSize, screen)
3160 * Put a new command into the remote execution buffer. The command buffer is
3161 * just one big long string of stuff to be executed.
3166 * newCmd = command to add to the buffer
3167 * hostName = host where command is to be executed from
3168 * displayName = display where host is to be executed to
3169 * remoteBuf = an array of buffers - one for each screen
3170 * maxSize = array of buffers of the current malloced size of each cmdBuf
3171 * actSize = array of space currently used by each cmdBuf
3172 * screen = screen number for this command
3173 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3178 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3179 * in remote format (host name and display name)
3180 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3181 * actSize[screen] = updated size of the command buffer
3187 *************************************<->***********************************/
3190 unsigned char *newCmd,
3191 unsigned char *hostName,
3192 unsigned char *displayName,
3193 unsigned char *remoteBuf[] ,
3194 unsigned int *maxSize ,
3195 unsigned int *actSize ,
3196 unsigned int screen )
3198 unsigned char *string;
3199 static int remoteBufSize = 5000;
3202 * If the screen that this command was meant for is not in the current
3203 * set of available screens, don't save it
3205 if(screen >= smGD.numSavedScreens)
3211 * Check to see if this buffer has been malloc'd before - if it hasn't
3212 * malloc it. If it has - check to make sure it's big enough to hold the
3215 if(maxSize[screen] == 0)
3217 remoteBuf[screen] = (unsigned char *)
3218 SM_MALLOC(remoteBufSize * sizeof(char));
3219 if(remoteBuf[screen] == NULL)
3221 actSize[screen] = 0;
3222 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3225 maxSize[screen] = remoteBufSize * sizeof(char);
3229 if((actSize[screen] + strlen((char *)newCmd) +
3230 strlen((char *)hostName) +
3231 strlen((char *)displayName) +
3232 strlen("-display ") + 5) >= maxSize[screen])
3234 remoteBuf[screen] = (unsigned char *)
3235 SM_REALLOC((char *)remoteBuf[screen],
3237 (remoteBufSize * sizeof(char)));
3238 if(remoteBuf[screen] == NULL)
3240 actSize[screen] = 0;
3241 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3244 maxSize[screen] = maxSize[screen] + (remoteBufSize * sizeof(char));
3248 if(actSize[screen] == 0)
3251 * If the buffer is empty fill it with the initial contents
3253 strcpy((char *)remoteBuf[screen], (char *)hostName);
3254 strcat((char *)remoteBuf[screen], " ");
3259 * if this buffer is not emtpy
3260 * add the new command BEFORE the last null terminator
3261 * Commands for remote executions are separated by newlines
3263 strcat((char *)remoteBuf[screen], "\n");
3264 strcat((char *)remoteBuf[screen], (char *)hostName);
3268 * Copy the command in - quote it
3270 strcat((char *)remoteBuf[screen], " \"");
3271 string = GetSmartString(&newCmd);
3272 strcat((char *)remoteBuf[screen], (char *)string);
3273 strcat((char *)remoteBuf[screen], " ");
3276 * Once display name has been put in place - concatenate the
3277 * rest of the command
3279 while((string = GetSmartString(&newCmd)) != NULL )
3281 strcat((char *)remoteBuf[screen], " ");
3282 strcat((char *)remoteBuf[screen], (char *)string);
3286 * Now close off the command with a quote
3288 strcat((char *)remoteBuf[screen], "\"");
3290 actSize[screen] = strlen((char *)remoteBuf[screen]);
3293 * Bump the remote command counter
3301 /*************************************<->*************************************
3303 * CreateExecString(execString)
3308 * Create a string that can be fed to a fork and exec by breaking it up
3309 * into argc and argv
3314 * execString = whole command
3318 * smExecArray = global modified to contain pointers to argc and argv
3324 *************************************<->***********************************/
3332 static int iSizeArgv = ARG_AMT;
3337 if (smExecArray == NULL)
3339 smExecArray = (char **) XtMalloc (ARG_AMT * sizeof(char *));
3341 string = (char *) GetSmartString((unsigned char **) &execString);
3342 while(string != NULL)
3344 smExecArray[argc] = string;
3346 if (argc >= iSizeArgv)
3348 iSizeArgv += ARG_AMT;
3349 smExecArray = (char **)
3350 XtRealloc ((char *)smExecArray, (iSizeArgv * sizeof(char *)));
3352 string = (char *) GetSmartString((unsigned char **) &execString);
3356 * If the last string is a background character
3361 if(!strcmp((char *)smExecArray[argc - 1], "&"))
3363 smExecArray[argc - 1] = '\0';
3367 smExecArray[argc] = '\0';
3369 } /* END OF FUNCTION CreateExecString */
3373 * SetTemporaryDisplay - does a putenv of the current value of the
3374 * DISPLAY environment variable but with the given screen number.
3380 SetTemporaryDisplay (
3383 static char * tmpDisplay = NULL;
3384 static int lastScreen = -1;
3387 if (screenNum == -1)
3390 if (!savedDisplay) {
3393 if ((dispEnv = getenv (DISPLAY_NAME)) == NULL)
3395 savedDisplay = XtMalloc (strlen (DISPLAY_NAME_EQUAL) +
3396 strlen (dispEnv) + 2);
3399 sprintf (savedDisplay, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
3402 if (lastScreen == screenNum && tmpDisplay != NULL) {
3403 putenv (tmpDisplay);
3406 lastScreen = screenNum;
3411 tmpDisplay = XtMalloc (strlen (savedDisplay) + 4);
3414 strcpy (tmpDisplay, savedDisplay);
3417 if (pch = strrchr (tmpDisplay, ':')) {
3420 if (pch2 = strchr (pch, '.'))
3422 pch3 = XtMalloc (strlen (tmpDisplay) + 4);
3425 sprintf (pch3, "%s.%d", tmpDisplay, screenNum);
3426 strcpy (tmpDisplay, pch3);
3427 XtFree ((char *) pch3);
3429 putenv (tmpDisplay);
3435 * RestoreDisplay - does a putenv of the global variable savedDisplay
3441 if (screenNum != -1 && savedDisplay)
3442 putenv (savedDisplay);
3446 /*************************************<->*************************************
3448 * StartClient - calls StartLocalClient or StartRemoteClient depending
3449 * on the value of hostName.
3453 * Starts a local or remote application
3457 * program = execArray[0]
3458 * execArray = command to fork and exec
3459 * hostName = the name of the host where program should be executed
3460 * cwd = directory to chdir to before doing the exec
3461 * envp = the envrironment variables to add to the child processes env
3462 * checkCwd = if True and cwd is NULL, a message will be logged; if
3463 * False, cwd will not be checked and the cwd will be set to $HOME
3464 * useIgnoreEnvironmentResource = if True, the variables listed in the
3465 * IgnoreEnvironment resource will be removed from 'environ' before
3466 * execArray is exec'd
3467 * screen = if set to -1, it will be ignored; otherwise, the screen
3468 * number will be used to define DISPLAY for the duration of this
3469 * function - DISPLAY will be reset before the function returns.
3473 * Returns True if the command is successfully executed; False otherwise.
3477 * localHost - is modified
3479 *************************************<->***********************************/
3488 Boolean useIgnoreEnvironmentResource,
3491 static char * defaultCwd = NULL;
3492 Boolean cwdNull = False;
3493 Boolean startStatus;
3495 SetTemporaryDisplay (screen);
3497 if (!ignoreEnvPtr && useIgnoreEnvironmentResource) {
3498 if (smRes.ignoreEnvironment)
3499 ignoreEnvPtr = _DtVectorizeInPlace (
3500 smRes.ignoreEnvironment, ',');
3505 char *tstr = getenv("HOME");
3508 int slen = strlen(tstr) + 1;
3509 defaultCwd = XtCalloc(1, slen);
3510 snprintf(defaultCwd, slen, "%s", tstr);
3513 defaultCwd = getcwd (NULL, MAXPATHLEN + 1);
3515 (void) gethostname (localHost, MAXHOSTNAMELEN);
3523 if (!hostName || (_DtIsSameHost (localHost, hostName)))
3524 startStatus = StartLocalClient (program, execArray,
3525 cwd, envp, checkCwd,
3526 useIgnoreEnvironmentResource);
3528 startStatus = StartRemoteClient (program, execArray, hostName,
3530 useIgnoreEnvironmentResource);
3532 RestoreDisplay (screen);
3534 return (startStatus);
3537 /*************************************<->*************************************
3543 * Starts a local application.
3546 * Returns True if the command is successfully executed; False otherwise.
3548 *************************************<->***********************************/
3556 Boolean useIgnoreEnvironmentResource)
3560 char clientMessage[MAXPATHLEN + 30];
3561 char **tmpEnv, **ppchar;
3564 * Fork and exec the client process
3566 clientFork = vfork();
3569 * If the fork fails - Send out an error and return
3573 PrintErrnoError(DtError, smNLS.cantForkClientString);
3578 * Fork succeeded - now do the exec
3582 SetSIGPIPEToDefault ();
3585 * Log a warning if the given cwd is not valid
3589 if ((chdir (cwd)) == -1)
3593 tmpCwd = getcwd (NULL, MAXPATHLEN + 1);
3595 LogCWDMessage (cwd, program, tmpCwd);
3600 * Add envp to the client's environ if the variable
3601 * is not in the ignoreEnvironment list
3603 if (useIgnoreEnvironmentResource && envp) {
3606 tmpEnv = RemoveEnvironmentVars (envp);
3610 for (ppchar = tmpEnv; ppchar && *ppchar; ppchar++)
3611 putenv (strdup (*ppchar));
3616 * Set the gid of the process back from bin
3619 setregid(smGD.runningGID, smGD.runningGID);
3621 setgid(smGD.runningGID);
3622 setegid(smGD.runningGID);
3626 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3628 #if defined(CSRG_BASED)
3632 #endif /* CSRG_BASED */
3634 MarkFileDescriptors (3, F_SETFD, 1);
3636 execStatus = execvp(program, execArray);
3639 sprintf(clientMessage, ((char *)GETMESSAGE(16, 3, "Unable to exec %s.")), execArray[0]);
3640 PrintErrnoError(DtError, clientMessage);
3648 /*************************************<->*************************************
3654 * Starts a remote application.
3657 * Returns True if the command is successfully executed; False otherwise.
3659 *************************************<->***********************************/
3667 Boolean useIgnoreEnvironmentResource)
3670 SPC_Channel_Ptr channel;
3672 char errorMessage[1024];
3674 static Boolean cmdInvokerInitialized = False;
3675 char ** tmpEnv = envp;
3677 ioMode = SPCIO_NOIO | SPCIO_FORCE_CONTEXT;
3679 if (!cmdInvokerInitialized) {
3680 _DtInitializeCommandInvoker(smGD.display,
3684 cmdInvokerInitialized = True;
3687 (void) strcpy (errorMessage, "");
3689 channel = (SPC_Channel_Ptr) _DtSPCOpen (hostName, ioMode, errorMessage);
3690 if (channel == SPC_ERROR) {
3691 message = strdup ((char *) GETMESSAGE (40, 13,
3692 "The following application cannot be started on host '%s'\nbecause this host cannot be reached from host '%s':\n\n %s"));
3695 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3696 message, hostName, localHost, program);
3702 netfile = tt_host_file_netfile (hostName, cwd);
3703 if (tt_pointer_error (netfile) != TT_OK) {
3705 message = strdup ((char *) GETMESSAGE (40, 14,
3706 "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]"));
3709 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3710 message, program, hostName, cwd,
3711 tt_status_message (tt_pointer_error (
3719 * Add envp to the client's environ if the variable
3720 * is not in the ignoreEnvironment list
3722 if (useIgnoreEnvironmentResource && ignoreEnvPtr && envp)
3723 tmpEnv = RemoveEnvironmentVars (envp);
3725 if ((_DtSPCSpawn (program, netfile, execArray, tmpEnv, channel,
3726 hostName, NULL, cwd, errorMessage)) == SPC_ERROR) {
3727 DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMessage);
3729 XtFree ((char *) tmpEnv);
3735 XtFree ((char *) tmpEnv);
3741 /*************************************<->*************************************
3748 * Fork and exec the default window manager
3761 *************************************<->***********************************/
3770 * These lines were added to support the builtin
3775 char *displayName,*dpy;
3777 hostName = SM_MALLOC(MAXPATHSM);
3778 displayName = SM_MALLOC(MAXPATHSM);
3780 if( gethostname(hostName, (sizeof(hostName) - 1) ) == 0)
3782 hostName[MAXPATHSM - 1] = '\0';
3783 dpy = getenv(DISPLAY_NAME);
3784 homeDir = getenv("HOME");
3787 strcpy(displayName, dpy);
3788 dpy = strchr(displayName, ':');
3793 sprintf(tmpExecWmFile, "%s/.dt/bin/%s/%s/dtwm", homeDir,
3794 hostName,displayName);
3795 if (access(tmpExecWmFile,X_OK) != 0)
3797 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3801 localWmLaunched = True;
3802 if (!smGD.userSetWaitWmTimeout)
3804 smRes.waitWmTimeout = 60000;
3810 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3815 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3819 SM_FREE(displayName);
3821 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3822 * End of lines were added to support the builtin
3826 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3831 * Fork and exec the client process
3833 clientFork = vfork();
3836 * If the fork fails - Send out an error and return
3840 PrintErrnoError(DtError, smNLS.cantForkClientString);
3845 * Fork succeeded - now do the exec
3849 SetSIGPIPEToDefault ();
3853 * Set the gid of the process back from bin
3856 setregid(smGD.runningGID, smGD.runningGID);
3858 setgid(smGD.runningGID);
3859 setegid(smGD.runningGID);
3862 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3864 #if defined(CSRG_BASED)
3868 #endif /* CSRG_BASED */
3870 MarkFileDescriptors (3, F_SETFD, 1);
3873 * These lines were added to support the builtin
3876 * execStatus = execlp(".../dt/bin/dtwm", "dtwm", (char *) 0);
3879 execStatus = execlp(tmpExecWmFile, "dtwm", (char *) 0);
3882 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3883 * End of lines were added to support the builtin
3887 if(execStatus != 0 && (!localWmLaunched))
3889 PrintErrnoError(DtError, GETMESSAGE(16, 4, "Unable to exec process /usr/dt/bin/dtwm. No window manager will be started."));
3896 /*************************************<->*************************************
3903 * Fork a copy of ourselves and kill the parent off so that scripts starting
3904 * up the session manager can continue.
3916 *************************************<->***********************************/
3924 * Fork and exec the client process
3926 clientFork = fork();
3929 * If the fork fails - We have to exit so that the rest of the
3930 * script can continue
3934 PrintErrnoError(DtError, smNLS.cantForkClientString);
3939 * Fork succeeded - now kill the parent
3947 * Disassociate from parent
3949 #if defined(CSRG_BASED)
3953 #endif /* CSRG_BASED */
3958 /*************************************<->*************************************
3965 * This routine waits for the window manager to start. It uses a
3966 * resource (waitWmTimeout) with a dynamic default to determine how many
3967 * seconds to wait for WM start and then starts clients.
3972 * appContext = application context for the window
3973 * window = window id for the
3982 *************************************<->***********************************/
3987 XtIntervalId wmTimerId;
3989 XtAddEventHandler(smGD.topLevelWid,
3992 (XtEventHandler)HandleWMClientMessage,
3996 * Set a timer which stops the block on waiting for the
3997 * window manager to start
4000 wmTimerId = XtAppAddTimeOut(smGD.appCon,
4001 smRes.waitWmTimeout,
4002 WaitWMTimeout, NULL);
4004 while((smGD.dtwmRunning == False) && (wmTimeout == False))
4006 XtAppProcessEvent(smGD.appCon, XtIMAll);
4009 XtRemoveTimeOut(wmTimerId);
4010 XtRemoveEventHandler(smGD.topLevelWid,
4013 (XtEventHandler)HandleWMClientMessage,
4017 } /* END OF FUNCTION WaitForWM */
4020 /*************************************<->*************************************
4027 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
4028 * for the window manager to get started.
4037 * wmTimeout = (global) flag that stops the loop
4042 *************************************<->***********************************/
4045 XtPointer client_data,
4050 } /* END OF FUNCTION WaitWMTimeout */
4054 /*************************************<->*************************************
4056 * HandleWMClientMessage
4061 * This is the event handler registered to receive the client message
4062 * from dtwm when dtwm is ready for business
4065 *************************************<->***********************************/
4067 HandleWMClientMessage( Widget smWidget,
4071 if (event->type == ClientMessage)
4073 ProcessClientMessage(event);
4076 } /* END OF FUNCTION HandleWMClientMessage */
4081 /*************************************<->*************************************
4083 * FixEnvironmentData
4088 * If DISPLAY variable exists in the environment - remove it
4097 * wmTimeout = (global) flag that stops the loop
4102 *************************************<->***********************************/
4104 FixEnvironmentData( void )
4108 extern char **environ; /* MODIFIED - DISPLAY is remove if found. */
4110 for (i=0, ppchar = environ; *ppchar; ppchar++, i++)
4112 if ((strncmp (*ppchar, DISPLAY_NAME_EQUAL, strlen(DISPLAY_NAME_EQUAL))) == 0)
4115 * Change the DISPLAY environment variable.
4117 for (; *ppchar; ppchar++, i++)
4119 environ[i]=environ[i+1];
4128 /*************************************<->*************************************
4135 * After one screen is finished - set up the info for the next
4140 * cmdBuf - Buffer that holds all the invocation information
4141 * screen - Pointer to the screen number that we're currently working on
4142 * env - used to set up the environment for changing the display var
4143 * displayName - name of the current display
4147 * cmdBuf - old buffers are freed
4148 * screen - updated to point to the new screen info
4149 * done - tells whether the clients are done being exec'd
4150 * linec - *GLOBAL* sets line being read from
4156 *************************************<->***********************************/
4158 ResetScreenInfo(unsigned char **cmdBuf,
4160 unsigned int *cmdSize,
4165 SM_FREE((char *) cmdBuf[*screen]);
4167 while((cmdSize[*screen] == 0) && (*screen < smGD.numSavedScreens))
4172 if(*screen >= smGD.numSavedScreens)
4178 sprintf((char *)env,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, *screen);
4182 parseP = cmdBuf[*screen];
4188 /*************************************<->*************************************
4190 * RemoteRequestFailed ()
4195 * If a request to the command invoker fails, this callback will be called.
4196 * It will then try to execute the command by performing a remsh on it.
4209 *************************************<->***********************************/
4211 RemoteRequestFailed(char *message,
4214 static char *cmdBuf = NULL;
4215 static char *tmpCmdBuf = NULL;
4216 char *errorString = NULL;
4219 static int cmdBufSize = 0;
4222 RemoteReq *tmpReq = (RemoteReq *) client_data;
4225 * If the memory for the buffer has not been malloced - do so
4229 cmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4232 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4235 cmdBufSize = 200 + 1;
4237 tmpCmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4238 if(tmpCmdBuf == NULL)
4240 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4245 * Copy in the host and command field and execute the command
4248 tmpSize = (strlen(REMOTE_CMD_STRING) +
4249 strlen((char *) tmpReq->hostPtr) +
4250 strlen((char *) tmpReq->cmdPtr) + 1);
4252 if(tmpSize >= cmdBufSize)
4254 cmdBuf = SM_REALLOC(cmdBuf, (tmpSize) * sizeof(char));
4258 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4262 cmdBufSize = tmpSize;
4264 if(tmpCmdBuf != NULL)
4266 tmpCmdBuf = SM_REALLOC(tmpCmdBuf, (tmpSize) * sizeof(char));
4267 if(tmpCmdBuf == NULL)
4269 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4274 sprintf(cmdBuf, REMOTE_CMD_STRING, tmpReq->hostPtr, tmpReq->cmdPtr);
4277 * save cmdBuf for error message, cmdBuf is changed
4278 * by CreateExecString
4280 if (tmpCmdBuf != NULL)
4282 strcpy(tmpCmdBuf,cmdBuf);
4285 CreateExecString(cmdBuf);
4286 if(smExecArray[0] != NULL)
4288 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
4289 NULL, False, False, -1);
4291 if (tmpCmdBuf != NULL)
4293 tmpString = GETMESSAGE(16, 8,
4294 "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");
4297 (char *)SM_MALLOC((strlen(tmpString) +
4298 strlen((char *)tmpReq->hostPtr) +
4299 strlen((char *)tmpReq->cmdPtr) +
4300 strlen(tmpCmdBuf) + 1 ) *
4303 if(errorString == NULL)
4305 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4309 sprintf(errorString, tmpString, tmpReq->hostPtr,
4310 tmpReq->cmdPtr, tmpCmdBuf );
4311 PrintError(DtError, errorString);
4312 SM_FREE(errorString);
4317 * Now check to make sure that this isn't the last remote request.
4318 * If so, free the data
4322 if(numRemoteExecs == 0)
4324 for(i = 0;i < smGD.numSavedScreens;i++)
4326 if(actRemoteSize[i] > 0)
4328 SM_FREE((char *) remoteBuf[i]);
4338 /*************************************<->*************************************
4340 * RemoteRequestSucceeded ()
4345 * If a request to the command invoker succeeds, this callback will be called.
4346 * It decrements the remote execution counter, and frees the info if
4347 * remote executions are finished
4360 *************************************<->***********************************/
4362 RemoteRequestSucceeded(char *message,
4369 if(numRemoteExecs == 0)
4371 for(i = 0;i < smGD.numSavedScreens;i++)
4373 if(actRemoteSize[i] > 0)
4375 SM_FREE((char *) remoteBuf[i]);
4381 /**************************************************************************
4385 **************************************************************************/
4389 char * databaseName)
4392 XSMPClientDBRecPtr pXSMPRec;
4393 ProxyClientDBRecPtr pProxyRec;
4398 if ((inputDB = OpenInputClientDB (databaseName,
4400 &smXSMP.dbSessionId)) == NULL) {
4401 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogError, 1);
4405 if (!smXSMP.dbVersion) {
4406 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 2);
4407 smXSMP.dbVersion = SM_VENDOR_NAME;
4410 if (!smXSMP.dbSessionId) {
4411 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 3);
4412 smXSMP.dbSessionId = SM_RELEASE_NAME;
4416 * First start the XSMP clients
4420 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4423 if (!CheckRequiredProperties (pXSMPRec, databaseName)) {
4424 FreeXSMPClientDBRec (pXSMPRec);
4428 if (StartXSMPClient (pXSMPRec, databaseName)) {
4430 XSMPClientDBRecPtr tmpRecPtr;
4432 pXSMPRec->next = NULL;
4434 if (!smXSMP.xsmpDbList) {
4435 smXSMP.xsmpDbList = pXSMPRec;
4440 * Find the end of the list
4442 for (tmpRecPtr = smXSMP.xsmpDbList;
4443 tmpRecPtr && tmpRecPtr->next != NULL;
4444 tmpRecPtr = tmpRecPtr->next);
4446 tmpRecPtr->next = pXSMPRec;
4449 FreeXSMPClientDBRec (pXSMPRec);
4453 * Now start the Proxy clients
4455 for (i = 0; ; i++) {
4457 if ((pProxyRec = GetProxyClientDBRec (inputDB)) == NULL)
4460 if (!CheckRequiredFields (pProxyRec, databaseName, i)) {
4461 FreeProxyClientDBRec (pProxyRec);
4465 (void) StartProxyClient (pProxyRec);
4467 FreeProxyClientDBRec (pProxyRec);
4470 (void) CloseClientDB (inputDB, False);
4478 XSMPClientDBRecPtr pDbRec,
4479 char * databaseName)
4481 return (StartClient (pDbRec->restartCommand[0],
4482 pDbRec->restartCommand,
4485 pDbRec->environment,
4488 pDbRec->screenNum));
4494 ProxyClientDBRecPtr pDbRec)
4496 return (StartClient (pDbRec->command[0],
4503 pDbRec->screenNum));
4508 ExecuteCommandProperty (
4510 ClientRecPtr pClientRec)
4513 char ** envp = NULL;
4515 PropertyRecPtr pPropRec;
4519 if ((pPropRec = GetPropertyRec (pClientRec, commandName)) == NULL)
4522 argv = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4527 for (i = 0; i < pPropRec->prop.num_vals; i++)
4528 argv[i] = pPropRec->prop.vals[i].value;
4529 argv[pPropRec->prop.num_vals] = NULL;
4531 cwd = GetArrayPropertyValue (pClientRec, SmCurrentDirectory);
4534 if ((pPropRec = GetPropertyRec (pClientRec, SmEnvironment)) != NULL) {
4535 envp = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4540 for (i = 0; i < pPropRec->prop.num_vals; i++)
4541 envp[i] = pPropRec->prop.vals[i].value;
4542 envp[pPropRec->prop.num_vals] = NULL;
4545 retValue = StartClient (argv[0], argv,
4546 pClientRec->clientHost,
4549 pClientRec->screenNum);
4551 XtFree ((char *) argv);
4553 XtFree ((char *) envp);
4559 /*************************************<->*************************************
4561 * ExecuteDiscardCommands -
4563 * Description: Executes all of the DiscardCommand properties in the
4564 * given client database
4568 *************************************<->***********************************/
4570 ExecuteDiscardCommands (
4574 XSMPClientDBRecPtr pXSMPRec;
4575 char * version = NULL;
4579 if ((inputDB = OpenInputClientDB (db, &version, &id )) == NULL) {
4580 str = strdup ((char *) GETMESSAGE (40, 26,
4581 "The following client database cannot be opened:\n\n %s\n\nThe 'DiscardCommand' properties cannot be run."));
4584 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str, db);
4590 XtFree ((char *) version);
4592 XtFree ((char *) id);
4595 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4598 if (!pXSMPRec->discardCommand)
4601 if (!StartClient (pXSMPRec->discardCommand[0],
4602 pXSMPRec->discardCommand,
4603 pXSMPRec->clientHost,
4605 pXSMPRec->environment,
4608 pXSMPRec->screenNum)) {
4609 str = strdup ((char *) GETMESSAGE (40, 27,
4610 "An attempt to execute the 'DiscardCommand' property for\napplication '%s' failed."));
4613 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
4618 FreeXSMPClientDBRec (pXSMPRec);
4621 (void) CloseClientDB (inputDB, False);
4626 CheckRequiredProperties (
4627 XSMPClientDBRecPtr pDbRec,
4628 char * databaseName)
4630 Boolean propsOK = True;
4632 if (!pDbRec->program) {
4633 LogMissingPropertyMessage (pDbRec, SmProgram,
4634 databaseName, DtMsgLogError);
4638 if (!pDbRec->restartCommand) {
4639 LogMissingPropertyMessage (pDbRec, SmRestartCommand,
4640 databaseName, DtMsgLogError);
4649 CheckRequiredFields (
4650 ProxyClientDBRecPtr pDbRec,
4651 char * databaseName,
4656 if (!pDbRec->command) {
4658 message = strdup ((char *) GETMESSAGE (40, 11,
4659 "The required resource '%s' is missing for client '%d'\nin the file '%s'."));
4664 DtMsgLogMessage (smGD.programName, DtMsgLogError, message,
4665 SmProgram, clientNum, databaseName);
4677 LogXSMPOpenDatabaseFailure (
4678 char * databaseName,
4679 DtMsgLogType msgType,
4682 char * message = NULL;
4687 case 1: data = databaseName;
4689 message = strdup ((char *) GETMESSAGE (40, msgNum,
4690 "The following session database could not be opened:\n\n '%s'"));
4693 case 2: data = versionStr;
4695 message = strdup ((char *) GETMESSAGE (40, msgNum,
4696 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4699 case 3: data = dtsessionIDStr;
4701 message = strdup ((char *) GETMESSAGE (40, msgNum,
4702 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4710 DtMsgLogMessage (smGD.programName, msgType, message, data);
4712 DtMsgLogMessage (smGD.programName, msgType, message,
4713 data, databaseName);
4720 LogMissingPropertyMessage (
4721 XSMPClientDBRecPtr pDbRec,
4723 char * databaseName,
4724 DtMsgLogType msgType)
4728 message = strdup ((char *) GETMESSAGE (40, 10,
4729 "The required property '%s' is missing for client\n\n %s\n\nin the file '%s'."));
4734 DtMsgLogMessage (smGD.programName, msgType, message,
4735 propName, pDbRec->clientId, databaseName);
4749 message = strdup ((char *) GETMESSAGE (40, 12,
4750 "The directory '%s'\nis not available for application '%s'.\n\nThe following directory will be used:\n\n %s"));
4755 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, message,
4756 badDir, appName, goodDir);
4763 char ** RemoveEnvironmentVars (
4767 char ** retEnv = NULL;
4768 char **ppchar, **ppchar2;
4775 for (count = 0, ppchar = envp; ppchar && *ppchar; count++, ppchar++) ;
4777 retEnv = (char **) XtMalloc ((count + 1) * sizeof (char *));
4781 if (!ignoreEnvPtr) {
4782 for (count = 0, ppchar = envp; ppchar && *ppchar;
4783 count++, ppchar++) {
4784 retEnv[count] = *ppchar;
4786 retEnv[count] = NULL;
4791 for (count = 0, ppchar = envp; ppchar && *ppchar; ppchar++) {
4795 for (ppchar2 = ignoreEnvPtr; ppchar2 && *ppchar2; ppchar2++) {
4797 if ((!strncmp (*ppchar, *ppchar2, strlen (*ppchar2))) &&
4798 (((*ppchar)[strlen(*ppchar2)]) == '=')) {
4804 retEnv[count] = *ppchar;
4808 retEnv[count] = NULL;
4814 * MarkFileDescriptors - mark file descriptiors start_fd through open_max
4815 * with the given "cmd" and "data".
4817 * The code for calculating open_max was taken from DtSvc/DtUtil1/CmdMain.c
4820 MarkFileDescriptors (
4828 open_max = sysconf(_SC_OPEN_MAX);
4830 if (open_max == -1) {
4835 open_max = FOPEN_MAX;
4837 open_max = FD_SETSIZE;
4839 #endif /* _SUN_OS */
4842 for (i = start_fd; i < open_max; i++)
4843 (void) fcntl (i, cmd, data);