2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: SmRestore.c /main/26 1998/12/14 20:13:07 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /*************************************<+>*************************************
31 *****************************************************************************
35 ** Project: HP DT Session Manager (dtsession)
39 ** This file contains functions that are in charge of restoring state.
40 ** When the session manager is first started, it restores the state that
41 ** was either last saved (home state), or last exited (current state). The
42 ** state restored depends on values the user has configured.
46 *******************************************************************
47 ** (c) Copyright Hewlett-Packard Company, 1990. All rights are
48 ** reserved. Copying or other reproduction of this program
49 ** except for archival purposes is prohibited without prior
50 ** written consent of Hewlett-Packard Company.
51 ********************************************************************
55 *****************************************************************************
56 *************************************<+>*************************************/
62 #ifdef _SUN_OS /* to get the define for NOFILE */
63 #include <sys/param.h>
65 #include <sys/types.h>
68 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
70 #include <sys/socket.h>
72 #include <netinet/in.h>
77 #include <X11/Intrinsic.h>
78 #include <X11/Xutil.h>
79 #include <X11/Xatom.h>
80 #include <X11/StringDefs.h>
81 #include <X11/keysymdef.h>
82 #include <X11/SM/SMlib.h>
86 # define Va_start(a,b) va_start(a,b)
89 #include <Dt/Message.h>
90 #include <Dt/CommandM.h>
91 #include <Dt/Connect.h>
94 #include <Dt/UserMsg.h>
95 #include <Dt/SessionM.h>
96 #include <Dt/EnvControlP.h>
97 #include <Dt/Utility.h>
98 #include <Dt/MsgLog.h>
100 #include <Dt/CmdInv.h>
101 #include <Dt/ActionUtilP.h>
104 #include "SmResource.h"
106 #include "SmCommun.h"
107 #include "SmRestore.h"
108 #include "SmProtocol.h"
109 #include "SmConMgmt.h"
112 #include "SmGlobals.h"
117 #include <X11/Xlibint.h>
122 static const char * DISPLAY_NAME_EQUAL = "DISPLAY=";
123 static const char * DISPLAY_NAME = "DISPLAY";
124 static char * savedDisplay = NULL;
130 #define MAXPATHSM 1023
131 #define MAX_QUOTE_DEPTH 10
133 #define SM_MAX_ARGS MAXLINE
136 #define REMOTE_CMD_STRING "rsh %s -n %s &"
138 #define REMOTE_CMD_STRING "remsh %s -n %s &"
147 unsigned char *hostPtr;
148 unsigned char *cmdPtr;
152 * Variables global to this module only
154 static XtResource settingsResources[] =
156 {SmNaccelNum, SmCaccelNum, XtRInt, sizeof(int),
157 XtOffset(SessionSettingsPtr, accelNum),
158 XtRImmediate, (XtPointer) -1},
159 {SmNaccelDenom, SmCaccelDenom, XtRInt, sizeof(int),
160 XtOffset(SessionSettingsPtr, accelDenom),
161 XtRImmediate, (XtPointer) -1},
162 {SmNthreshold, SmCthreshold, XtRInt, sizeof(int),
163 XtOffset(SessionSettingsPtr, threshold),
164 XtRImmediate, (XtPointer) -1},
166 {SmNtimeout, SmCtimeout, XtRInt, sizeof(int),
167 XtOffset(SessionSettingsPtr, timeout),
168 XtRImmediate, (XtPointer) -1},
169 {SmNinterval, SmCinterval, XtRInt, sizeof(int),
170 XtOffset(SessionSettingsPtr, interval),
171 XtRImmediate, (XtPointer) -1},
172 {SmNpreferBlank, SmCpreferBlank, XtRInt, sizeof(int),
173 XtOffset(SessionSettingsPtr, preferBlank),
174 XtRImmediate, (XtPointer) 0},
175 {SmNallowExp, SmCallowExp, XtRInt, sizeof(int),
176 XtOffset(SessionSettingsPtr, allowExp),
177 XtRImmediate, (XtPointer) 0},
179 {SmNfontPath, SmCfontPath, XtRString, sizeof(String),
180 XtOffset(SessionSettingsPtr, fontDirs), XtRString, (XtPointer) ""},
182 {SmNkeyClick, SmCkeyClick, XtRInt, sizeof(int),
183 XtOffset(SessionSettingsPtr, kbdState.key_click_percent),
184 XtRImmediate, (XtPointer) -1},
185 {SmNbellPercent, SmCbellPercent, XtRInt, sizeof(int),
186 XtOffset(SessionSettingsPtr, kbdState.bell_percent),
187 XtRImmediate, (XtPointer) -1},
188 {SmNbellPitch, SmCbellPitch, XtRInt, sizeof(int),
189 XtOffset(SessionSettingsPtr, kbdState.bell_pitch),
190 XtRImmediate, (XtPointer) -1},
191 {SmNbellDuration, SmCbellDuration, XtRInt, sizeof(int),
192 XtOffset(SessionSettingsPtr, kbdState.bell_duration),
193 XtRImmediate, (XtPointer) -1},
194 {SmNledMask, SmCledMask, XtRInt, sizeof(int),
195 XtOffset(SessionSettingsPtr, kbdState.led_mask),
196 XtRImmediate, (XtPointer) 0},
197 {SmNglobalRepeats, SmCglobalRepeats, XtRInt, sizeof(int),
198 XtOffset(SessionSettingsPtr, kbdState.global_auto_repeat),
199 XtRImmediate, (XtPointer) 2},
200 {SmNautoRepeats, SmCautoRepeats, XtRString, sizeof(String),
201 XtOffset(SessionSettingsPtr, autoRepeats), XtRString, (XtPointer) ""},
203 {SmNbuttonMap, SmCbuttonMap, XtRString, sizeof(String),
204 XtOffset(SessionSettingsPtr, buttonMap), XtRString, (XtPointer) ""},
206 {SmNnumKeyCode, SmCnumKeyCode, XtRInt, sizeof(int),
207 XtOffset(SessionSettingsPtr, numKeyCode), XtRImmediate, (XtPointer) 0},
208 {SmNkeySymsPerKey, SmCkeySymsPerKey, XtRInt, sizeof(int),
209 XtOffset(SessionSettingsPtr, keySymPerCode),
210 XtRImmediate, (XtPointer) 0},
211 {SmNkeySyms, SmCkeySyms, XtRString, sizeof(String),
212 XtOffset(SessionSettingsPtr, keySyms), XtRString, (XtPointer) ""},
214 {SmNmaxKeyPerMod, SmCmaxKeyPerMod, XtRInt, sizeof(int),
215 XtOffset(SessionSettingsPtr, maxKeyPerMod),
216 XtRImmediate, (XtPointer) 0},
217 {SmNmodMap, SmCmodMap, XtRString, sizeof(String),
218 XtOffset(SessionSettingsPtr, modSyms),
219 XtRString, (XtPointer) ""},
221 {SmNdidQuerySettings, SmCdidQuerySettings, XtRBoolean, sizeof(Boolean),
222 XtOffset(SessionSettingsPtr, didQuery),
223 XtRImmediate, (XtPointer) False},
224 {SmNshutDownState, SmCshutDownState, XtRInt, sizeof(int),
225 XtOffset(SessionSettingsPtr, confirmMode),
226 XtRImmediate, (XtPointer) 1},
227 {SmNshutDownMode, SmCshutDownMode, XtRInt, sizeof(int),
228 XtOffset(SessionSettingsPtr, startState),
229 XtRImmediate, (XtPointer) 4},
233 * Variables used for parsing code
236 static unsigned char fallBackLine[MAXLINE+2]; /* line buffer */
237 static unsigned char *line; /* line buffer */
238 static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
239 static int linec = 0; /* line counter for parser */
240 static unsigned char *parseP = NULL; /* pointer to parse string */
241 static int fileSize = 0;
242 char **smExecArray = NULL;
245 * Variables used for remote execution
247 static int numRemoteExecs = 0;
248 unsigned char *remoteBuf[MAX_SCREENS_SAVED];
249 unsigned int actRemoteSize[MAX_SCREENS_SAVED];
250 RemoteReq remoteBufPtr[MAX_REMOTE_CLIENTS];
251 static char localHost[MAXHOSTNAMELEN];
252 static char ** ignoreEnvPtr = NULL;
255 * Timeout for workspace manager handshake
257 static Boolean wmTimeout;
260 * These lines were added to support the builtin
264 char tmpExecWmFile[MAXPATHSM+1];
265 static Boolean localWmLaunched = False;
268 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
269 * End of lines were added to support the builtin
284 "*XmTextField*FontList",
285 "*DtEditor*textFontList",
290 static char *fontclass[] = {
298 "*XmTextField*FontList",
299 "*DtEditor*textFontList",
308 static int RestoreSettings( void ) ;
309 static int RestoreClients( void ) ;
310 static unsigned char * GetNextLine( void ) ;
311 static unsigned int PeekAhead( unsigned char *, unsigned int ) ;
312 static unsigned char * GetSmartString( unsigned char **) ;
313 static void ForkWM( void ) ;
314 static int FillCmdBuf( unsigned char *, unsigned char **,
315 unsigned int *, unsigned int *,
316 unsigned int, unsigned int *) ;
317 static int FillRemoteBuf( unsigned char *, unsigned char *,
318 unsigned char *, unsigned char **,
319 unsigned int *, unsigned int *, unsigned int) ;
320 static int FillHintBuf(unsigned char *, unsigned char **,
321 unsigned int *, unsigned int *,
322 unsigned int, unsigned int *);
323 static void WaitForWM( void ) ;
324 static void HandleWMClientMessage(Widget smWidget, XtPointer dummy,
326 static void WaitWMTimeout( XtPointer , XtIntervalId *) ;
327 static void FixEnvironmentData( void ) ;
328 static void ResetScreenInfo(unsigned char **,
329 int *, unsigned int *,
332 static void RemoteRequestFailed(char *, void *);
333 static void RemoteRequestSucceeded(char *, void *);
335 static void SetTemporaryDisplay (
338 int RestorePreferences(char *filename);
340 static void RestoreDisplay (
343 static Boolean StartLocalClient (
349 Boolean useIgnoreEnvResource);
351 static Boolean StartRemoteClient (
357 Boolean useIgnoreEnvResource);
359 static Boolean CheckRequiredProperties (
360 XSMPClientDBRecPtr pDbRec,
361 char * databaseName);
363 static Boolean CheckRequiredFields (
364 ProxyClientDBRecPtr pDbRec,
368 static void LogXSMPOpenDatabaseFailure (
370 DtMsgLogType msgType,
373 static void LogMissingPropertyMessage (
374 XSMPClientDBRecPtr pDbRec,
377 DtMsgLogType msgType);
379 static void LogCWDMessage (
384 static char ** RemoveEnvironmentVars (
387 static void MarkFileDescriptors (
393 /*************************************<->*************************************
400 * Sets _DT_SM_STATE_INFO for dtstyle indicating compatibility mode
413 * The only thing dtstyle should be looking at is the compatMode
415 *************************************<->***********************************/
417 SetCompatState( void )
422 * BEFORE any clients are started
423 * set a property on the top level window
424 * which lets the style manager know what state the sm is in
426 state.flags = SM_STATE_ALL;
427 state.smStartState = 0;
428 state.smConfirmMode = 0;
429 state.smCompatMode = True;
430 state.smSendSettings = False;
431 state.smCoverScreen = True;
432 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
433 state.smCycleTimeout = 0;
434 state.smLockTimeout = 0;
435 state.smSaverTimeout = 0;
437 state.smDisplaySpecific = smGD.displaySpecific;
439 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
441 XFlush(smGD.display);
445 } /* END OF FUNCTION SetCompatState */
448 /*************************************<->*************************************
455 * This function fiddles with our signal handling and calls the
456 * system() function to invoke a unix command.
461 * pchCmd = string with the command we want to exec.
469 * The system() command is touchy about the SIGCLD behavior. Restore
470 * the default SIGCLD handler during the time we run system().
472 *************************************<->***********************************/
475 SystemCmd (char *pchCmd)
477 void (*signalHandler) ();
479 signalHandler = (void (*)())signal (SIGCHLD, SIG_DFL);
483 signal (SIGCHLD, signalHandler);
484 } /* END OF FUNTION SystemCmd */
488 /*************************************<->*************************************
504 * When this routine is finished, all settings and resources will be restored.
505 * Clients may not be, as they are actually restored by different processes.
507 *************************************<->***********************************/
513 char convertCommand[MAXPATHSM+1];
515 Boolean fixedBuffer = False;
518 Boolean useXrmDB = False;
521 * Restore all the X settings which were active at the time of shutdown
525 if (smGD.sessionType == HOME_SESSION)
526 smSettings.startState = DtSM_HOME_STATE;
528 smSettings.startState = DtSM_CURRENT_STATE;
531 * BEFORE any clients are started
532 * set a property on the top level window
533 * which lets the style manager know what state the sm is in
535 state.flags = SM_STATE_ALL;
536 state.smStartState = smSettings.startState;
537 state.smConfirmMode = smSettings.confirmMode;
538 state.smCompatMode = smGD.compatMode;
539 state.smSendSettings = !smRes.querySettings;
540 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
541 state.smCycleTimeout = smSaverRes.cycleTimeout;
542 state.smLockTimeout = smSaverRes.lockTimeout;
543 state.smSaverTimeout = smSaverRes.saverTimeout;
544 state.smRandom = smSaverRes.random;
545 state.smDisplaySpecific = smGD.displaySpecific;
547 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
549 saver.saverList = smGD.saverList;
550 _DtSetSmSaver(smGD.display, smGD.topLevelWindow, &saver);
553 * Set up the Property telling all applications what session is being
556 XaSmRestoreMode = XInternAtom(smGD.display, _XA_DT_RESTORE_MODE, False);
557 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
558 XaSmRestoreMode, XA_STRING, 8, PropModeReplace,
559 (unsigned char *)smGD.restoreSession, strlen(smGD.restoreSession));
560 XFlush(smGD.display);
563 * Check the session database and either parse it as an
564 * Xrm-database or the CDE1.0 format
566 if ((pchar = strrchr (smGD.clientPath, '/')) != NULL)
569 if ((*pchar != '\0') && (!strcmp (pchar, SM_CLIENT_FILE2)))
575 return (StartXSMPSession (smGD.clientPath));
579 * Malloc line for parsing.
581 status = stat(smGD.clientPath, &buf);
584 fileSize = buf.st_size;
587 if (fileSize < MAXLINE + 1)
589 fileSize = MAXLINE + 1;
592 line = malloc(fileSize + 1);
596 fileSize = MAXLINE + 1;
599 cfileP = fopen(smGD.clientPath, "r");
602 PrintErrnoError(DtError, smNLS.cantOpenFileString);
603 if (!fixedBuffer && line)
605 SM_FREE((char *)line);
612 if (!fixedBuffer && line)
614 SM_FREE((char *)line);
623 /*************************************<->*************************************
630 * Start up the window manager. The default is to start dtmwm unless
631 * another one is specified in a resource.
644 * When this routine is finished, all settings and resources will be restored.
645 * Clients may not be, as they are actually restored by different processes.
647 *************************************<->***********************************/
651 char wmStartupErrorString[(2 * MAXPATHSM) + 1];
652 char localWmErrorString[(2 * MAXPATHSM) + 1];
653 Boolean goodWmStartup = True;
656 if((smGD.wmStartup == NULL) || (*smGD.wmStartup == 0))
662 CreateExecString(smGD.wmStartup);
665 * check to see if the wmStartup string exists and is
668 status = access(smExecArray[0], F_OK | X_OK);
671 goodWmStartup = False;
672 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
675 if(smExecArray[0] != NULL)
677 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
678 NULL, False, False, -1);
683 * We used to start the message server before the window
684 * manager and then if the message server did not start
685 * we would exit. Now we start the window manager, then
686 * start the message server and then wait for the window
687 * manager. This seems to improve performance.
692 if (goodWmStartup == False)
694 sprintf(wmStartupErrorString, GETMESSAGE(16, 7,
695 "The wmStartupCommand resource is set to:\n\n"
697 "This file does not exist or is not executable.\n"
698 CDE_INSTALLATION_TOP "/bin/dtwm will be started "
701 PrintError(DtError, wmStartupErrorString);
707 * These lines were added to support the builtin
711 if (localWmLaunched && wmTimeout)
713 if (!smGD.userSetWaitWmTimeout)
715 smRes.waitWmTimeout = smGD.savedWaitWmTimeout;
718 localWmLaunched = False;
720 * A special version of a built-in Xterminal dtwm
721 * was attempted and failed.
722 * Try to launch .../dt/bin/dtwm instead
725 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
726 if(smExecArray[0] != NULL)
728 (void) StartClient(smExecArray[0], smExecArray, NULL,
729 NULL, NULL, False, False, -1);
732 sprintf(localWmErrorString, GETMESSAGE(16, 9,
733 "The following window manager did not start:\n\n"
735 "This message indicates you tried to start a\n"
736 "window manager that is built into an X terminal.\n"
737 "This will only work with X terminals that support this protocol.\n"
738 CDE_INSTALLATION_TOP "/bin/dtwm will be started instead.\n"),
740 PrintError(DtError, localWmErrorString);
743 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
744 * End of lines were added to support the builtin
753 /*************************************<->*************************************
760 * Reloads RESOURCE_MANAGER during running session
772 *************************************<->***********************************/
775 ReloadResources(void)
778 * Load sys.resources and .Xdefaults
780 RestoreResources(True,
787 * Merge _DT_SM_PREFERENCES
789 RestorePreferences(NULL);
795 /*************************************<->*************************************
797 * RestoreResources (errorHandlerInstalled, options ... )
802 * Calls routines responsible for restoring resources.
803 * Resources are restored by a fork and exec of dtsession_res.
816 * When this routine is finished, all settings and resources will be restored.
817 * Clients may not be, as they are actually restored by different processes.
819 *************************************<->***********************************/
822 RestoreResources( Boolean errorHandlerInstalled, ... )
825 int childStatus, execStatus, i;
831 /* JET - this seems like a bad (and unused) idea */
833 * Check for alternate resource loader.
835 if ((pgrm = getenv("DTLOADRESOURCES")) == NULL)
837 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
840 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
844 * By convention, exec() wants arg0 to be the program name. Ex: if pgrm
845 * is /usr/dt/bin/dtsession_res, the program name is dtsession_res.
846 * If all else fails, use pgrm.
848 argv[0] = (p = strrchr(pgrm, '/')) != NULL && *(p+1) != '\0' ? p+1 : pgrm;
851 Va_start(args,errorHandlerInstalled);
855 argv[i] = va_arg(args, char *);
861 * if an error handler is installed - remove it
863 if(errorHandlerInstalled)
865 sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
869 * Fork and exec the xrdb process to load in the file created by
870 * writing out the resource manager string generated by the last
871 * session termination.
874 for(i = 0;(i < 10) && ((forkrc = vfork()) < 0);i++)
885 PrintErrnoError(DtError, smNLS.cantForkClientString);
890 * Fork succeeded - now do the exec
894 SetSIGPIPEToDefault ();
898 * Set the gid of the process back from bin
901 setregid(smGD.runningGID, smGD.runningGID);
903 setgid(smGD.runningGID);
904 setegid(smGD.runningGID);
907 #if defined(CSRG_BASED)
911 #endif /* CSRG_BASED */
913 MarkFileDescriptors (3, F_SETFD, 1);
915 execStatus = execv(pgrm, argv);
919 char clientMessage[MAXPATHLEN + 256];
921 memset(clientMessage, 0, MAXPATHLEN + 256);
922 snprintf(clientMessage, (MAXPATHLEN + 256) - 1,
923 ((char *)GETMESSAGE(16, 1, "Unable to exec process %s. No session resources will be restored.")), pgrm);
924 PrintErrnoError(DtError, clientMessage);
929 while(wait(&childStatus) != forkrc);
932 * if an error handler is installed - remove it
934 if(errorHandlerInstalled)
936 sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
943 /*************************************<->*************************************
945 * RestorePreferences ( filename)
951 * This routine has two roles:
953 * 1) If 'filename' specified, the content of filename is read, and
954 * _DT_SM_PREFERENCES is populated with its content. This is used
955 * at session startup to set the initial state of _DT_SM_PREFERENCES.
957 * 2) If 'filename' is NULL, the content of _DT_SM_PREFERENCES is
958 * merged into RESOURCE_MANAGER. This is used when resources are
959 * reloaded at user request during a session.
972 *************************************<->***********************************/
984 struct stat statinfo;
986 if(access(filename,R_OK) != 0)
992 * Determine size of file.
994 if (stat(filename, &statinfo) == -1)
1002 if ((data = (char *)SM_MALLOC(statinfo.st_size + 1)) == NULL)
1008 * Read file into memory.
1010 if ((fp = fopen(filename, "r")) == NULL)
1016 size = fread(data, 1, statinfo.st_size, fp);
1018 if (size == statinfo.st_size)
1021 * Merge .Xdefaults string into RESOURCE_MANAGER database, and
1022 * also convert to Xrm database form for later subtraction.
1025 _DtAddResString(smGD.display, data, _DT_ATR_PREFS);
1033 * Read string from _DT_SM_PREFERENCES
1035 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1038 * Merge string into RESOURCE_MANAGER
1040 _DtAddResString(smGD.display, data, _DT_ATR_RESMGR);
1049 /*************************************<->*************************************
1051 * RestoreSettings ()
1056 * In charge of restoring all settings. Settings are stored in resource
1057 * format so it gets the values by getting the resource values stored in
1058 * a resource file that was created by the session manager.
1063 * smGD.settingPath = path that points to the settings resource file.
1072 * This routine messes with the actual strings returned by the resource
1073 * manager by tokenizing them, so these session settings resources should
1074 * not be accessed again.
1076 *************************************<->***********************************/
1078 RestoreSettings( void )
1080 XrmDatabase smBase = NULL;
1081 XKeyboardControl kbdControl;
1083 char **restorePtrArray, **tmpRestore;
1084 char *restoreCharArray;
1085 int numArgs, ptrSize, charSize;
1088 KeySym *tmpSyms, codeSym;
1091 XModifierKeymap restoreMod;
1095 restorePtrArray = (char **) SM_MALLOC (ptrSize * sizeof(char *));
1096 restoreCharArray = (char *) SM_MALLOC (charSize * sizeof(char));
1097 if((restorePtrArray == NULL) || (restoreCharArray == NULL))
1099 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1101 if(restorePtrArray != NULL)
1103 SM_FREE((char *) restorePtrArray);
1107 if(restoreCharArray != NULL)
1109 SM_FREE(restoreCharArray);
1116 * Load the resources from the SM database file
1118 if (smGD.settingPath[0] != 0)
1120 smBase = XrmGetFileDatabase(smGD.settingPath);
1124 PrintError(DtError, GETMESSAGE(16, 2, "Invalid client settings file. No settings restored."));
1129 XrmMergeDatabases(smBase, &(smGD.display->db));
1134 * Retrieve the session settings file from the database
1136 XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smSettings,
1137 settingsResources, XtNumber(settingsResources),
1141 * Copy any string resources since they may be overwritten in
1144 smGD.fontDirs = SmNewString(smSettings.fontDirs);
1145 smGD.autoRepeats = SmNewString(smSettings.autoRepeats);
1146 smGD.buttonMap = SmNewString(smSettings.buttonMap);
1147 smGD.keySyms = SmNewString(smSettings.keySyms);
1148 smGD.modSyms = SmNewString(smSettings.modSyms);
1152 * This is provided for backward compatibility sake. The values that
1153 * confirmMode can take have changed
1155 if(smSettings.confirmMode == DtSM_ASK_STATE)
1157 smSettings.confirmMode = DtSM_VERBOSE_MODE;
1161 * If the user has previously used the "query" method, and now wishes
1162 * to use "only what I've customized" method, then we have to start
1163 * from scratch. So don't set anything until customizer tells me to
1165 if((smSettings.didQuery == True) && (smRes.querySettings == False))
1167 SM_FREE((char *) restorePtrArray);
1168 SM_FREE(restoreCharArray);
1173 * Restore pointer control settings
1175 if((smSettings.accelNum > -1 ) || (smSettings.threshold > -1))
1177 XChangePointerControl(smGD.display, True, True,
1178 smSettings.accelNum,
1179 smSettings.accelDenom,
1180 smSettings.threshold);
1181 smToSet.pointerChange = True;
1185 smToSet.pointerChange = False;
1189 * Restore screen saver settings if any are set to non-default
1192 if ((smSettings.timeout > -1) || (smSettings.interval > -1) ||
1193 (smSaverRes.saverTimeout > -1) || (smSaverRes.lockTimeout > -1) ||
1194 (smSaverRes.cycleTimeout > -1))
1198 * For the time between Screen Savers, use the cycleTimeout
1199 * if the user has set this value. Otherwise, use the interval
1200 * value that was set when the session was saved.
1202 if (smSaverRes.cycleTimeout < 0)
1204 screenSaverVals.smInterval = smSettings.interval;
1208 screenSaverVals.smInterval = smSaverRes.cycleTimeout;
1212 * For the screen saver time, use the minimum of the values set for
1213 * saverTimeout or lockTimeout if the user has set one of these
1216 * Otherwise, use the Timeout value that was set when the
1217 * session was saved.
1219 * If it is not set, then use the minimum of the values set for
1220 * saverTimeout or lockTimeout. Set timeout to the Timeout value
1223 if ((smSaverRes.saverTimeout > -1) ||
1224 (smSaverRes.lockTimeout > -1))
1226 if (smSaverRes.saverTimeout > -1)
1228 if ((smSaverRes.lockTimeout > -1) &&
1229 (smSaverRes.lockTimeout < smSaverRes.saverTimeout))
1231 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1235 screenSaverVals.smTimeout = smSaverRes.saverTimeout;
1240 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1245 screenSaverVals.smTimeout = smSettings.timeout;
1247 screenSaverVals.smPreferBlank = smSettings.preferBlank;
1248 screenSaverVals.smAllowExp = smSettings.allowExp;
1250 /* Notify X of the new screen saver values */
1251 XSetScreenSaver(smGD.display, screenSaverVals.smTimeout,
1252 screenSaverVals.smInterval,
1253 screenSaverVals.smPreferBlank,
1254 screenSaverVals.smAllowExp);
1257 * If using timeout or interval values that were
1258 * previously saved, then set flag to indicate that they
1259 * should be saved again when the state for the session
1262 if ((smSettings.timeout > -1) || (smSettings.interval > -1))
1264 smToSet.screenSavChange = True;
1268 smToSet.screenSavChange = False;
1274 smToSet.screenSavChange = False;
1278 * Get the font path. Then set it.
1280 tmpRestore = restorePtrArray;
1282 *tmpRestore = strtok(smGD.fontDirs, ",");
1284 while(*tmpRestore != NULL)
1286 numArgs++; tmpRestore++;
1287 *tmpRestore = strtok(NULL, ",");
1288 if((numArgs >= ptrSize) && (*tmpRestore != NULL))
1291 restorePtrArray = (char **)SM_REALLOC((char *)
1292 restorePtrArray, ptrSize *
1294 if(restorePtrArray == NULL)
1296 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1297 SM_FREE(restoreCharArray);
1305 XSetFontPath(smGD.display, restorePtrArray, numArgs);
1309 * Restore the keyboard control information. In order for it
1310 * to be restored it has to be changed from a XKeyboardState
1311 * format to an XKeyboardControl format.
1313 if((smSettings.kbdState.key_click_percent > -1) ||
1314 (smSettings.kbdState.bell_percent > -1) ||
1315 (smSettings.kbdState.bell_pitch > -1) ||
1316 (smSettings.kbdState.bell_duration > -1))
1320 if((smSettings.kbdState.bell_percent > -1) ||
1321 (smSettings.kbdState.bell_pitch > -1) ||
1322 (smSettings.kbdState.bell_duration > -1))
1324 kbdControl.bell_percent = smSettings.kbdState.bell_percent;
1325 kbdControl.bell_pitch = smSettings.kbdState.bell_pitch;
1326 kbdControl.bell_duration = smSettings.kbdState.bell_duration;
1327 kbdControlMask |= (KBBellPercent | KBBellPitch | KBBellDuration);
1328 smToSet.audioChange = True;
1329 audioVals.smBellPercent = smSettings.kbdState.bell_percent;
1330 audioVals.smBellPitch = smSettings.kbdState.bell_pitch;
1331 audioVals.smBellDuration = smSettings.kbdState.bell_duration;
1335 smToSet.audioChange = False;
1338 if((smSettings.kbdState.key_click_percent > -1) ||
1339 (smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn))
1341 kbdControl.key_click_percent =
1342 smSettings.kbdState.key_click_percent;
1343 kbdControlMask |= KBKeyClickPercent;
1344 smToSet.keyboardChange = True;
1345 keyboardVals.smKeyClickPercent = kbdControl.key_click_percent;
1349 smToSet.keyboardChange = False;
1354 * NOTICE THAT THE LED'S DON'T GET RESET. THIS IS BECAUSE LED STUFF
1355 * IS MACHINE DEPENDENT.
1358 * Set the auto repeat stuff
1360 tmpKey = strtok(smGD.autoRepeats, ",");
1361 if((tmpKey == NULL) &&
1362 ((smSettings.kbdState.global_auto_repeat == AutoRepeatModeOff) ||
1363 (smSettings.kbdState.global_auto_repeat == AutoRepeatModeOn)))
1365 smToSet.keyboardChange = True;
1366 kbdControl.auto_repeat_mode =
1367 smSettings.kbdState.global_auto_repeat;
1368 kbdControlMask |= KBAutoRepeatMode;
1369 XChangeKeyboardControl(smGD.display, kbdControlMask, &kbdControl);
1370 keyboardVals.smGlobalAutoRepeat =
1371 smSettings.kbdState.global_auto_repeat;
1377 smToSet.keyboardChange = True;
1378 kbdControl.auto_repeat_mode = smSettings.kbdState.global_auto_repeat;
1379 kbdControlMask |= KBAutoRepeatMode;
1380 XChangeKeyboardControl(smGD.display,
1381 kbdControlMask, &kbdControl);
1382 kbdControl.auto_repeat_mode = AutoRepeatModeOn;
1383 kbdControlMask = KBAutoRepeatMode | KBKey;
1385 * This is only involked when there is auto repeats set for
1386 * specific keys only. It is VERY SLOW code so unless you
1387 * have to save off auto repeats for single keys - DONT
1389 while(tmpKey != NULL)
1391 kbdControl.key = atoi(tmpKey);
1392 XChangeKeyboardControl(smGD.display,
1393 kbdControlMask, &kbdControl);
1394 tmpKey = strtok(NULL, ",");
1399 if(kbdControlMask != 0)
1401 XChangeKeyboardControl(smGD.display,
1402 kbdControlMask, &kbdControl);
1409 smToSet.audioChange = False;
1410 smToSet.keyboardChange = False;
1414 * Restore the button mappings
1417 tmpKey = strtok(smGD.buttonMap, ",");
1421 smToSet.pointerMapChange = True;
1425 smToSet.pointerMapChange = False;
1428 while(tmpKey != NULL)
1430 restoreCharArray[numArgs] = (char) atoi(tmpKey);
1432 tmpKey = strtok(NULL, ",");
1433 if((numArgs >= charSize) && (tmpKey != NULL))
1436 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1437 charSize * sizeof(char));
1438 if(restoreCharArray == NULL)
1440 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1441 SM_FREE((char *)restorePtrArray);
1449 XSetPointerMapping(smGD.display, (unsigned char *)restoreCharArray, numArgs);
1452 * Copy the pointer map into the saved map for logout
1454 smToSet.numButton = ((numArgs > 5) ? 5 : numArgs);
1455 for(i = 0; i < smToSet.numButton;i++)
1457 smToSet.pointerMap[i] = restoreCharArray[i];
1462 * Restore the key mappings
1464 if(smSettings.numKeyCode > 0)
1466 tmpSyms = (KeySym *) restoreCharArray;
1467 symSize = (charSize * sizeof(char)) / sizeof(KeySym);
1468 tmpKey = strtok(smGD.keySyms, ",");
1469 for(i = 0;tmpKey != NULL;i++)
1471 tmpSyms[i] = (KeySym) atol(tmpKey);
1472 tmpKey = strtok(NULL, ",");
1474 if((numArgs >= symSize) && (tmpKey != NULL))
1477 symSize = (charSize * sizeof(char))/sizeof(KeySym);
1478 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1479 (charSize * sizeof(char)));
1480 if(restoreCharArray == NULL)
1482 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1483 SM_FREE((char *) restorePtrArray);
1486 tmpSyms = (KeySym *) restoreCharArray;
1489 numArgs /= smSettings.keySymPerCode;
1490 XChangeKeyboardMapping(smGD.display, (KeyCode)
1491 smGD.display->min_keycode,
1492 smSettings.keySymPerCode, tmpSyms,
1497 * Restore the modifier mappings
1499 tmpCode = (KeyCode *) restoreCharArray;
1500 tmpKey = strtok(smGD.modSyms, ",");
1503 for(i = 0;i < (8 * smSettings.maxKeyPerMod);i++)
1507 codeSym = (KeySym) atol(tmpKey);
1510 tmpCode[i] = XKeysymToKeycode(smGD.display, codeSym);
1514 tmpCode[i] = (KeyCode) 0;
1519 tmpCode[i] = (KeyCode) 0;
1521 tmpKey = strtok(NULL, ",");
1523 restoreMod.max_keypermod = smSettings.maxKeyPerMod;
1524 restoreMod.modifiermap = tmpCode;
1525 XSetModifierMapping(smGD.display, &restoreMod);
1528 SM_FREE((char *) restorePtrArray);
1529 SM_FREE(restoreCharArray);
1536 /*************************************<->*************************************
1538 * RestoreIndependentResources ()
1543 * In charge of restoring the resources that help make the session more
1544 * resolution and language independent - only restored if they are
1545 * necessary (lang || resolution has changed) and exist
1550 * smResources = global pointer to the resources to be restored by the SM
1560 *************************************<->***********************************/
1562 RestoreIndependentResources( void )
1566 unsigned long nitems, leftover;
1567 unsigned char *data = NULL;
1569 XrmValue fontResourceReturn;
1570 char *currentLangPtr, *resValRet, *sessionType;
1572 int intYRes[2], status,i;
1575 Boolean resIndep = False, resRet;
1578 if(((smGD.sessionLang == NULL) || (*smGD.sessionLang == 0)) &&
1579 (smRes.displayResolution == 0))
1582 * No saved info to draw from - nothing new is added
1587 currentLangPtr = getenv("LANG");
1589 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1590 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1592 if(fltYRes < MED_RES_Y_RES)
1594 intYRes[0] = LOW_RES_Y_RES;
1595 sessionRes = SM_LOW_RES_EXT;
1599 if(fltYRes >= HIGH_RES_Y_RES)
1601 intYRes[0] = HIGH_RES_Y_RES;
1602 sessionRes = SM_HIGH_RES_EXT;
1606 intYRes[0] = MED_RES_Y_RES;
1607 sessionRes = SM_MED_RES_EXT;
1611 if(smRes.displayResolution < MED_RES_Y_RES)
1613 intYRes[1] = LOW_RES_Y_RES;
1617 if(smRes.displayResolution >= HIGH_RES_Y_RES)
1619 intYRes[1] = HIGH_RES_Y_RES;
1623 intYRes[1] = MED_RES_Y_RES;
1628 * If the resolution or the language has changed -
1629 * load the language/resolution independent fonts if
1630 * they exist in the users home directory or in the system
1632 if((strcmp(currentLangPtr, smGD.sessionLang)) ||
1633 (intYRes[0] != intYRes[1]))
1635 char *fontPath = SM_MALLOC(MAXPATHLEN + 1);
1637 if(smGD.sessionType == HOME_SESSION)
1639 sessionType = SM_HOME_FONT_DIRECTORY;
1643 sessionType = SM_CURRENT_FONT_DIRECTORY;
1646 memset(fontPath, 0, MAXPATHLEN + 1);
1647 snprintf(fontPath, MAXPATHLEN, "%s/%s/%s/%s.%s",
1648 smGD.savePath, sessionType,
1649 currentLangPtr, SM_FONT_FILE, sessionRes);
1650 status = stat(fontPath, &buf);
1654 * User has nothing there - look in the system defaults
1655 * first in the language dep -then in lang independent
1657 memset(fontPath, 0, MAXPATHLEN + 1);
1659 if((currentLangPtr != NULL) && (*currentLangPtr != 0))
1661 strcat(fontPath, "/");
1662 strncat(fontPath, currentLangPtr, MAXPATHLEN);
1665 strncat(fontPath, "/", MAXPATHLEN);
1666 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1670 status = stat(fontPath, &buf);
1673 if((currentLangPtr != NULL) && (*currentLangPtr != 0) &&
1674 (strcmp(currentLangPtr, "C")))
1676 memset(fontPath, 0, MAXPATHLEN + 1);
1677 strcpy(fontPath, "/C/");
1678 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1682 status = stat(fontPath, &buf);
1699 strncpy(smGD.fontPath, fontPath, MAXPATHLEN);
1701 if(resIndep == True)
1705 * add the auxillary resources onto the root window
1707 RestoreResources(True, "-merge", "-file", smGD.fontPath, NULL);
1710 * Load the resources from the RESOURCE_MANAGER
1711 * property on the root window
1713 if(XGetWindowProperty(smGD.display, RootWindow(smGD.display, 0),
1714 XA_RESOURCE_MANAGER,0L,
1715 100000000L,False,XA_STRING,&actualType,
1716 &actualFormat,&nitems,&leftover,
1717 (unsigned char**) &data) == Success)
1719 smBase = XrmGetStringDatabase((char *)data);
1728 PrintError(DtError, GETMESSAGE(16, 6, "Invalid display/language independent resource file. No display/language independent resources will be restored."));
1729 SM_FREE((char *)data);
1735 * Get the new fontlist from the resources and
1736 * Put it on the application shell. Then add
1737 * the auxillary resources into the display struct
1739 resRet = XrmGetResource(smBase, "*fontList", "*FontList",
1740 &resValRet, &fontResourceReturn);
1743 XtSetArg(uiArgs[i], XmNdefaultFontList,
1744 (XmFontList) fontResourceReturn.addr);i++;
1745 XtSetValues(smGD.topLevelWid, uiArgs, i);
1748 * Overwrite the old font preferences, otherwise,
1749 * they'll come back to haunt us if the user logs in again
1750 * under the current language. We need to get the font
1751 * resources which have just been loaded, then overlay
1752 * them onto the _DT_SM_PREFERENCES root property to make
1753 * sure we get them back when we login again.
1755 for (i = 0; i < XtNumber(fonttype); i++)
1757 resRet = XrmGetResource(smBase, fonttype[i], fontclass[i],
1758 &resValRet, &fontResourceReturn);
1762 (char *)SM_MALLOC(fontResourceReturn.size + 30);
1763 bzero(resdata, fontResourceReturn.size + 30);
1764 strcat(resdata, fonttype[i]);
1765 strcat(resdata, ": ");
1766 strcat(resdata, fontResourceReturn.addr);
1767 strcat(resdata, "\n");
1768 _DtAddResString(smGD.display, resdata, _DT_ATR_PREFS);
1773 XrmMergeDatabases(smBase, &(smGD.display->db));
1774 SM_FREE((char *)data);
1778 SM_FREE((char*) fontPath);
1785 /*************************************<->*************************************
1792 * Reads through the client file and restores its contents. A client file
1793 * consists of hints for the workspace manager, actual client commands, and
1794 * remote execution commands. All commands are processed accordingly.
1795 * If this is the first DT 3.0 session for a DT 2.0 user then we will
1796 * also launch the helpviewer. If this is the first DT 3.0 session for a
1797 * DT 2.0 user then we will also run convertVS.sh to change all
1798 * occurances of /usr/bin/X11/hpterm to .../dt/bin/hpterm,
1799 * /usr/bin/X11/xterm to .../dt/bin/xterm and
1800 * /usr/bin/X11/xload to .../dt/bin/xload.
1811 * Any information read from the client file will be mucked with during
1812 * processing, and should not try to be mucked with again.
1814 * WARNING: This routine closes cfileP - not the calling routine
1815 * DOUBLE-WARNING: This routine starts the window manager
1817 *************************************<->***********************************/
1819 RestoreClients( void )
1821 unsigned char *lineP, *string;
1822 char *pch, *dispPtr = NULL;
1823 char *dispEnv, *dispSav, *dispEnvHelpview, *dispSavHelpview;
1824 unsigned char *hostPtr=NULL, *cmdPtr=NULL, *hintPtr = NULL;
1825 unsigned char *remoteDisplay;
1828 unsigned char tmpChar[35];
1829 int screenNum = 0, i, j, chlen, numClientsExec;
1830 int numRemoteDone = 0;
1832 Boolean clientsDone = False, wmHandshake = False, cmdInvInit = False;
1833 XClientMessageEvent smToWmMessage;
1836 * These variables are needed to buffer up the commands and then
1837 * execute them (also buffer up hints then put them on the root window
1839 unsigned char *hintsBuf[MAX_SCREENS_SAVED];
1840 unsigned char *cmdBuf[MAX_SCREENS_SAVED];
1841 unsigned int maxHintsSize[MAX_SCREENS_SAVED];
1842 unsigned int actHintsSize[MAX_SCREENS_SAVED];
1843 unsigned int numHints[MAX_SCREENS_SAVED];
1844 unsigned int maxCmdSize[MAX_SCREENS_SAVED];
1845 unsigned int actCmdSize[MAX_SCREENS_SAVED];
1846 unsigned int numCmd[MAX_SCREENS_SAVED];
1847 unsigned int maxRemoteSize[MAX_SCREENS_SAVED];
1850 * Initialize the buffers and their sizes to null and 0. Because of
1851 * all possible combinations - buffers aren't malloc'd until they're
1854 for(i = 0;i<smGD.numSavedScreens;i++)
1858 remoteBuf[i] = NULL;
1859 maxHintsSize[i] = 0;
1860 actHintsSize[i] = 0;
1865 maxRemoteSize[i] = 0;
1866 actRemoteSize[i] = 0;
1870 * Save the contents of the DISPLAY environment variable so that it
1871 * can be restored when we're through
1873 dispEnv = getenv(DISPLAY_NAME);
1876 dispSav = (char *) SM_MALLOC(((strlen(dispEnv) +
1877 strlen(DISPLAY_NAME_EQUAL)) * sizeof(char) + 1));
1878 sprintf(dispSav, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
1886 displayName = strdup(smGD.display->display_name);
1887 remoteDisplay = (unsigned char *)
1888 SM_MALLOC(sizeof(unsigned char) * (strlen(displayName) + 101));
1891 * Create the display name for locally executing clients
1917 * Create the display name for remotely executing clients.
1918 * These two may or may not be the same
1920 DtGetShortHostname((char *)remoteDisplay, 100);
1923 * Add the display qualifications to the host name
1924 * screen is added at execution time
1926 strcat((char *)remoteDisplay, (char *)dispPtr);
1929 * Intern the atom needed to put the hints on the root window
1930 * This has to be done here because InitProtocol has not been called yet
1932 XaWmDtHints = XInternAtom(smGD.display, _XA_DT_SESSION_HINTS, False);
1934 while(GetNextLine() != NULL)
1937 string = GetSmartString(&lineP);
1938 if( string != NULL && !strcmp((char *)string, "dtsmcmd"))
1940 while((string = GetSmartString(&lineP)) != NULL )
1942 if(!strcmp((char *)string, "-host"))
1945 * Extract a host pointer - host pointers
1946 * only exist on remote executions
1948 string = GetSmartString(&lineP);
1953 if(!strcmp((char *)string, "-cmd"))
1956 * Extract the command pointer from the
1959 string = GetSmartString(&lineP);
1964 if(!strcmp((char *)string, "-screen"))
1967 * Extract the screen number from the command
1969 string = GetSmartString(&lineP);
1970 screenNum = atoi((char *)string);
1975 if(!strcmp((char *)string, "-hints"))
1978 * Extract the hints string
1980 string = GetSmartString(&lineP);
1989 * Now put our information in buffers and reinitialize the pointers
1993 if(FillHintBuf(hintPtr, hintsBuf, maxHintsSize,
1994 actHintsSize, screenNum, numHints) != 0)
1997 * Free all malloc'd buffers and exit
1999 for(i = 0;i < smGD.numSavedScreens;i++)
2001 if(actHintsSize[i] > 0)
2003 SM_FREE((char *) hintsBuf[i]);
2005 if(actCmdSize[i] > 0)
2007 SM_FREE((char *) cmdBuf[i]);
2009 if(actRemoteSize[i] > 0)
2011 SM_FREE((char *) remoteBuf[i]);
2020 if((cmdPtr != NULL) && (hostPtr == NULL))
2022 if(FillCmdBuf(cmdPtr, cmdBuf, maxCmdSize,
2023 actCmdSize,screenNum, &numCmd[screenNum]) != 0)
2026 * Free all malloc'd buffers and exit
2028 for(i = 0;i < smGD.numSavedScreens;i++)
2030 if(actHintsSize[i] > 0)
2032 SM_FREE((char *) hintsBuf[i]);
2034 if(actCmdSize[i] > 0)
2036 SM_FREE((char *) cmdBuf[i]);
2038 if(actRemoteSize[i] > 0)
2040 SM_FREE((char *) remoteBuf[i]);
2049 if((cmdPtr != NULL) && (hostPtr != NULL))
2051 if(FillRemoteBuf(cmdPtr, hostPtr, remoteDisplay,
2052 remoteBuf, maxRemoteSize,
2053 actRemoteSize, screenNum) != 0)
2056 * Free all malloc'd buffers and exit
2058 for(i = 0;i < smGD.numSavedScreens;i++)
2060 if(actHintsSize[i] > 0)
2062 SM_FREE((char *) hintsBuf[i]);
2064 if(actCmdSize[i] > 0)
2066 SM_FREE((char *) cmdBuf[i]);
2068 if(actRemoteSize[i] > 0)
2070 SM_FREE((char *) remoteBuf[i]);
2080 screenNum = XDefaultScreen(smGD.display);
2085 * All done with file so close it off and set descriptor to NULL -
2086 * This is done so that parsing routines can be used with a buffer later
2092 * Now execute all the buffers, put all hints on the root windows
2093 * Do all remote executions
2095 for(i = 0;i < smGD.numSavedScreens;i++)
2098 * Put the root window property on each root window
2100 if(actHintsSize[i] > 0)
2103 * Append number of hints to front of buffer
2105 sprintf((char *)tmpChar, "%d", numHints[i]);
2106 strncpy((char *)hintsBuf[i], (char *)tmpChar,
2107 strlen((char *)tmpChar));
2108 XChangeProperty(smGD.display, RootWindow(smGD.display, i),
2109 XaWmDtHints, XA_STRING, 8, PropModeReplace,
2110 hintsBuf[i], actHintsSize[i]);
2111 SM_FREE((char *) hintsBuf[i]);
2112 XSync(smGD.display, 0);
2120 * Now exec on the local clients - we're doing contention management
2121 * to make sure the system doesn't get swamped
2125 while((actCmdSize[i] == 0) && (i < smGD.numSavedScreens))
2130 envVal = SM_MALLOC(BUFSIZ);
2131 if(i >= smGD.numSavedScreens)
2137 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2145 * Keep forking one client after the other until the
2146 * memory utilization gets beyond the threshold -
2147 * (but only if the capability exists) Then go to
2148 * window manager handshaking
2150 #ifdef DEBUG_CONT_MANAGEMENT
2151 if(smRes.contManagement & SM_CM_SYSTEM)
2153 fprintf(stderr, "SM_CM_SYSTEM flag set in smRes.contManagement\n");
2155 if(smRes.contManagement & SM_CM_HANDSHAKE)
2157 fprintf(stderr, "SM_CM_HANDSHAKE flag set in smRes.contManagement\n");
2159 #endif /* DEBUG_CONT */
2161 if((smRes.contManagement & SM_CM_SYSTEM) &&
2162 ((GetMemoryUtilization() != MEM_NOT_AVAILABLE) &&
2163 (clientsDone == False)))
2165 while((GetMemoryUtilization() == MEM_NOT_FULL) &&
2166 (clientsDone == False))
2170 CreateExecString((char *) lineP);
2171 if(smExecArray[0] != NULL)
2173 (void) StartClient(smExecArray[0], (char **)smExecArray, NULL,
2174 NULL, NULL, False, False, -1);
2179 * When all the clients have been exec'd for this screen
2182 if(numClientsExec >= numCmd[i])
2184 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2185 envVal, displayName);
2192 * After we've checked memory utilization - finish up
2193 * by handshaking with the worksapce manager - if it's there
2195 if(clientsDone == False)
2197 if((smGD.dtwmRunning) && (smRes.contManagement & SM_CM_HANDSHAKE))
2200 * Get the window id of the workspace manager and tell it
2201 * to start messaging
2203 _DtGetMwmWindow(smGD.display, RootWindow(smGD.display, 0),
2205 smToWmMessage.type = ClientMessage;
2206 smToWmMessage.window = dtwmWin;
2207 smToWmMessage.message_type = XaSmWmProtocol;
2208 smToWmMessage.format = 32;
2209 smToWmMessage.data.l[0] = XaSmStartAckWindow;
2210 smToWmMessage.data.l[1] = CurrentTime;
2211 if (XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2212 (XEvent *) &smToWmMessage) != 0)
2215 XSync(smGD.display, 0);
2221 * Start a client - and wait for the workspace manager to
2222 * map a window to start a new client
2224 while(clientsDone == False)
2228 CreateExecString((char *) lineP);
2229 if(smExecArray[0] != NULL)
2231 (void) StartClient(smExecArray[0], smExecArray,
2232 NULL, NULL, NULL, False, False, -1);
2236 * If we're handshaking with the workspace manager
2237 * wait for the client to be mapped before starting
2240 if(wmHandshake == True)
2248 * When all the clients have been exec'd for this screen
2251 if(numClientsExec >= numCmd[i])
2253 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2254 envVal, displayName);
2259 if(wmHandshake == True)
2262 * If we are handshaking - tell the workspace manager to
2265 smToWmMessage.type = ClientMessage;
2266 smToWmMessage.window = dtwmWin;
2267 smToWmMessage.message_type = XaSmWmProtocol;
2268 smToWmMessage.format = 32;
2269 smToWmMessage.data.l[0] = XaSmStopAckWindow;
2270 smToWmMessage.data.l[0] = CurrentTime;
2271 XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2272 (XEvent *) &smToWmMessage);
2277 for(i = 0;i < smGD.numSavedScreens;i++)
2279 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2285 * Send out all the remote execution commands for the screen to
2286 * the command invoker. On failure - do a remsh instead
2288 if(actRemoteSize[i] > 0)
2291 * Initialize the command invoker - if not done
2293 if(cmdInvInit == False)
2295 _DtInitializeCommandInvoker(smGD.display,
2303 * Set up the display environment variable so that the
2304 * application comes back to the right screen
2306 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2310 parseP = remoteBuf[i];
2311 while(numRemoteExecs > 0 && GetNextLine() != NULL)
2314 * Get the host and the command and send them off
2315 * On failure of the command invoker do a remsh
2318 string = GetSmartString(&lineP);
2320 string = GetSmartString(&lineP);
2323 remoteBufPtr[numRemoteDone].cmdPtr = cmdPtr;
2324 remoteBufPtr[numRemoteDone].hostPtr = hostPtr;
2326 _DtCommandInvokerExecute(DtSTART_SESSION, NULL, NULL, NULL,
2327 "-", (char *) hostPtr, (char *) cmdPtr,
2328 RemoteRequestSucceeded, NULL,
2329 RemoteRequestFailed,
2330 &remoteBufPtr[numRemoteDone]);
2334 * If there is no more room in the remote client
2335 * array - quit exec'ing remote clients
2337 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2339 PrintError(DtError, GETMESSAGE(16, 5, "You have reached the maximum allowed number of remote clients. No further remote clients will be restored."));
2349 * Now return the display variable back to the display that was
2350 * originally opened (the default display)
2358 FixEnvironmentData();
2363 } /* END OF FUNCTION RestoreClients */
2367 /*************************************<->*************************************
2369 * StartEtc ( exiting )
2374 * Call the StartClient routine to fork and exec either the sessionetc file
2375 * (if exiting==False) or the sessionexit file (if exiting==True).
2387 *************************************<->***********************************/
2389 StartEtc( Boolean exiting )
2396 execArray[0] = smGD.exitPath;
2397 execArray[1] = smExitFile;
2399 execArray[0] = smGD.etcPath;
2400 execArray[1] = smEtcFile;
2402 execArray[2] = '\0';
2404 if ((status=stat(execArray[0], &buf)) != -1)
2406 StartClient(execArray[0], execArray, NULL, NULL, NULL, False, False, -1);
2411 /*************************************<->*************************************
2418 * Returns the next line from an fopened configuration file or a newline-
2419 * embedded configuration string.
2424 * cfileP = (global) file pointer to fopened configuration file or NULL
2425 * line = (global) line buffer
2426 * linec = (global) line count
2427 * parseP = (global) parse string pointer if cfileP == NULL
2432 * line = (global) next line
2433 * linec = (global) line count incremented
2434 * parseP = (global) parse string pointer incremented
2435 * Return = line or NULL if file or string is exhausted.
2440 * If there are more than MAXLINE characters on a line in the file cfileP the
2441 * excess are truncated.
2442 * Assumes the line buffer is long enough for any parse string line.
2443 * Code stolen from dtmwm
2445 *************************************<->***********************************/
2446 static unsigned char *
2449 unsigned char *string;
2455 /* read fopened file */
2457 string = (unsigned char *) fgets((char *)line, fileSize, cfileP);
2459 else if ((parseP != NULL) && (*parseP != 0))
2460 /* read parse string */
2464 while ((*parseP != 0) &&
2465 ((chlen = mblen ((char *) parseP, MB_CUR_MAX)) > 0) &&
2467 /* copy all but NULL and newlines to line buffer */
2471 *(string++) = *(parseP++);
2475 while ((*parseP != NULL) && (*parseP != '\n'))
2476 /* copy all but NULL and newlines to line buffer */
2478 *(string++) = *(parseP++);
2482 if (*parseP == '\n')
2495 } /* END OF FUNCTION GetNextLine */
2499 /*************************************<->*************************************
2501 * PeekAhead (currentChar, currentLev)
2506 * Returns a new level value if this is a new nesting level of quoted string
2507 * Otherwise it returns a zero
2512 * currentChar = current position in the string
2513 * currentLev = current level of nesting
2518 * Returns either a new level of nesting or zero if the character is copied in
2524 *************************************<->***********************************/
2527 unsigned char *currentChar,
2528 unsigned int currentLev )
2530 Boolean done = False;
2531 unsigned int tmpLev = 1;
2535 while (((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) &&
2536 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
2541 if(((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
2542 ((*currentChar == '"') || (*currentChar == '\\')))
2545 if(*currentChar == '"')
2556 while((*currentChar != NULL) && (done == False) &&
2557 ((*currentChar == '"') || (*currentChar == '\\')))
2560 if((*currentChar != NULL) &&
2561 ((*currentChar == '"') || (*currentChar == '\\')))
2564 if(*currentChar == '"')
2574 #endif /*MULTIBYTE*/
2577 * Figure out if this is truly a new level of nesting - else ignore it
2578 * This section probably could do some error checking and return -1
2579 * If so, change type of routine from unsigned int to int
2593 /*************************************<->*************************************
2595 * GetSmartString (linePP)
2600 * Returns the next quoted or whitespace-terminated nonquoted string in the
2602 * Additional functionality added to GetString in that anything in a
2603 * quoted string is considered sacred and nothing will be stripped from
2604 * the middle of a quoted string.
2609 * linePP = pointer to current line buffer pointer.
2614 * linePP = pointer to revised line buffer pointer.
2620 * May alter the line buffer contents.
2621 * Handles quoted strings and characters, removing trailing whitespace from
2623 * Returns NULL string if the line is empty or is a comment.
2624 * Code stolen from dtmwm.
2626 *************************************<->***********************************/
2628 static unsigned char *
2630 unsigned char **linePP )
2632 unsigned char *lineP = *linePP;
2633 unsigned char *endP;
2634 unsigned char *curP;
2635 unsigned char *lnwsP;
2636 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
2640 /* get rid of leading white space */
2641 ScanWhitespace (&lineP);
2644 * Return NULL if line is empty, whitespace, or begins with a comment.
2646 if((chlen = mblen ((char *) lineP, MB_CUR_MAX)) < 1)
2652 if ((chlen == 1) && (*lineP == '"'))
2655 quoteLevel[level] = 1;
2657 * Start beyond double quote and find the end of the quoted string.
2658 * '\' quotes the next character - but is not stripped out.
2659 * Otherwise, matching double quote or NULL terminates the string.
2661 * We use lnwsP to point to the last non-whitespace character in the
2662 * quoted string. When we have found the end of the quoted string,
2663 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2664 * This removes any trailing whitespace without overwriting the
2665 * matching quote, needed later. If the quoted string was all
2666 * whitespace, then this will write a NULL at the beginning of the
2667 * string that will be returned -- OK.
2669 lnwsP = lineP++; /* lnwsP points to first '"' */
2670 curP = endP = lineP; /* other pointers point beyond */
2672 while ((*endP = *curP) &&
2673 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2674 ((chlen > 1) || (*curP != '"')))
2675 /* Haven't found matching quote yet.
2676 * First byte of next character has been copied to endP.
2680 if ((chlen == 1) && (*endP == '\\') &&
2681 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2684 * Check to see if this is a quoted quote - if it is
2685 * strip off a level - if not - it's sacred leave it alone
2687 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2690 if(quoteLevel[level] >= checkLev)
2692 if (level > 0) level--;
2694 else if (level < MAX_QUOTE_DEPTH)
2697 quoteLevel[level] = checkLev;
2700 for(i = 0;i < (checkLev - 2);i++)
2702 *endP++ = *curP++;curP++;
2709 /* Singlebyte character: character copy finished. */
2711 if (isspace (*endP))
2712 /* whitespace character: leave lnwsP unchanged. */
2717 /* non-whitespace character: point lnwsP to it. */
2723 /* Multibyte (nonwhitespace) character: point lnwsP to it.
2724 * Finish character byte copy.
2737 /* get rid of leading white space */
2738 ScanWhitespace (&lineP);
2740 /* Return NULL if line is empty, or whitespace */
2750 quoteLevel[level] = 1;
2752 * Start beyond double quote and find the end of the quoted string.
2753 * '\' quotes the next character.
2754 * Otherwise, matching double quote or NULL terminates the string.
2756 * We use lnwsP to point to the last non-whitespace character in the
2757 * quoted string. When we have found the end of the quoted string,
2758 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2759 * This removes any trailing whitespace without overwriting the
2760 * matching quote, needed later. If the quoted string was all
2761 * whitespace, then this will write a NULL at the beginning of the
2762 * string that will be returned -- OK.
2764 lnwsP = lineP++; /* lnwsP points to first '"' */
2765 curP = endP = lineP; /* other pointers point beyond */
2767 while ((*endP = *curP) && (*endP != '"'))
2768 /* haven't found matching quote yet */
2770 /* point curP to next character */
2772 if ((*endP == '\\') && (*curP != NULL))
2773 /* shift quoted nonNULL character down and curP ahead */
2776 * Check to see if this is a quoted quote - if it is
2777 * strip off a level - if not - it's sacred leave it alone
2779 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2782 if(quoteLevel[level] >= checkLev)
2784 if (level > 0) level--;
2786 else if (level < MAX_QUOTE_DEPTH)
2789 quoteLevel[level] = checkLev;
2792 for(i = 0;i < (checkLev - 2);i++)
2794 *endP++ = *curP++;curP++;
2800 if (isspace (*endP))
2801 /* whitespace character: leave lnwsP unchanged. */
2806 /* non-whitespace character: point lnwsP to it. */
2814 * Found matching quote or NULL.
2815 * NULL out any trailing whitespace.
2826 /* Unquoted string */
2829 * Find the end of the nonquoted string.
2830 * '\' quotes the next character.
2831 * Otherwise, whitespace, NULL, terminates the string.
2833 curP = endP = lineP;
2836 while ((*endP = *curP) &&
2837 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2838 ((chlen > 1) || (!isspace (*curP))))
2839 /* Haven't found whitespace yet.
2840 * First byte of next character has been copied to endP.
2844 if ((chlen == 1) && (*endP == '\\') &&
2845 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2847 * copy first byte of quoted nonNULL character down.
2848 * point curP to next byte
2855 /* Multibyte character: finish character copy. */
2864 while ((*endP = *curP) && !isspace (*endP))
2866 /* point curP to next character */
2868 if ((*endP == '\\') && (*curP != NULL))
2869 /* shift quoted nonNULL character down and curP ahead */
2879 * Two cases for *endP:
2881 * matching quote -> write NULL over char and point beyond
2882 * NULL -> point to NULL
2887 *endP = 0; /* write NULL over terminator */
2888 *linePP = ++curP; /* point beyond terminator */
2894 return ((unsigned char *)lineP);
2896 } /* END OF FUNCTION GetString */
2901 /*************************************<->*************************************
2903 * ScanWhitespace(linePP)
2908 * Scan the string, skipping over all white space characters.
2913 * linePP = nonNULL pointer to current line buffer pointer
2918 * linePP = nonNULL pointer to revised line buffer pointer
2923 * Assumes linePP is nonNULL
2924 * Code Stolen from dtmwm
2926 *************************************<->***********************************/
2929 unsigned char **linePP )
2932 while (*linePP && (mblen ((char *) *linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
2934 while (*linePP && isspace (**linePP))
2940 } /* END OF FUNCTION ScanWhitespace */
2944 /*************************************<->*************************************
2946 * FillHintBuf(newHint, hintBuf, maxSize, actSize, screen, numHints)
2951 * Put the new hint into the hint buffer. Each hint is separated by a
2957 * newHint = hint to add to the buffer
2958 * hintBuf = an array of buffers - one for each screen
2959 * maxSize = array of buffers of the current malloced size of each hintBuf
2960 * actSize = array of space currently used by each hintBuf
2961 * screen = screen number for this hint
2962 * numHints = array of the number of hints for each screen
2963 * smGD.numSavedScreens = (global) checked to make sure this hint should be
2968 * hintBuf[screen] = updated hint buf for this screen (newHint added)
2969 * maxSize[screen] = enlarged if not big enough or malloced if not done before
2970 * actSize[screen] = updated size of the hints buffer
2971 * numHints[screen] = updated by 1 if this hint is added
2977 *************************************<->***********************************/
2980 unsigned char *newHint,
2981 unsigned char **hintBuf,
2982 unsigned int *maxSize,
2983 unsigned int *actSize,
2984 unsigned int screen,
2985 unsigned int *numHints)
2987 static int hintBufSize = 5000;
2990 * If the screen that this hint was meant for is not in the current
2991 * set of available screens, don't save it
2993 if(screen >= smGD.numSavedScreens)
2999 * Check to see if this buffer has been malloc'd before - if it hasn't
3000 * malloc it. If it has - check to make sure it's big enough to hold the
3003 if(maxSize[screen] == 0)
3005 hintBuf[screen] = (unsigned char *) SM_MALLOC(hintBufSize * sizeof(char));
3006 if(hintBuf[screen] == NULL)
3008 actSize[screen] = 0;
3009 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3012 maxSize[screen] = hintBufSize * sizeof(char);
3015 * Now reserve 4 bytes for the length
3017 strcpy((char *)hintBuf[screen], " \n");
3021 if((actSize[screen] + strlen((char *)newHint) + 2) >= maxSize[screen])
3023 hintBuf[screen] = (unsigned char *)
3024 SM_REALLOC((char *) hintBuf[screen],
3028 if(hintBuf[screen] == NULL)
3030 actSize[screen] = 0;
3031 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3034 maxSize[screen] = maxSize[screen] + (hintBufSize * sizeof(char));
3039 * add the new hint AFTER the last newline
3041 strcat((char *)hintBuf[screen], (char *)newHint);
3042 strcat((char *)hintBuf[screen], "\n");
3043 actSize[screen] = strlen((char *)hintBuf[screen]);
3044 numHints[screen] += 1;
3051 /*************************************<->*************************************
3053 * FillCmdBuf(newCmd, cmdBuf, maxSize, actSize, screen)
3058 * Put a new command into the command buffer. The command buffer is just
3059 * one big long string of stuff to be executed.
3064 * newCmd = command to add to the buffer
3065 * cmdBuf = an array of buffers - one for each screen
3066 * maxSize = array of buffers of the current malloced size of each cmdBuf
3067 * actSize = array of space currently used by each cmdBuf
3068 * screen = screen number for this command
3069 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3074 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3075 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3076 * actSize[screen] = updated size of the command buffer
3082 *************************************<->***********************************/
3085 unsigned char *newCmd,
3086 unsigned char **cmdBuf,
3087 unsigned int *maxSize,
3088 unsigned int *actSize,
3089 unsigned int screen,
3090 unsigned int *numCmd )
3092 static int cmdBufSize = 5000;
3095 * If the screen that this command was meant for is not in the current
3096 * set of available screens, don't save it
3098 if(screen >= smGD.numSavedScreens)
3104 * Check to see if this buffer has been malloc'd before - if it hasn't
3105 * malloc it. If it has - check to make sure it's big enough to hold the
3108 if(maxSize[screen] == 0)
3110 cmdBuf[screen] = (unsigned char *) SM_MALLOC(cmdBufSize * sizeof(char));
3111 if(cmdBuf[screen] == NULL)
3113 actSize[screen] = 0;
3114 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3117 maxSize[screen] = cmdBufSize * sizeof(char);
3121 if((actSize[screen] + strlen((char *)newCmd)) >= maxSize[screen])
3123 cmdBuf[screen] = (unsigned char *) SM_REALLOC((char *)cmdBuf[screen],
3127 if(cmdBuf[screen] == NULL)
3129 actSize[screen] = 0;
3130 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3133 maxSize[screen] = maxSize[screen] + (cmdBufSize * sizeof(char));
3137 if(actSize[screen] == 0)
3139 strcpy((char *)cmdBuf[screen], (char *)newCmd);
3143 strcat((char *)cmdBuf[screen], (char *)newCmd);
3146 *numCmd = *numCmd + 1;
3147 strcat((char *)cmdBuf[screen], "\n");
3148 actSize[screen] = strlen((char *)cmdBuf[screen]);
3155 /*************************************<->*************************************
3157 * FillRemoteBuf(newCmd, hostName, displayName, remoteBuf,
3158 * maxSize, actSize, screen)
3163 * Put a new command into the remote execution buffer. The command buffer is
3164 * just one big long string of stuff to be executed.
3169 * newCmd = command to add to the buffer
3170 * hostName = host where command is to be executed from
3171 * displayName = display where host is to be executed to
3172 * remoteBuf = an array of buffers - one for each screen
3173 * maxSize = array of buffers of the current malloced size of each cmdBuf
3174 * actSize = array of space currently used by each cmdBuf
3175 * screen = screen number for this command
3176 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3181 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3182 * in remote format (host name and display name)
3183 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3184 * actSize[screen] = updated size of the command buffer
3190 *************************************<->***********************************/
3193 unsigned char *newCmd,
3194 unsigned char *hostName,
3195 unsigned char *displayName,
3196 unsigned char *remoteBuf[] ,
3197 unsigned int *maxSize ,
3198 unsigned int *actSize ,
3199 unsigned int screen )
3201 unsigned char *string;
3202 static int remoteBufSize = 5000;
3205 * If the screen that this command was meant for is not in the current
3206 * set of available screens, don't save it
3208 if(screen >= smGD.numSavedScreens)
3214 * Check to see if this buffer has been malloc'd before - if it hasn't
3215 * malloc it. If it has - check to make sure it's big enough to hold the
3218 if(maxSize[screen] == 0)
3220 remoteBuf[screen] = (unsigned char *)
3221 SM_MALLOC(remoteBufSize * sizeof(char));
3222 if(remoteBuf[screen] == NULL)
3224 actSize[screen] = 0;
3225 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3228 maxSize[screen] = remoteBufSize * sizeof(char);
3232 if((actSize[screen] + strlen((char *)newCmd) +
3233 strlen((char *)hostName) +
3234 strlen((char *)displayName) +
3235 strlen("-display ") + 5) >= maxSize[screen])
3237 remoteBuf[screen] = (unsigned char *)
3238 SM_REALLOC((char *)remoteBuf[screen],
3240 (remoteBufSize * sizeof(char)));
3241 if(remoteBuf[screen] == NULL)
3243 actSize[screen] = 0;
3244 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3247 maxSize[screen] = maxSize[screen] + (remoteBufSize * sizeof(char));
3251 if(actSize[screen] == 0)
3254 * If the buffer is empty fill it with the initial contents
3256 strcpy((char *)remoteBuf[screen], (char *)hostName);
3257 strcat((char *)remoteBuf[screen], " ");
3262 * if this buffer is not emtpy
3263 * add the new command BEFORE the last null terminator
3264 * Commands for remote executions are separated by newlines
3266 strcat((char *)remoteBuf[screen], "\n");
3267 strcat((char *)remoteBuf[screen], (char *)hostName);
3271 * Copy the command in - quote it
3273 strcat((char *)remoteBuf[screen], " \"");
3274 string = GetSmartString(&newCmd);
3275 strcat((char *)remoteBuf[screen], (char *)string);
3276 strcat((char *)remoteBuf[screen], " ");
3279 * Once display name has been put in place - concatenate the
3280 * rest of the command
3282 while((string = GetSmartString(&newCmd)) != NULL )
3284 strcat((char *)remoteBuf[screen], " ");
3285 strcat((char *)remoteBuf[screen], (char *)string);
3289 * Now close off the command with a quote
3291 strcat((char *)remoteBuf[screen], "\"");
3293 actSize[screen] = strlen((char *)remoteBuf[screen]);
3296 * Bump the remote command counter
3304 /*************************************<->*************************************
3306 * CreateExecString(execString)
3311 * Create a string that can be fed to a fork and exec by breaking it up
3312 * into argc and argv
3317 * execString = whole command
3321 * smExecArray = global modified to contain pointers to argc and argv
3327 *************************************<->***********************************/
3335 static int iSizeArgv = ARG_AMT;
3340 if (smExecArray == NULL)
3342 smExecArray = (char **) XtMalloc (ARG_AMT * sizeof(char *));
3344 string = (char *) GetSmartString((unsigned char **) &execString);
3345 while(string != NULL)
3347 smExecArray[argc] = string;
3349 if (argc >= iSizeArgv)
3351 iSizeArgv += ARG_AMT;
3352 smExecArray = (char **)
3353 XtRealloc ((char *)smExecArray, (iSizeArgv * sizeof(char *)));
3355 string = (char *) GetSmartString((unsigned char **) &execString);
3359 * If the last string is a background character
3364 if(!strcmp((char *)smExecArray[argc - 1], "&"))
3366 smExecArray[argc - 1] = '\0';
3370 smExecArray[argc] = '\0';
3372 } /* END OF FUNCTION CreateExecString */
3376 * SetTemporaryDisplay - does a putenv of the current value of the
3377 * DISPLAY environment variable but with the given screen number.
3383 SetTemporaryDisplay (
3386 static char * tmpDisplay = NULL;
3387 static int lastScreen = -1;
3390 if (screenNum == -1)
3393 if (!savedDisplay) {
3396 if ((dispEnv = getenv (DISPLAY_NAME)) == NULL)
3398 savedDisplay = XtMalloc (strlen (DISPLAY_NAME_EQUAL) +
3399 strlen (dispEnv) + 2);
3402 sprintf (savedDisplay, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
3405 if (lastScreen == screenNum && tmpDisplay != NULL) {
3406 putenv (tmpDisplay);
3409 lastScreen = screenNum;
3414 tmpDisplay = XtMalloc (strlen (savedDisplay) + 4);
3417 strcpy (tmpDisplay, savedDisplay);
3420 if (pch = strrchr (tmpDisplay, ':')) {
3423 if (pch2 = strchr (pch, '.'))
3425 pch3 = XtMalloc (strlen (tmpDisplay) + 4);
3428 sprintf (pch3, "%s.%d", tmpDisplay, screenNum);
3429 strcpy (tmpDisplay, pch3);
3430 XtFree ((char *) pch3);
3432 putenv (tmpDisplay);
3438 * RestoreDisplay - does a putenv of the global variable savedDisplay
3444 if (screenNum != -1 && savedDisplay)
3445 putenv (savedDisplay);
3449 /*************************************<->*************************************
3451 * StartClient - calls StartLocalClient or StartRemoteClient depending
3452 * on the value of hostName.
3456 * Starts a local or remote application
3460 * program = execArray[0]
3461 * execArray = command to fork and exec
3462 * hostName = the name of the host where program should be executed
3463 * cwd = directory to chdir to before doing the exec
3464 * envp = the envrironment variables to add to the child processes env
3465 * checkCwd = if True and cwd is NULL, a message will be logged; if
3466 * False, cwd will not be checked and the cwd will be set to $HOME
3467 * useIgnoreEnvironmentResource = if True, the variables listed in the
3468 * IgnoreEnvironment resource will be removed from 'environ' before
3469 * execArray is exec'd
3470 * screen = if set to -1, it will be ignored; otherwise, the screen
3471 * number will be used to define DISPLAY for the duration of this
3472 * function - DISPLAY will be reset before the function returns.
3476 * Returns True if the command is successfully executed; False otherwise.
3480 * localHost - is modified
3482 *************************************<->***********************************/
3491 Boolean useIgnoreEnvironmentResource,
3494 static char * defaultCwd = NULL;
3495 Boolean cwdNull = False;
3496 Boolean startStatus;
3498 SetTemporaryDisplay (screen);
3500 if (!ignoreEnvPtr && useIgnoreEnvironmentResource) {
3501 if (smRes.ignoreEnvironment)
3502 ignoreEnvPtr = _DtVectorizeInPlace (
3503 smRes.ignoreEnvironment, ',');
3508 char *tstr = getenv("HOME");
3511 int slen = strlen(tstr) + 1;
3512 defaultCwd = XtCalloc(1, slen);
3513 snprintf(defaultCwd, slen, "%s", tstr);
3516 defaultCwd = getcwd (NULL, MAXPATHLEN + 1);
3518 (void) gethostname (localHost, MAXHOSTNAMELEN);
3526 if (!hostName || (_DtIsSameHost (localHost, hostName)))
3527 startStatus = StartLocalClient (program, execArray,
3528 cwd, envp, checkCwd,
3529 useIgnoreEnvironmentResource);
3531 startStatus = StartRemoteClient (program, execArray, hostName,
3533 useIgnoreEnvironmentResource);
3535 RestoreDisplay (screen);
3537 return (startStatus);
3540 /*************************************<->*************************************
3546 * Starts a local application.
3549 * Returns True if the command is successfully executed; False otherwise.
3551 *************************************<->***********************************/
3559 Boolean useIgnoreEnvironmentResource)
3563 char clientMessage[MAXPATHLEN + 30];
3564 char **tmpEnv, **ppchar;
3567 * Fork and exec the client process
3569 clientFork = vfork();
3572 * If the fork fails - Send out an error and return
3576 PrintErrnoError(DtError, smNLS.cantForkClientString);
3581 * Fork succeeded - now do the exec
3585 SetSIGPIPEToDefault ();
3588 * Log a warning if the given cwd is not valid
3592 if ((chdir (cwd)) == -1)
3596 tmpCwd = getcwd (NULL, MAXPATHLEN + 1);
3598 LogCWDMessage (cwd, program, tmpCwd);
3603 * Add envp to the client's environ if the variable
3604 * is not in the ignoreEnvironment list
3606 if (useIgnoreEnvironmentResource && envp) {
3609 tmpEnv = RemoveEnvironmentVars (envp);
3613 for (ppchar = tmpEnv; ppchar && *ppchar; ppchar++)
3614 putenv (strdup (*ppchar));
3619 * Set the gid of the process back from bin
3622 setregid(smGD.runningGID, smGD.runningGID);
3624 setgid(smGD.runningGID);
3625 setegid(smGD.runningGID);
3629 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3631 #if defined(CSRG_BASED)
3635 #endif /* CSRG_BASED */
3637 MarkFileDescriptors (3, F_SETFD, 1);
3639 execStatus = execvp(program, execArray);
3642 sprintf(clientMessage, ((char *)GETMESSAGE(16, 3, "Unable to exec %s.")), execArray[0]);
3643 PrintErrnoError(DtError, clientMessage);
3651 /*************************************<->*************************************
3657 * Starts a remote application.
3660 * Returns True if the command is successfully executed; False otherwise.
3662 *************************************<->***********************************/
3670 Boolean useIgnoreEnvironmentResource)
3673 SPC_Channel_Ptr channel;
3675 char errorMessage[1024];
3677 static Boolean cmdInvokerInitialized = False;
3678 char ** tmpEnv = envp;
3680 ioMode = SPCIO_NOIO | SPCIO_FORCE_CONTEXT;
3682 if (!cmdInvokerInitialized) {
3683 _DtInitializeCommandInvoker(smGD.display,
3687 cmdInvokerInitialized = True;
3690 (void) strcpy (errorMessage, "");
3692 channel = (SPC_Channel_Ptr) _DtSPCOpen (hostName, ioMode, errorMessage);
3693 if (channel == SPC_ERROR) {
3694 message = strdup ((char *) GETMESSAGE (40, 13,
3695 "The following application cannot be started on host '%s'\nbecause this host cannot be reached from host '%s':\n\n %s"));
3698 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3699 message, hostName, localHost, program);
3705 netfile = tt_host_file_netfile (hostName, cwd);
3706 if (tt_pointer_error (netfile) != TT_OK) {
3708 message = strdup ((char *) GETMESSAGE (40, 14,
3709 "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]"));
3712 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3713 message, program, hostName, cwd,
3714 tt_status_message (tt_pointer_error (
3722 * Add envp to the client's environ if the variable
3723 * is not in the ignoreEnvironment list
3725 if (useIgnoreEnvironmentResource && ignoreEnvPtr && envp)
3726 tmpEnv = RemoveEnvironmentVars (envp);
3728 if ((_DtSPCSpawn (program, netfile, execArray, tmpEnv, channel,
3729 hostName, NULL, cwd, errorMessage)) == SPC_ERROR) {
3730 DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMessage);
3732 XtFree ((char *) tmpEnv);
3738 XtFree ((char *) tmpEnv);
3744 /*************************************<->*************************************
3751 * Fork and exec the default window manager
3764 *************************************<->***********************************/
3773 * These lines were added to support the builtin
3778 char *displayName,*dpy;
3780 hostName = SM_MALLOC(MAXPATHSM);
3781 displayName = SM_MALLOC(MAXPATHSM);
3783 if( gethostname(hostName, (sizeof(hostName) - 1) ) == 0)
3785 hostName[MAXPATHSM - 1] = '\0';
3786 dpy = getenv(DISPLAY_NAME);
3787 homeDir = getenv("HOME");
3790 strcpy(displayName, dpy);
3791 dpy = strchr(displayName, ':');
3796 sprintf(tmpExecWmFile, "%s/.dt/bin/%s/%s/dtwm", homeDir,
3797 hostName,displayName);
3798 if (access(tmpExecWmFile,X_OK) != 0)
3800 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3804 localWmLaunched = True;
3805 if (!smGD.userSetWaitWmTimeout)
3807 smRes.waitWmTimeout = 60000;
3813 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3818 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3822 SM_FREE(displayName);
3824 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3825 * End of lines were added to support the builtin
3829 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3834 * Fork and exec the client process
3836 clientFork = vfork();
3839 * If the fork fails - Send out an error and return
3843 PrintErrnoError(DtError, smNLS.cantForkClientString);
3848 * Fork succeeded - now do the exec
3852 SetSIGPIPEToDefault ();
3856 * Set the gid of the process back from bin
3859 setregid(smGD.runningGID, smGD.runningGID);
3861 setgid(smGD.runningGID);
3862 setegid(smGD.runningGID);
3865 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3867 #if defined(CSRG_BASED)
3871 #endif /* CSRG_BASED */
3873 MarkFileDescriptors (3, F_SETFD, 1);
3876 * These lines were added to support the builtin
3879 * execStatus = execlp(".../dt/bin/dtwm", "dtwm", (char *) 0);
3882 execStatus = execlp(tmpExecWmFile, "dtwm", (char *) 0);
3885 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3886 * End of lines were added to support the builtin
3890 if(execStatus != 0 && (!localWmLaunched))
3892 PrintErrnoError(DtError, GETMESSAGE(16, 4, "Unable to exec process /usr/dt/bin/dtwm. No window manager will be started."));
3899 /*************************************<->*************************************
3906 * Fork a copy of ourselves and kill the parent off so that scripts starting
3907 * up the session manager can continue.
3919 *************************************<->***********************************/
3927 * Fork and exec the client process
3929 clientFork = fork();
3932 * If the fork fails - We have to exit so that the rest of the
3933 * script can continue
3937 PrintErrnoError(DtError, smNLS.cantForkClientString);
3942 * Fork succeeded - now kill the parent
3950 * Disassociate from parent
3952 #if defined(CSRG_BASED)
3956 #endif /* CSRG_BASED */
3961 /*************************************<->*************************************
3968 * This routine waits for the window manager to start. It uses a
3969 * resource (waitWmTimeout) with a dynamic default to determine how many
3970 * seconds to wait for WM start and then starts clients.
3975 * appContext = application context for the window
3976 * window = window id for the
3985 *************************************<->***********************************/
3990 XtIntervalId wmTimerId;
3992 XtAddEventHandler(smGD.topLevelWid,
3995 (XtEventHandler)HandleWMClientMessage,
3999 * Set a timer which stops the block on waiting for the
4000 * window manager to start
4003 wmTimerId = XtAppAddTimeOut(smGD.appCon,
4004 smRes.waitWmTimeout,
4005 WaitWMTimeout, NULL);
4007 while((smGD.dtwmRunning == False) && (wmTimeout == False))
4009 XtAppProcessEvent(smGD.appCon, XtIMAll);
4012 XtRemoveTimeOut(wmTimerId);
4013 XtRemoveEventHandler(smGD.topLevelWid,
4016 (XtEventHandler)HandleWMClientMessage,
4020 } /* END OF FUNCTION WaitForWM */
4023 /*************************************<->*************************************
4030 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
4031 * for the window manager to get started.
4040 * wmTimeout = (global) flag that stops the loop
4045 *************************************<->***********************************/
4048 XtPointer client_data,
4053 } /* END OF FUNCTION WaitWMTimeout */
4057 /*************************************<->*************************************
4059 * HandleWMClientMessage
4064 * This is the event handler registered to receive the client message
4065 * from dtwm when dtwm is ready for business
4068 *************************************<->***********************************/
4070 HandleWMClientMessage( Widget smWidget,
4074 if (event->type == ClientMessage)
4076 ProcessClientMessage(event);
4079 } /* END OF FUNCTION HandleWMClientMessage */
4084 /*************************************<->*************************************
4086 * FixEnvironmentData
4091 * If DISPLAY variable exists in the environment - remove it
4100 * wmTimeout = (global) flag that stops the loop
4105 *************************************<->***********************************/
4107 FixEnvironmentData( void )
4111 extern char **environ; /* MODIFIED - DISPLAY is remove if found. */
4113 for (i=0, ppchar = environ; *ppchar; ppchar++, i++)
4115 if ((strncmp (*ppchar, DISPLAY_NAME_EQUAL, strlen(DISPLAY_NAME_EQUAL))) == 0)
4118 * Change the DISPLAY environment variable.
4120 for (; *ppchar; ppchar++, i++)
4122 environ[i]=environ[i+1];
4131 /*************************************<->*************************************
4138 * After one screen is finished - set up the info for the next
4143 * cmdBuf - Buffer that holds all the invocation information
4144 * screen - Pointer to the screen number that we're currently working on
4145 * env - used to set up the environment for changing the display var
4146 * displayName - name of the current display
4150 * cmdBuf - old buffers are freed
4151 * screen - updated to point to the new screen info
4152 * done - tells whether the clients are done being exec'd
4153 * linec - *GLOBAL* sets line being read from
4159 *************************************<->***********************************/
4161 ResetScreenInfo(unsigned char **cmdBuf,
4163 unsigned int *cmdSize,
4168 SM_FREE((char *) cmdBuf[*screen]);
4170 while((cmdSize[*screen] == 0) && (*screen < smGD.numSavedScreens))
4175 if(*screen >= smGD.numSavedScreens)
4181 sprintf((char *)env,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, *screen);
4185 parseP = cmdBuf[*screen];
4191 /*************************************<->*************************************
4193 * RemoteRequestFailed ()
4198 * If a request to the command invoker fails, this callback will be called.
4199 * It will then try to execute the command by performing a remsh on it.
4212 *************************************<->***********************************/
4214 RemoteRequestFailed(char *message,
4217 static char *cmdBuf = NULL;
4218 static char *tmpCmdBuf = NULL;
4219 char *errorString = NULL;
4222 static int cmdBufSize = 0;
4225 RemoteReq *tmpReq = (RemoteReq *) client_data;
4228 * If the memory for the buffer has not been malloced - do so
4232 cmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4235 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4238 cmdBufSize = 200 + 1;
4240 tmpCmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4241 if(tmpCmdBuf == NULL)
4243 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4248 * Copy in the host and command field and execute the command
4251 tmpSize = (strlen(REMOTE_CMD_STRING) +
4252 strlen((char *) tmpReq->hostPtr) +
4253 strlen((char *) tmpReq->cmdPtr) + 1);
4255 if(tmpSize >= cmdBufSize)
4257 cmdBuf = SM_REALLOC(cmdBuf, (tmpSize) * sizeof(char));
4261 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4265 cmdBufSize = tmpSize;
4267 if(tmpCmdBuf != NULL)
4269 tmpCmdBuf = SM_REALLOC(tmpCmdBuf, (tmpSize) * sizeof(char));
4270 if(tmpCmdBuf == NULL)
4272 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4277 sprintf(cmdBuf, REMOTE_CMD_STRING, tmpReq->hostPtr, tmpReq->cmdPtr);
4280 * save cmdBuf for error message, cmdBuf is changed
4281 * by CreateExecString
4283 if (tmpCmdBuf != NULL)
4285 strcpy(tmpCmdBuf,cmdBuf);
4288 CreateExecString(cmdBuf);
4289 if(smExecArray[0] != NULL)
4291 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
4292 NULL, False, False, -1);
4294 if (tmpCmdBuf != NULL)
4296 tmpString = GETMESSAGE(16, 8,
4297 "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");
4300 (char *)SM_MALLOC((strlen(tmpString) +
4301 strlen((char *)tmpReq->hostPtr) +
4302 strlen((char *)tmpReq->cmdPtr) +
4303 strlen(tmpCmdBuf) + 1 ) *
4306 if(errorString == NULL)
4308 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4312 sprintf(errorString, tmpString, tmpReq->hostPtr,
4313 tmpReq->cmdPtr, tmpCmdBuf );
4314 PrintError(DtError, errorString);
4315 SM_FREE(errorString);
4320 * Now check to make sure that this isn't the last remote request.
4321 * If so, free the data
4325 if(numRemoteExecs == 0)
4327 for(i = 0;i < smGD.numSavedScreens;i++)
4329 if(actRemoteSize[i] > 0)
4331 SM_FREE((char *) remoteBuf[i]);
4341 /*************************************<->*************************************
4343 * RemoteRequestSucceeded ()
4348 * If a request to the command invoker succeeds, this callback will be called.
4349 * It decrements the remote execution counter, and frees the info if
4350 * remote executions are finished
4363 *************************************<->***********************************/
4365 RemoteRequestSucceeded(char *message,
4372 if(numRemoteExecs == 0)
4374 for(i = 0;i < smGD.numSavedScreens;i++)
4376 if(actRemoteSize[i] > 0)
4378 SM_FREE((char *) remoteBuf[i]);
4384 /**************************************************************************
4388 **************************************************************************/
4392 char * databaseName)
4395 XSMPClientDBRecPtr pXSMPRec;
4396 ProxyClientDBRecPtr pProxyRec;
4401 if ((inputDB = OpenInputClientDB (databaseName,
4403 &smXSMP.dbSessionId)) == NULL) {
4404 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogError, 1);
4408 if (!smXSMP.dbVersion) {
4409 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 2);
4410 smXSMP.dbVersion = SM_VENDOR_NAME;
4413 if (!smXSMP.dbSessionId) {
4414 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 3);
4415 smXSMP.dbSessionId = SM_RELEASE_NAME;
4419 * First start the XSMP clients
4423 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4426 if (!CheckRequiredProperties (pXSMPRec, databaseName)) {
4427 FreeXSMPClientDBRec (pXSMPRec);
4431 if (StartXSMPClient (pXSMPRec, databaseName)) {
4433 XSMPClientDBRecPtr tmpRecPtr;
4435 pXSMPRec->next = NULL;
4437 if (!smXSMP.xsmpDbList) {
4438 smXSMP.xsmpDbList = pXSMPRec;
4443 * Find the end of the list
4445 for (tmpRecPtr = smXSMP.xsmpDbList;
4446 tmpRecPtr && tmpRecPtr->next != NULL;
4447 tmpRecPtr = tmpRecPtr->next);
4449 tmpRecPtr->next = pXSMPRec;
4452 FreeXSMPClientDBRec (pXSMPRec);
4456 * Now start the Proxy clients
4458 for (i = 0; ; i++) {
4460 if ((pProxyRec = GetProxyClientDBRec (inputDB)) == NULL)
4463 if (!CheckRequiredFields (pProxyRec, databaseName, i)) {
4464 FreeProxyClientDBRec (pProxyRec);
4468 (void) StartProxyClient (pProxyRec);
4470 FreeProxyClientDBRec (pProxyRec);
4473 (void) CloseClientDB (inputDB, False);
4481 XSMPClientDBRecPtr pDbRec,
4482 char * databaseName)
4484 return (StartClient (pDbRec->restartCommand[0],
4485 pDbRec->restartCommand,
4488 pDbRec->environment,
4491 pDbRec->screenNum));
4497 ProxyClientDBRecPtr pDbRec)
4499 return (StartClient (pDbRec->command[0],
4506 pDbRec->screenNum));
4511 ExecuteCommandProperty (
4513 ClientRecPtr pClientRec)
4516 char ** envp = NULL;
4518 PropertyRecPtr pPropRec;
4522 if ((pPropRec = GetPropertyRec (pClientRec, commandName)) == NULL)
4525 argv = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4530 for (i = 0; i < pPropRec->prop.num_vals; i++)
4531 argv[i] = pPropRec->prop.vals[i].value;
4532 argv[pPropRec->prop.num_vals] = NULL;
4534 cwd = GetArrayPropertyValue (pClientRec, SmCurrentDirectory);
4537 if ((pPropRec = GetPropertyRec (pClientRec, SmEnvironment)) != NULL) {
4538 envp = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4543 for (i = 0; i < pPropRec->prop.num_vals; i++)
4544 envp[i] = pPropRec->prop.vals[i].value;
4545 envp[pPropRec->prop.num_vals] = NULL;
4548 retValue = StartClient (argv[0], argv,
4549 pClientRec->clientHost,
4552 pClientRec->screenNum);
4554 XtFree ((char *) argv);
4556 XtFree ((char *) envp);
4562 /*************************************<->*************************************
4564 * ExecuteDiscardCommands -
4566 * Description: Executes all of the DiscardCommand properties in the
4567 * given client database
4571 *************************************<->***********************************/
4573 ExecuteDiscardCommands (
4577 XSMPClientDBRecPtr pXSMPRec;
4578 char * version = NULL;
4582 if ((inputDB = OpenInputClientDB (db, &version, &id )) == NULL) {
4583 str = strdup ((char *) GETMESSAGE (40, 26,
4584 "The following client database cannot be opened:\n\n %s\n\nThe 'DiscardCommand' properties cannot be run."));
4587 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str, db);
4593 XtFree ((char *) version);
4595 XtFree ((char *) id);
4598 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4601 if (!pXSMPRec->discardCommand)
4604 if (!StartClient (pXSMPRec->discardCommand[0],
4605 pXSMPRec->discardCommand,
4606 pXSMPRec->clientHost,
4608 pXSMPRec->environment,
4611 pXSMPRec->screenNum)) {
4612 str = strdup ((char *) GETMESSAGE (40, 27,
4613 "An attempt to execute the 'DiscardCommand' property for\napplication '%s' failed."));
4616 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
4621 FreeXSMPClientDBRec (pXSMPRec);
4624 (void) CloseClientDB (inputDB, False);
4629 CheckRequiredProperties (
4630 XSMPClientDBRecPtr pDbRec,
4631 char * databaseName)
4633 Boolean propsOK = True;
4635 if (!pDbRec->program) {
4636 LogMissingPropertyMessage (pDbRec, SmProgram,
4637 databaseName, DtMsgLogError);
4641 if (!pDbRec->restartCommand) {
4642 LogMissingPropertyMessage (pDbRec, SmRestartCommand,
4643 databaseName, DtMsgLogError);
4652 CheckRequiredFields (
4653 ProxyClientDBRecPtr pDbRec,
4654 char * databaseName,
4659 if (!pDbRec->command) {
4661 message = strdup ((char *) GETMESSAGE (40, 11,
4662 "The required resource '%s' is missing for client '%d'\nin the file '%s'."));
4667 DtMsgLogMessage (smGD.programName, DtMsgLogError, message,
4668 SmProgram, clientNum, databaseName);
4680 LogXSMPOpenDatabaseFailure (
4681 char * databaseName,
4682 DtMsgLogType msgType,
4685 char * message = NULL;
4690 case 1: data = databaseName;
4692 message = strdup ((char *) GETMESSAGE (40, msgNum,
4693 "The following session database could not be opened:\n\n '%s'"));
4696 case 2: data = versionStr;
4698 message = strdup ((char *) GETMESSAGE (40, msgNum,
4699 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4702 case 3: data = dtsessionIDStr;
4704 message = strdup ((char *) GETMESSAGE (40, msgNum,
4705 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4713 DtMsgLogMessage (smGD.programName, msgType, message, data);
4715 DtMsgLogMessage (smGD.programName, msgType, message,
4716 data, databaseName);
4723 LogMissingPropertyMessage (
4724 XSMPClientDBRecPtr pDbRec,
4726 char * databaseName,
4727 DtMsgLogType msgType)
4731 message = strdup ((char *) GETMESSAGE (40, 10,
4732 "The required property '%s' is missing for client\n\n %s\n\nin the file '%s'."));
4737 DtMsgLogMessage (smGD.programName, msgType, message,
4738 propName, pDbRec->clientId, databaseName);
4752 message = strdup ((char *) GETMESSAGE (40, 12,
4753 "The directory '%s'\nis not available for application '%s'.\n\nThe following directory will be used:\n\n %s"));
4758 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, message,
4759 badDir, appName, goodDir);
4766 char ** RemoveEnvironmentVars (
4770 char ** retEnv = NULL;
4771 char **ppchar, **ppchar2;
4778 for (count = 0, ppchar = envp; ppchar && *ppchar; count++, ppchar++) ;
4780 retEnv = (char **) XtMalloc ((count + 1) * sizeof (char *));
4784 if (!ignoreEnvPtr) {
4785 for (count = 0, ppchar = envp; ppchar && *ppchar;
4786 count++, ppchar++) {
4787 retEnv[count] = *ppchar;
4789 retEnv[count] = NULL;
4794 for (count = 0, ppchar = envp; ppchar && *ppchar; ppchar++) {
4798 for (ppchar2 = ignoreEnvPtr; ppchar2 && *ppchar2; ppchar2++) {
4800 if ((!strncmp (*ppchar, *ppchar2, strlen (*ppchar2))) &&
4801 (((*ppchar)[strlen(*ppchar2)]) == '=')) {
4807 retEnv[count] = *ppchar;
4811 retEnv[count] = NULL;
4817 * MarkFileDescriptors - mark file descriptiors start_fd through open_max
4818 * with the given "cmd" and "data".
4820 * The code for calculating open_max was taken from DtSvc/DtUtil1/CmdMain.c
4823 MarkFileDescriptors (
4831 open_max = sysconf(_SC_OPEN_MAX);
4833 if (open_max == -1) {
4838 open_max = FOPEN_MAX;
4840 open_max = FD_SETSIZE;
4842 #endif /* _SUN_OS */
4845 for (i = start_fd; i < open_max; i++)
4846 (void) fcntl (i, cmd, data);